"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MagicApi = void 0;
const decorator_1 = require("@midwayjs/decorator");
const constant_1 = require("../constant");
const core_1 = require("./core");
const definition_1 = require("./definition");
const joi_router_1 = require("./joi.router");
const magic_interceptor_1 = require("./magic.interceptor");
const magic_swagger_1 = require("./magic.swagger");
const utils_1 = require("./utils");
let MagicApi = class MagicApi {
    constructor() {
        this.type = 'api';
        /**
         * 路由
         * @private
         */
        this.magicRouter = new joi_router_1.default();
        /**
         * 路由中间件
         * @private
         */
        this.routerMiddleware = this.magicRouter.middleware();
    }
    async init(reInit = false) {
        if (reInit) {
            this.logger.info('重新初始化MagicRouter');
            this.magicRouter.routes = [];
            this.magicRouter.router.stack = [];
        }
        else {
            this.logger.info('初始化MagicRouter');
        }
        if ((0, utils_1.isNotBlank)(this.magicConfig.prefix)) {
            this.magicRouter.prefix(this.magicConfig.prefix);
        }
        const resources = await this.magicResourceService.findByType(constant_1.RESOURCE_TYPE.Api);
        for (const resource of resources) {
            await this.add(resource);
        }
    }
    /**
     * 拼接完整路径
     * @param path 路由路径
     * @private
     */
    joinFullPath(path) {
        return `${(0, utils_1.isNotBlank)(this.magicConfig.prefix) ? this.magicConfig.prefix : ''}${path}`;
    }
    /**
     * 路由中间件
     */
    middleware() {
        return this.routerMiddleware;
    }
    /**
     *添加路由
     * @param resource
     */
    async add(resource) {
        await this.removeById(resource.id);
        const options = {};
        const apiOptions = resource.definition.options;
        (apiOptions || []).filter(a => {
            options[a.key] = a.value;
        });
        const apiDefinition = (0, definition_1.ApiDefinition)(resource.script);
        const spec = {
            options,
            pre: this.magicInterceptor.middleware(),
            id: resource.id,
            meta: {
                swagger: {
                    summary: resource.fileName,
                    tags: ['Magic接口服务'],
                    // deprecated: true,
                    security: [
                        {
                            ApiKeyAuth: [],
                        },
                    ],
                },
            },
            validate: (0, definition_1.generateValidate)(resource),
            output: {
                200: (0, definition_1.generateOutput)(resource),
            },
            method: resource.method,
            path: await this.magicResourceService.getMappingPath(resource),
            handler: async (ctx) => await (0, definition_1.ApiHandler)(ctx, apiDefinition),
        };
        const path = spec.path;
        const method = spec.method;
        this.logger.info('注册路由:[%s %s]', method, this.joinFullPath(path));
        this.magicRouter.addRouter(spec);
    }
    /**
     * 删除路由
     * @param id 资源id
     */
    async removeById(id) {
        const specIndex = this.magicRouter.routes.findIndex(r => r.id === id);
        if (specIndex != -1) {
            const { path, method } = this.magicRouter.routes[specIndex];
            const fullPath = this.joinFullPath(path);
            const { route, pathAndMethod } = this.magicRouter.router.match(fullPath, method.toUpperCase());
            this.magicRouter.routes.splice(specIndex, 1);
            if (route && pathAndMethod != null && pathAndMethod.length > 0) {
                const stack = this.magicRouter.router.stack;
                const index = stack.findIndex(layer => layer === pathAndMethod[0]);
                if (index >= 0) {
                    stack.splice(index, 1);
                    this.logger.info('删除路由成功:[%s %s]', method, fullPath);
                }
            }
        }
    }
    /**
     * 获取路由定义
     * @param method 请求方式
     * @param path 请求路径
     */
    getRouterSpec(method, path) {
        const routeSpecs = this.magicRouter.routes.filter(r => r.method === method.toUpperCase() &&
            r.path === path.replace(this.magicConfig.prefix, ''));
        return routeSpecs[0];
    }
    /**
     * 生成定义
     */
    generateSpec() {
        const generator = new magic_swagger_1.default();
        generator.addJoiRouter(this.magicRouter);
        const properties = {
            message: {
                type: 'string',
                description: '返回消息',
            },
            code: {
                type: 'string',
                description: '异常状态码',
            },
            success: {
                type: 'boolean',
                description: '操作是否成功',
            },
        };
        return generator.generateSpec({
            tags: [
                {
                    name: 'Magic接口服务',
                    description: '由MagicNode定义的接口',
                },
            ],
            info: {
                ...this.magicConfig.swagger,
            },
            basePath: '/',
            securityDefinitions: {
                ApiKeyAuth: {
                    type: 'apiKey',
                    in: 'header',
                    name: 'Authorization',
                },
            },
        }, {
            defaultResponses: {
                200: {
                    description: '正常返回',
                    schema: {
                        type: 'object',
                        properties: {
                            ...properties,
                            data: {
                                type: 'object',
                                description: '数据',
                            },
                        },
                    },
                },
                400: {
                    description: '参数错误',
                    schema: {
                        type: 'object',
                        properties,
                    },
                },
                401: {
                    description: '授权失败',
                    schema: {
                        type: 'object',
                        properties,
                    },
                },
                403: {
                    description: '权限不足',
                    schema: {
                        type: 'object',
                        properties,
                    },
                },
                500: {
                    description: '服务器异常',
                    schema: {
                        type: 'object',
                        properties,
                    },
                },
            },
        });
    }
};
__decorate([
    (0, decorator_1.Logger)('magic'),
    __metadata("design:type", Object)
], MagicApi.prototype, "logger", void 0);
__decorate([
    (0, decorator_1.Config)('magic'),
    __metadata("design:type", Object)
], MagicApi.prototype, "magicConfig", void 0);
__decorate([
    (0, decorator_1.Inject)(),
    __metadata("design:type", core_1.MagicResourceService)
], MagicApi.prototype, "magicResourceService", void 0);
__decorate([
    (0, decorator_1.Inject)(),
    __metadata("design:type", magic_interceptor_1.MagicInterceptor)
], MagicApi.prototype, "magicInterceptor", void 0);
MagicApi = __decorate([
    (0, decorator_1.Provide)(),
    (0, decorator_1.Scope)(decorator_1.ScopeEnum.Singleton)
], MagicApi);
exports.MagicApi = MagicApi;
//# sourceMappingURL=magic.api.js.map