"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypescriptScaffolding = void 0;
const tslib_1 = require("tslib");
const fs = require("fs");
const path = require("path");
const __1 = require("..");
const IBetterLogger_1 = require("@codiac.io/codiac-common/IBetterLogger");
const codiac_common_1 = require("@codiac.io/codiac-common");
const inversify_1 = require("inversify");
const codiac_ops_common_1 = require("@codiac.io/codiac-ops-common");
const entities_1 = require("../entities");
/** Initializes a node-typescript project for use with Codiac.
 */
let TypescriptScaffolding = class TypescriptScaffolding extends entities_1.Scaffolding {
    constructor(logger) {
        super("typescript");
        this.logger = logger;
        this.npmDependencies = ["reflect-metadata"];
        this.npmDevDependencies = [
            "mocha",
            "chai",
            "nyc",
            "@types/mocha",
            "@types/chai",
            "@types/node",
            "ts-node",
            "typescript@3.8.3",
            'reflect-metadata'
        ];
        this.scaffoldFolders = [".vscode", "src"];
        this.scaffoldFiles = [
            `.gitignore${__1.ProjectInitializer.SCAFFOLDING_SUFFIX}`,
            `src/index.ts${__1.ProjectInitializer.SCAFFOLDING_SUFFIX}`,
            ".vscode/settings.json",
            ".vscode/tasks.json",
            ".vscode/launch.json"
        ];
        this.sccIgnoreFile = `.gitignore${__1.ProjectInitializer.SCAFFOLDING_SUFFIX}`;
        // this.afterInitHandler = async config => {
        //   // Declare the api image
        //   let target = new RegistryTarget("default", ProjectInitializer.DEFAULT_REGISTRY_URL)
        //   this._ops.declareImageExport(<ProjectConfig>config, config.name, target, "Dockerfile", undefined);
        // };
        this.afterInitHandler = (projectRoot, projConfig, localOps) => tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    yield this.initTypescript(projectRoot, true);
                    yield this.initNpm(projectRoot, projConfig, this, localOps);
                    projConfig.buildDef = ["tsc -p ."];
                    resolve();
                }
                catch (err) {
                    reject(err);
                }
            }));
        });
    }
    /**
     * @param rootFolder
     * @param overwrite Reinitializes seamlessly if the project has already been initialized.  Otherwise will throw exception.
     */
    initTypescript(rootFolder, overwrite = false) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    // TODO: replace this with this._ops.deleteProjectFile(LocalOps.TSCONFIG_JSON_FILENAME);
                    let pathName = path.join(rootFolder, "tsconfig.json");
                    this.logger.debug("tsConfigPath: " + pathName);
                    if (fs.existsSync(pathName) && overwrite) {
                        this.logger.detail("removing existing tsconfig");
                        fs.unlinkSync(pathName);
                        this.logger.detail(`Deleted existing Typescript config: ${pathName}`);
                    }
                    // "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
                    // "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
                    // "lib": ["es6","dom"],                     /* Specify library files to be included in the compilation:  */
                    // "declaration": true,                      /* Generates corresponding '.d.ts' file. */
                    // "sourceMap": true,                        /* Generates corresponding '.map' file. */
                    // "outDir": "bin",                          /* Redirect output structure to the directory. */
                    // "rootDir": "src",                         /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
                    // "strict": true,                            /* Enable all strict type-checking options. */
                    // "types": ["node", "reflect-metadata"],                           /* Type declaration files to be included in compilation. */
                    // "experimentalDecorators": true        /* Enables experimental support for ES7 decorators. */
                    // "emitDecoratorMetadata": true         /* Enables experimental support for emitting type metadata for decorators. */
                    let cliExec = new codiac_ops_common_1.CliExec(this.logger);
                    let cmd = "tsc --init";
                    cmd += " --target es6";
                    cmd += " --module commonjs";
                    cmd += " --lib es6,dom";
                    cmd += " --declaration";
                    cmd += " --sourceMap";
                    cmd += " --outDir ./dist";
                    cmd += " --rootDir ./src"; //  ??
                    // cmd += " --strict"  // --alwaysStrict ?
                    cmd += " --types node,reflect-metadata";
                    // cmd += " --include src"
                    // cmd += " --exclude node_modules submodules dist"  // this param doesnt exist - whats its equivalent?
                    cmd += " --resolveJsonModule";
                    cmd += " --esModuleInterop";
                    cmd += " --experimentalDecorators"; // ??
                    cmd += " --emitDecoratorMetadata"; // ??
                    cmd += " --skipLibCheck"; // Keeps the plugin declarations from registering as errors & MS recommended  
                    let output = yield cliExec.execAsync(cmd, { cwd: rootFolder });
                    this.logger.detail(output.stderr + output.stdout);
                    resolve();
                }
                catch (err) {
                    reject(err);
                }
            }));
        });
    }
    initNpm(rootFolder, projConfig, scaffolding, localOps) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve, reject) => tslib_1.__awaiter(this, void 0, void 0, function* () {
                try {
                    this.logger.detail("Initializing NPM...");
                    localOps.deleteNpmPackageJson();
                    localOps.clearNpmNodeModulesFolder();
                    let cliExec = new codiac_ops_common_1.CliExec(this.logger);
                    let cmd = `npm init -y`; // How annoying that npm doesnt expose a way to set the name upon init.
                    let { stdout, stderr } = yield cliExec.execAsync(cmd, { cwd: rootFolder });
                    this.logger.detail(`${stderr} ${stdout}`);
                    let pkgJson = localOps.readNpmPackageJson();
                    pkgJson.name = projConfig.name;
                    localOps.writeNpmPackageJson(pkgJson);
                    this.logger.detail("NPM dependencies...");
                    let cmdDep = `npm install ${this.npmDependencies.join(' ')}`;
                    let depOutput = yield cliExec.spawnAndLog(cmdDep, rootFolder, undefined, IBetterLogger_1.LogLevel.detail);
                    // for (let index in this.npmDependencies) {
                    //   let dep = this.npmDependencies[index];
                    //   this.logger.detail(`Installing ${dep}...`);
                    //   let depOutput = await this.cliExec.spawnAndLog(`npm install ${dep}`, rootFolder, undefined, LogLevel.detail);
                    //   // let depOutput = await this.cliExec.execAsync(`npm install ${dep}`, { cwd: rootFolder });
                    //   // this.logger.detail(depOutput.stderr + depOutput.stdout);
                    // }
                    this.logger.detail("NPM Dev dependencies...");
                    let cmdDev = `npm install ${this.npmDevDependencies.join(' ')}`;
                    let devOutput = yield cliExec.spawnAndLog(cmdDev, rootFolder, undefined, IBetterLogger_1.LogLevel.detail);
                    // for (let index in this.npmDevDependencies) {
                    //   let dep = this.npmDevDependencies[index];
                    //   this.logger.detail(`Installing ${dep}...`);
                    //   let devDepOutput = await this.cliExec.spawnAndLog(`npm install --save-dev ${dep} `, rootFolder, undefined, LogLevel.detail);
                    //   // let devDepOutput = await this.cliExec.execAsync(`npm install --save-dev ${dep} `, { cwd: rootFolder });
                    //   // this.logger.detail(devDepOutput.stderr + devDepOutput.stdout);
                    // }
                    resolve();
                }
                catch (err) {
                    this.logger.error(`Error occurred initializing NPM: ${err}`);
                    reject(err);
                }
            }));
        });
    }
};
TypescriptScaffolding = tslib_1.__decorate([
    (0, inversify_1.injectable)(),
    tslib_1.__param(0, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
    tslib_1.__metadata("design:paramtypes", [Object])
], TypescriptScaffolding);
exports.TypescriptScaffolding = TypescriptScaffolding;
//# sourceMappingURL=typescript-scaffolding.js.map