"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const perf_hooks_1 = require("perf_hooks");
const uuidv4_1 = __importDefault(require("uuidv4"));
const WebruntimeConfig_1 = __importDefault(require("./config/WebruntimeConfig"));
const LocalDevTelemetryReporter_1 = __importDefault(require("../instrumentation/LocalDevTelemetryReporter"));
const extensions_1 = require("./extensions");
const server_1 = require("@webruntime/server");
const CustomComponentService_1 = require("./services/CustomComponentService");
const fileUtils_1 = require("../common/fileUtils");
const LabelsService_1 = require("./services/LabelsService");
const ComponentServiceWithExclusions_1 = require("./services/ComponentServiceWithExclusions");
const colors_1 = __importDefault(require("colors"));
const StaticResourcesUtils_1 = require("../common/StaticResourcesUtils");
class LocalDevServer {
    constructor(project, connection) {
        this.project = project;
        this.sessionNonce = uuidv4_1.default();
        this.vendorVersion = project.configuration.core_version;
        this.reporter = LocalDevTelemetryReporter_1.default.getInstance();
        const supportedCoreVersions = this.getSupportedCoreVersions();
        if (!this.vendorVersion ||
            !supportedCoreVersions.includes(this.vendorVersion)) {
            this.vendorVersion =
                supportedCoreVersions[supportedCoreVersions.length - 1];
        }
        const config = new WebruntimeConfig_1.default(this.project);
        const middleware = [
            extensions_1.sessionNonce(this.sessionNonce),
            extensions_1.resourceUrl()
        ];
        if (connection) {
            middleware.push(extensions_1.apexMiddleware({
                instanceUrl: connection.instanceUrl,
                accessToken: connection.accessToken
            }), extensions_1.apiMiddleware({
                apiEndpoint: project.configuration.endpoint,
                apiEndpointHeaders: project.configuration.endpointHeaders,
                apiVersion: project.configuration.api_version,
                recordDir: path_1.default.join(config.buildDir, 'api')
            }));
        }
        config.addMiddleware(middleware);
        const routes = [
            extensions_1.projectMetadata(this.sessionNonce, this.project)
        ];
        if (this.project.configuration.liveReload) {
            this.liveReload = extensions_1.liveReload(path_1.default.join(config.buildDir, 'metadata.json'), project, config);
            routes.push(this.liveReload);
        }
        config.addRoutes(routes);
        config.addModules([
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-${this.vendorVersion}/lightning-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-${this.vendorVersion}/lightning-stub-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-${this.vendorVersion}/force-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-${this.vendorVersion}/connect-gen-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-226/lightning-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-226/force-pkg`,
            `@salesforce/lwc-dev-server-dependencies/vendors/dependencies-226/connect-gen-pkg`
        ]);
        if (!this.project.isSfdx) {
            config.addModules([this.project.modulesSourceDirectory]);
            this.reporter.trackNonSfdxProjectUsage();
        }
        const services = [
            ComponentServiceWithExclusions_1.ComponentServiceWithExclusions,
            LabelsService_1.getLabelService(project.customLabelsPath)
        ];
        if (this.project.isSfdx) {
            const lwcPath = fileUtils_1.findLWCFolderPath(this.project.modulesSourceDirectory);
            if (lwcPath) {
                services.push(CustomComponentService_1.getCustomComponentService(project.configuration.namespace, project.projectDirectory, path_1.default.dirname(lwcPath)));
            }
            else {
                console.warn(`No 'lwc' directory found in path ${project.modulesSourceDirectory}`);
            }
        }
        config.addServices(services);
        this.config = config;
        this.server = new server_1.Server({
            config
        });
    }
    async shutdown() {
        if (this.liveReload) {
            await this.liveReload.close();
        }
        await this.server.shutdown();
    }
    async start() {
        const startTime = perf_hooks_1.performance.now();
        try {
            await this.server.initialize();
            StaticResourcesUtils_1.copyStaticAssets(this.project, this.config);
            this.server.on('shutdown', () => {
                this.reporter.trackApplicationEnd(startTime);
            });
            await this.server.start();
            this.reporter.trackApplicationStart(startTime, this.vendorVersion || '0');
            let port = `${this.serverPort}`;
            if (port && port !== 'undefined') {
                console.log(colors_1.default.magenta.bold(`Server up on http://localhost:${port}`));
            }
            else {
                console.error(`Server start up failed.`);
            }
        }
        catch (e) {
            this.reporter.trackApplicationStartException(e);
            console.error(`Server start up failed.`);
            throw e;
        }
    }
    get serverPort() {
        if (this.server.httpServer && this.server.httpServer.address()) {
            const addressInfo = this.server.httpServer.address();
            return addressInfo.port;
        }
    }
    getSupportedCoreVersions() {
        const vendoredModulesPath = path_1.default.join(require.resolve('@salesforce/lwc-dev-server-dependencies'), '..', 'vendors');
        const vendoredModules = fs_1.default.readdirSync(vendoredModulesPath);
        return vendoredModules.map(module => {
            return module.split('-')[1];
        });
    }
}
exports.default = LocalDevServer;
//# sourceMappingURL=LocalDevServer.js.map