nope-js-node
Version:
NoPE Runtime for Nodejs. For Browser-Support please use nope-browser
227 lines (226 loc) • 10.5 kB
JavaScript
;
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2021-11-11 11:36:37
* @modify date 2021-11-11 11:36:37
* @desc [description]
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseFunctionToOpenAPI = exports.parseModuleToOpenAPI = void 0;
const promises_1 = require("fs/promises");
const handlebars = require("handlebars");
const path_1 = require("path");
const fileMethods_1 = require("../../helpers/fileMethods");
const objectMethods_1 = require("../../helpers/objectMethods");
const stringMethods_1 = require("../../helpers/stringMethods");
/**
* Helper function to merge the Parameters into 1 description.
* @param elements
*/
function _unifySchema(elements, options) {
const ret = {
type: "object",
properties: {},
required: [],
};
for (const item of elements) {
if (options.sharedDefinitions) {
item.schema.definitions = undefined;
item.schema.$schema = undefined;
}
// Assign the Schema
ret.properties[item.name] = item.schema;
// If the Element is Optional,
if (!item.optional) {
ret.required.push(item.name);
}
}
return ret;
}
/**
* Function, to parse a description to an Open-API Element.
* @param description
* @param options
*/
async function parseModuleToOpenAPI(description, options) {
const _description = (0, objectMethods_1.deepClone)(description);
// load the Template.
const template = await (0, promises_1.readFile)((0, path_1.join)(process.cwd(), "lib", "parsers", "open-api", "templates", "method." + options.mode + ".handlebars"), {
encoding: "utf-8",
});
// Renderfuncting
const renderAPI = handlebars.compile(template);
await (0, fileMethods_1.createPath)((0, path_1.join)(options.outputDir));
// Now iterate over the Methods of the Module and find parsable Methods.
for (const [idx, method] of _description.methods.entries()) {
// Test if the Method contains some functions in the input / Output:
const parsedInputs = JSON.stringify(method.schema.inputs);
const parsedOutput = JSON.stringify(method.schema.outputs);
if (!parsedInputs.includes('"function"') &&
!parsedOutput.includes('"function"')) {
// The Method should be parseable.
// 1. Specify the Mode (No Params = GET, else POST)
method.mode = method.schema.inputs.length > 0 ? "POST" : "GET";
method.required = method.schema.inputs
.filter((param) => {
return !param.optional;
})
.map((param) => param.name);
method.hasInput = method.schema.inputs.length > 0;
// Now adapt the Schema of the Method.
// Iterate over the Inputs, add a Description if not provided
// And determine whehter the Parameters are required or not.
method.schema.inputs = method.schema.inputs.map((param) => {
// Provide a Description. (If not provided)
param.description = param.description || "Not provided";
if (options.sharedDefinitions) {
param.schema.definitions = undefined;
param.schema.$schema = undefined;
}
// Parse the Schema in here.
param.parsedSchema = JSON.stringify(param.schema);
return param;
});
// Make shure the Return type isnt an array
method.schema.outputs = Array.isArray(method.schema.outputs)
? _unifySchema(method.schema.outputs, options)
: method.schema.outputs;
if (options.sharedDefinitions) {
method.schema.outputs.definitions = undefined;
method.schema.outputs.$schema = undefined;
}
// Add an Description to the result.
method.resultDescription =
method.schema.outputs.description || "Not Provided";
// And add a Schema for the Return type.
method.parsedOutput = JSON.stringify(method.schema.outputs);
method.parsedInput = JSON.stringify(_unifySchema(method.schema.inputs, options));
method.hasInput = method.schema.inputs.length > 0;
method.tag = description.name;
// Determine the Filename.
const fileDir = (0, path_1.join)(options.outputDir, _description.name, "{instance}", "methods");
const fileName = (0, path_1.join)(fileDir, method.id + "." + options.mode);
// Determine the Import Pathes.
const imports = [
{
dir: (0, path_1.join)(process.cwd(), "lib", "types", "nope"),
fileName: "nopeDispatcher.interface",
name: "pathOfDispatcher",
},
{
dir: (0, path_1.join)(process.cwd(), "lib", "helpers"),
fileName: "dispatcherPathes",
name: "pathOfHelper",
},
];
for (const imp of imports) {
const relativDir = (0, path_1.relative)(fileDir, imp.dir);
method[imp.name] = (0, path_1.join)((0, fileMethods_1.convertPathToOsPath)(relativDir), (0, fileMethods_1.convertPathToOsPath)(imp.fileName));
}
// Write down the Schema:
await (0, fileMethods_1.createFile)(
// Generate the Path.
fileName, renderAPI(method));
if (options.logger) {
options.logger.info("Generated -> " + fileName);
}
}
else if (options.logger) {
options.logger.warn('parser can not convert: "' +
description.name +
"." +
method.id +
'". The Function contains functions as parameters');
}
}
}
exports.parseModuleToOpenAPI = parseModuleToOpenAPI;
/**
* Function, to parse a description to an Open-API Element.
* @param description
* @param options
*/
async function parseFunctionToOpenAPI(description, options) {
const _description = (0, objectMethods_1.deepClone)(description);
// load the Template.
const template = await (0, promises_1.readFile)((0, path_1.join)(process.cwd(), "lib", "parsers", "open-api", "templates", "function." + options.mode + ".handlebars"), {
encoding: "utf-8",
});
// Renderfuncting
const renderAPI = handlebars.compile(template);
await (0, fileMethods_1.createPath)((0, path_1.join)(options.outputDir));
// Now iterate over the Methods of the Module and find parsable Methods.
// Test if the Method contains some functions in the input / Output:
const parsedInputs = JSON.stringify(_description.schema.inputs);
const parsedOutput = JSON.stringify(_description.schema.outputs);
if (!parsedInputs.includes('"function"') &&
!parsedOutput.includes('"function"')) {
// The Method should be parseable.
// 1. Specify the Mode (No Params = GET, else POST)
_description.mode =
_description.schema.inputs.length > 0 ? "POST" : "GET";
// Now adapt the Schema of the Method.
// Iterate over the Inputs, add a Description if not provided
// And determine whehter the Parameters are required or not.
_description.schema.inputs = _description.schema.inputs.map((param) => {
// Provide a Description. (If not provided)
param.description = param.description || "Not provided";
if (options.sharedDefinitions) {
param.schema.definitions = undefined;
param.schema.$schema = undefined;
}
// Parse the Schema in here.
param.parsedSchema = JSON.stringify(param.schema);
return param;
});
// Make shure the Return type isnt an array
_description.schema.outputs = Array.isArray(_description.schema.outputs)
? _unifySchema(_description.schema.outputs, options)
: _description.schema.outputs;
if (options.sharedDefinitions) {
_description.schema.outputs.definitions = undefined;
_description.schema.outputs.$schema = undefined;
}
// Add an Description to the result.
_description.resultDescription =
_description.schema.outputs.description || "Not Provided";
// And add a Schema for the Return type.
_description.parsedOutput = JSON.stringify(_description.schema.outputs);
_description.tag = "generic-services";
_description.parsedInput = JSON.stringify(_unifySchema(_description.schema.inputs, options));
_description.hasInput = _description.schema.inputs.length > 0;
_description.required = _description.schema.inputs
.filter((param) => !param.optional)
.map((param) => param.name);
_description.name = _description.id;
// Determine the Filename.
const fileDir = (0, path_1.join)(options.outputDir, "generic-services");
const fileName = (0, path_1.join)(fileDir, _description.id + "." + options.mode);
// Determine the Import Pathes.
const imports = [
{
dir: (0, path_1.join)(process.cwd(), "lib", "types", "nope"),
fileName: "nopeDispatcher.interface",
name: "pathOfDispatcher",
},
];
for (const imp of imports) {
const relativDir = (0, path_1.relative)(fileDir, imp.dir);
_description[imp.name] = (0, stringMethods_1.replaceAll)((0, path_1.join)(relativDir, imp.fileName), "\\", "/");
}
// Write down the Schema:
await (0, fileMethods_1.createFile)(
// Generate the Path.
fileName, renderAPI(_description));
if (options.logger) {
options.logger.info("Generated -> " + fileName);
}
}
else if (options.logger) {
options.logger.warn('parser can not convert: "' +
_description.id +
'". The Function contains functions as parameters');
}
}
exports.parseFunctionToOpenAPI = parseFunctionToOpenAPI;