"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const path_1 = __importDefault(require("path"));
const core_1 = require("@restlessness/core");
const __1 = require("../");
class Openapi {
    static get openapiJsonPath() {
        return path_1.default.join(core_1.PathResolver.getPrjPath, 'openapi.json');
    }
    static getParameters(fields, allKeys, inValue) {
        const fieldsKeys = Object.keys(fields);
        for (let fieldKey of fieldsKeys) {
            if (fields[fieldKey]._type === 'object') {
                allKeys[fieldKey] = {
                    type: 'object',
                    properties: {},
                };
                Openapi.getParameters(fields[fieldKey].fields, allKeys[fieldKey].properties, inValue);
            }
            else {
                let type = fields[fieldKey]._type;
                if (fields[fieldKey]._type === 'number') {
                    if (fields[fieldKey]._exclusive.integer !== 'undefined') {
                        type = 'integer';
                    }
                    else {
                        type = 'number';
                    }
                }
                allKeys.push({
                    name: fieldKey,
                    type: type,
                    in: inValue,
                });
            }
        }
    }
    static getPropertiesRequestBody(fields, allKeys) {
        const fieldsKeys = Object.keys(fields);
        for (let fieldKey of fieldsKeys) {
            if (fields[fieldKey]._type === 'object') {
                allKeys[fieldKey] = {
                    type: 'object',
                    properties: {},
                };
                Openapi.getPropertiesRequestBody(fields[fieldKey].fields, allKeys[fieldKey].properties);
            }
            else if (fields[fieldKey]._type === 'array') {
                allKeys[fieldKey] = {
                    type: 'array',
                    items: {},
                };
                if (fields[fieldKey]._subType._type === 'object') {
                    allKeys[fieldKey].items = {
                        type: 'object',
                        properties: {},
                    };
                    Openapi.getPropertiesRequestBody(fields[fieldKey]._subType.fields, allKeys[fieldKey].items.properties);
                }
                else {
                    let type = fields[fieldKey]._subType._type;
                    if (fields[fieldKey]._subType._type === 'number') {
                        if (fields[fieldKey]._exclusive.integer !== 'undefined') {
                            type = 'integer';
                        }
                        else {
                            type = 'number';
                        }
                    }
                    allKeys[fieldKey].items = {
                        type: type,
                    };
                }
            }
            else {
                let type = fields[fieldKey]._type;
                if (fields[fieldKey]._type === 'number') {
                    if (fields[fieldKey]._exclusive.integer !== 'undefined') {
                        type = 'integer';
                    }
                    else {
                        type = 'number';
                    }
                }
                allKeys[fieldKey] = {
                    type: type,
                };
            }
        }
    }
    create() {
        return __awaiter(this, void 0, void 0, function* () {
            const endpoints = yield __1.Endpoint.getList();
            const openapi = {
                openapi: '3.0.0',
                servers: [{
                        url: 'http://localhost:4000',
                        description: 'local server',
                    }],
                info: {
                    title: 'RLN Swagger API overview',
                    version: '0.0.1',
                },
                components: {
                    securitySchemes: {
                        JWT: {
                            type: 'apiKey',
                            in: 'header',
                            name: 'authorization',
                        },
                    },
                },
                security: [{
                        JWT: [],
                    }],
                paths: {},
            };
            for (let ep of endpoints) {
                const routeName = ep.route.endpointRoute;
                const routeMethod = ep.method;
                if (!openapi.paths[routeName]) {
                    openapi.paths[routeName] = {};
                }
                openapi.paths[routeName][routeMethod] = {
                    description: `${routeMethod}: ${routeName}`,
                    tags: ['api'],
                    responses: {
                        200: {
                            description: 'Success',
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                    },
                                },
                            },
                        },
                    },
                };
                const folderPath = path_1.default.join(core_1.PathResolver.getDistEndpointsPath, ep.method + '-' + ep.route.folderName);
                const validationsRoutePath = path_1.default.join(folderPath, 'validations');
                try {
                    const validationYUP = require(validationsRoutePath).default();
                    if (validationYUP.payload) {
                        const properties = {};
                        Openapi.getPropertiesRequestBody(validationYUP.payload.fields, properties);
                        openapi.paths[routeName][routeMethod].requestBody = {
                            required: true,
                            content: {
                                'application/json': {
                                    schema: {
                                        type: 'object',
                                        properties: properties,
                                    },
                                },
                            },
                        };
                    }
                    if (validationYUP.pathParameters || validationYUP.queryStringParameters) {
                        const parameters = [];
                        if (validationYUP.pathParameters) {
                            Openapi.getParameters(validationYUP.pathParameters.fields, parameters, 'path');
                        }
                        if (validationYUP.queryStringParameters) {
                            Openapi.getParameters(validationYUP.queryStringParameters.fields, parameters, 'query');
                        }
                        openapi.paths[routeName][routeMethod].parameters = parameters;
                    }
                }
                catch (e) {
                    console.warn(e.message);
                }
            }
            yield Openapi.saveOpenapi(openapi);
        });
    }
    static saveOpenapi(openapi) {
        return __awaiter(this, void 0, void 0, function* () {
            yield fs_1.promises.writeFile(Openapi.openapiJsonPath, JSON.stringify(openapi, null, 2));
        });
    }
}
exports.default = Openapi;
//# sourceMappingURL=index.js.map