"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.doDevPostAppStartup = doDevPostAppStartup;
exports.doDelayedDevPostAppStartup = doDelayedDevPostAppStartup;
exports.logRoutesWithoutReturnType = logRoutesWithoutReturnType;
exports.serializeOpenApiSchema = serializeOpenApiSchema;
exports.dumpOpenApiSchema = dumpOpenApiSchema;
const tslib_1 = require("tslib");
function __assignType(fn, args) {
    fn.__type = args;
    return fn;
}
const app_1 = require("@deepkit/app");
const framework_1 = require("@deepkit/framework");
const http_1 = require("@deepkit/http");
const logger_1 = require("@deepkit/logger");
const type_1 = require("@deepkit/type");
const deepkit_openapi_core_1 = require("deepkit-openapi-core");
const promises_1 = require("fs/promises");
const path_1 = tslib_1.__importDefault(require("path"));
const yaml_1 = require("yaml");
const config_1 = require("./config");
const resolver_1 = require("./resolver");
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function doDevPostAppStartup(app) {
    // this hook seems to run before the router even outputs HTTP routes, which means
    // anything we output is hard for the developer to see. thus, we will run dev tooling
    // with a delay.
    setTimeout(() => doDelayedDevPostAppStartup(app), 250);
}
doDevPostAppStartup.__type = [() => app_1.App, 'app', 'doDevPostAppStartup', 'PP"7!2""/#'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function doDelayedDevPostAppStartup(app) {
    const config = (0, resolver_1.getAppConfig)();
    logRoutesWithoutReturnType(app);
    if ((0, config_1.isDevFeatureEnabled)(config.ENABLE_OPENAPI_SCHEMA)) {
        dumpOpenApiSchema(app);
    }
}
doDelayedDevPostAppStartup.__type = [() => app_1.App, 'app', 'doDelayedDevPostAppStartup', 'PP"7!2""/#'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function logRoutesWithoutReturnType(app) {
    const router = app.get(http_1.HttpRouter);
    const logger = app.get(logger_1.Logger);
    const routes = router.getRoutes();
    for (const route of routes) {
        if (!(route.action.module instanceof framework_1.FrameworkModule)) {
            if (!route.returnType || route.returnType.kind === type_1.ReflectionKind.any) {
                let message = `No return type declared for ${route.httpMethods.join(',')} ${route.getFullPath()}`;
                if (route.action.type === 'controller') {
                    message += ` (${route.action.controller.name} -> ${route.action.methodName})`;
                }
                logger.warn(message);
            }
            else if (route.returnType.typeName === 'RedirectResponse' && !route.responses.length) {
                route.responses.push({ statusCode: 302, description: '' });
            }
            else if (route.returnType.typeName === 'EmptyResponse' && !route.responses.length) {
                route.responses.push({ statusCode: 202, description: '' });
            }
        }
    }
}
logRoutesWithoutReturnType.__type = [() => app_1.App, 'app', 'logRoutesWithoutReturnType', 'PP"7!2""/#'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function serializeOpenApiSchema(app) {
    const router = app.get(http_1.HttpRouter);
    const logger = app.get(logger_1.Logger);
    const routes = router.getRoutes().filter(__assignType(r => !r.getFullPath().startsWith('/_devconsole'), ['r', '', 'P"2!"/"']));
    const doc = new deepkit_openapi_core_1.OpenAPIDocument(routes, logger, { contentTypes: ['application/json'] });
    return doc.serializeDocument();
}
serializeOpenApiSchema.__type = [() => app_1.App, 'app', 'serializeOpenApiSchema', 'PP"7!2""/#'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function dumpOpenApiSchema(app) {
    const logger = app.get(logger_1.Logger);
    try {
        const result = serializeOpenApiSchema(app);
        const yaml = (0, yaml_1.stringify)(result, {
            aliasDuplicateObjects: false
        });
        const yamlPath = path_1.default.join(process.cwd(), 'openapi.yaml');
        await (0, promises_1.writeFile)(yamlPath, yaml);
        logger.info(`OpenAPI schema written to: ${yamlPath}`);
    }
    catch (err) {
        logger.error(`Failed to write OpenAPI schema`, err);
    }
}
dumpOpenApiSchema.__type = [() => app_1.App, 'app', 'dumpOpenApiSchema', 'PP"7!2""/#'];
//# sourceMappingURL=dev.js.map