Update project

This commit is contained in:
Guilherme Werner 2025-12-16 18:30:32 -03:00
parent ca7f0b65d9
commit 82d19b6305
6 changed files with 112869 additions and 71873 deletions

View file

@ -1,197 +1,236 @@
const pveapi = require('./source')
const yaml = require('js-yaml')
const pveapi = require("./source");
const yaml = require("js-yaml");
const paths = {}
const models = {}
const responses = {}
const tags = []
const paths = {};
const models = {};
const responses = {};
const tags = [];
const capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1)
const capitalizeFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
function generateOpId(method, path){
let operation = path.split("/").map(capitalizeFirst).join('').replace(/[\-\_]/g, '')
function generateOpId(method, path) {
let operation = path
.split("/")
.map(capitalizeFirst)
.join("")
.replace(/[\-\_]/g, "");
operation = operation.replace(/\{[a-z]*\}/g, 'Single')
operation = operation.replace(/\{[a-z]*\}/g, "Single");
const prefix = (() => {
switch (method) {
case "post":
return "create"
return "create";
case "put":
return "update"
return "update";
case "patch":
return "update"
return "update";
default:
return method
return method;
}
})()
})();
return prefix + operation
return prefix + operation;
}
const mapping = require('./mapping')
const mapping = require("./mapping");
function filterSchema(p){
function filterSchema(p) {
const schema = {
type: p.type
type: p.type,
};
if (p.items) schema.items = filterSchema(p.items);
if (p.properties) {
schema.properties = {};
Object.keys(p.properties).forEach(
(name) =>
(schema.properties[name] = filterSchema(p.properties[name]))
);
}
if(p.items)
schema.items = filterSchema(p.items)
if(p.properties){
schema.properties = {}
Object.keys(p.properties).forEach(name => schema.properties[name] = filterSchema(p.properties[name]))
}
return schema
return schema;
}
function buildResponseSchema(source){
const schema = { type: source.type || 'string', description: source.description || '' }
if(schema.type === 'boolean')
schema.type = 'integer'
if(schema.type === 'null')
schema.type = 'string'
if(source.type === 'array' && source.items)
schema.items = buildResponseSchema(source.items)
if(source.type === 'object' && source.properties){
schema.properties = {}
Object.keys(source.properties || {}).forEach(k => {
if(k.endsWith('[n]')){
const nk = k.substr(0, k.length-3)
for(let i=0; i<30; i++){
schema.properties[nk+i] = buildResponseSchema(source.properties[k])
function buildResponseSchema(source) {
const schema = {
type: source.type || "string",
description: source.description || "",
};
if (schema.type === "boolean") schema.type = "integer";
if (schema.type === "integer") schema.type = "int64";
if (schema.type === "null") schema.type = "string";
if (source.type === "array" && source.items)
schema.items = buildResponseSchema(source.items);
if (source.type === "object" && source.properties) {
schema.properties = {};
Object.keys(source.properties || {}).forEach((k) => {
if (k.endsWith("[n]")) {
const nk = k.substr(0, k.length - 3);
for (let i = 0; i < 30; i++) {
schema.properties[nk + i] = buildResponseSchema(
source.properties[k]
);
}
}else{
schema.properties[k] = buildResponseSchema(source.properties[k])
} else {
schema.properties[k] = buildResponseSchema(
source.properties[k]
);
}
})
});
}
return schema
return schema;
}
function parseInfo(path, method, info){
function parseInfo(path, method, info) {
let id = generateOpId(method, path);
id = mapping[id] || id
const sourceProperties = (info.parameters && info.parameters.properties) ? Object.keys(info.parameters.properties).map(k => ({ name: k, ...info.parameters.properties[k] })) : []
id = mapping[id] || id;
const sourceProperties =
info.parameters && info.parameters.properties
? Object.keys(info.parameters.properties).map((k) => ({
name: k,
...info.parameters.properties[k],
}))
: [];
const properties = []
sourceProperties.forEach(p => {
if(p.name.endsWith('[n]')){
const nk = p.name.substr(0, p.name.length-3);
for(let i=0; i<30; i++){
properties.push({ ...JSON.parse(JSON.stringify(p)), name: nk+i })
const properties = [];
sourceProperties.forEach((p) => {
if (p.name.endsWith("[n]")) {
const nk = p.name.substr(0, p.name.length - 3);
for (let i = 0; i < 30; i++) {
properties.push({
...JSON.parse(JSON.stringify(p)),
name: nk + i,
});
}
}else{
properties.push(p)
} else {
properties.push(p);
}
});
const requestName = capitalizeFirst(id) + 'Request'
const responseName = capitalizeFirst(id) + 'Response'
const requestName = capitalizeFirst(id) + "Request";
const responseName = capitalizeFirst(id) + "Response";
paths[path][method] = {
operationId: id,
summary: id,
description: info.description || id,
tags: [path.substr(1).split('/')[0]],
parameters: properties.filter(p => path.includes('{'+p.name+'}')).map(p => ({ name: p.name, in: 'path', required: true, description: p.name, schema: { type: p.type } })),
tags: [path.substr(1).split("/")[0]],
parameters: properties
.filter((p) => path.includes("{" + p.name + "}"))
.map((p) => ({
name: p.name,
in: "path",
required: true,
description: p.name,
schema: { type: p.type },
})),
responses: {
'200': {
$ref: '#/components/responses/'+responseName
}
}
}
200: {
$ref: "#/components/responses/" + responseName,
},
},
};
paths[path][method].tags.forEach(t => {
if(!tags.includes(t))
tags.push(t)
})
paths[path][method].tags.forEach((t) => {
if (!tags.includes(t)) tags.push(t);
});
responses[responseName] = {
description: responseName,
content: {
'application/json': {
"application/json": {
schema: {
type: 'object',
type: "object",
properties: {
errors: {
type: 'array',
type: "array",
items: {
type: 'string'
}
type: "string",
},
},
data: buildResponseSchema(info.returns)
}
}
}
}
}
data: buildResponseSchema(info.returns),
},
},
},
},
};
if(method === 'post' || method === 'put'){
if (method === "post" || method === "put") {
models[requestName] = {
title: requestName,
type: 'object',
title: requestName,
type: "object",
properties: {},
required: []
}
properties.filter(p => !path.includes('{'+p.name+'}')).forEach(p => {
models[requestName].properties[p.name] = filterSchema(p)
if(p.optional !== 1){
models[requestName].required.push(p.name)
}
})
if(models[requestName].required.length < 1)
delete models[requestName].required
required: [],
};
properties
.filter((p) => !path.includes("{" + p.name + "}"))
.forEach((p) => {
models[requestName].properties[p.name] = filterSchema(p);
if (p.optional !== 1) {
models[requestName].required.push(p.name);
}
});
if (models[requestName].required.length < 1)
delete models[requestName].required;
paths[path][method].requestBody = {
content: {
'application/json': {
"application/json": {
schema: {
$ref: '#/components/schemas/'+requestName
}
}
}
}
}else{
properties.filter(p => !path.includes('{'+p.name+'}')).map(p => ({ name: p.name, in: 'query', required: p.optional !== 1, description: p.name, schema: { type: p.type } }))
$ref: "#/components/schemas/" + requestName,
},
},
},
};
} else {
properties
.filter((p) => !path.includes("{" + p.name + "}"))
.map((p) => ({
name: p.name,
in: "query",
required: p.optional !== 1,
description: p.name,
schema: { type: p.type },
}));
}
}
function parsePath(source){
if(source.info && Object.keys(source.info).length > 0){
paths[source.path] = {}
Object.keys(source.info).forEach(method => parseInfo(source.path, method.toLowerCase(), source.info[method]))
function parsePath(source) {
if (source.info && Object.keys(source.info).length > 0) {
paths[source.path] = {};
Object.keys(source.info).forEach((method) =>
parseInfo(source.path, method.toLowerCase(), source.info[method])
);
}
if(source.children)
source.children.forEach(parsePath)
if (source.children) source.children.forEach(parsePath);
}
pveapi.forEach(parsePath)
pveapi.forEach(parsePath);
const spec = {
openapi: '3.0.0',
openapi: "3.0.0",
info: {
title: 'ProxMox VE API',
version: '2.0',
description: 'ProxMox VE API',
title: "ProxMox VE API",
version: "2.0",
description: "ProxMox VE API",
contact: {
name: 'LUMASERV Support Team',
email: 'support@lumaserv.com'
}
name: "LUMASERV Support Team",
email: "support@lumaserv.com",
},
},
servers: [
{
description: 'local',
url: 'https://cluster.local:8006/api2/json'
}
description: "local",
url: "https://cluster.local:8006/api2/json",
},
],
tags: tags.map(t => ({ name: t })),
tags: tags.map((t) => ({ name: t })),
paths: paths,
components: {
schemas: models,
responses: responses
}
}
responses: responses,
},
};
const fs = require('fs')
const fs = require("fs");
fs.writeFileSync('../reference/spec.v2.yaml', yaml.safeDump(spec))
fs.writeFileSync("../reference/spec.v2.yaml", yaml.safeDump(spec));