"use strict";
/*
 * Copyright © 2020 Atomist, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeScriptCompileCacheRestore = exports.TypeScriptCompileCachePut = exports.NpmNodeModulesCacheRestore = exports.NpmNodeModulesCachePut = exports.NpmCompileProjectListener = exports.NpmInstallProjectListener = exports.NpmVersionProjectListener = exports.npmCompilePreparation = exports.npmInstallPreparation = exports.npmVersionPreparation = void 0;
const child_process_1 = require("../../../api-helper/misc/child_process");
const GoalInvocation_1 = require("../../../api/goal/GoalInvocation");
const projectVersioner_1 = require("../../../core/delivery/build/local/projectVersioner");
const goalCaching_1 = require("../../../core/goal/cache/goalCaching");
const spawn_1 = require("../npm/spawn");
const nodePushTests_1 = require("../pushtest/nodePushTests");
/**
 * Update package files with pre-release version for the provided goal
 * invocation.
 *
 * @param p Project to modify package files in
 * @param gi SDM goal invocation triggering this preparation
 * @return Success or failure
 */
async function npmVersionPreparation(p, gi) {
    const goalEvent = gi.goalEvent;
    const repo = goalEvent.repo;
    const version = await projectVersioner_1.readSdmVersion(repo.owner, repo.name, repo.providerId, goalEvent.sha, goalEvent.branch, gi.context);
    return child_process_1.spawnLog("npm", ["version", "--no-git-tag-version", version], spawn_1.npmSpawnLogOptions(p, gi.progressLog));
}
exports.npmVersionPreparation = npmVersionPreparation;
/**
 * Install Node.js dependencies using NPM, running `npm install` or
 * `npm ci`, as appropriate.
 *
 * @param p Project to install dependencies for
 * @param gi SDM goal invocation triggering this preparation
 * @return Success or failure
 */
async function npmInstallPreparation(p, gi) {
    const hasPackageLock = await p.hasFile("package-lock.json");
    const installCmd = hasPackageLock ? "ci" : "install";
    return child_process_1.spawnLog("npm", [installCmd], spawn_1.npmSpawnLogOptions(p, gi.progressLog));
}
exports.npmInstallPreparation = npmInstallPreparation;
/**
 * Run NPM package compile script, if present.
 *
 * @param p Project to run compile script in
 * @param gi SDM goal invocation triggering this preparation
 * @return Success or failure
 */
async function npmCompilePreparation(p, gi) {
    return child_process_1.spawnLog("npm", ["run", "--if-present", "compile"], spawn_1.npmSpawnLogOptions(p, gi.progressLog));
}
exports.npmCompilePreparation = npmCompilePreparation;
/**
 * Project listener that runs [[npmVersionPreparation]] before executing goal.
 */
exports.NpmVersionProjectListener = {
    events: [GoalInvocation_1.GoalProjectListenerEvent.before],
    listener: npmVersionPreparation,
    name: "npm version",
    pushTest: nodePushTests_1.IsNode,
};
/**
 * Project listener that runs [[npmInstallPreparation]] before executing goal.
 */
exports.NpmInstallProjectListener = {
    events: [GoalInvocation_1.GoalProjectListenerEvent.before],
    listener: npmInstallPreparation,
    name: "npm install",
    pushTest: nodePushTests_1.IsNode,
};
/**
 * Project listener that runs [[npmCompilePreparation]] before executing goal.
 */
exports.NpmCompileProjectListener = {
    events: [GoalInvocation_1.GoalProjectListenerEvent.before],
    listener: npmCompilePreparation,
    name: "npm compile",
    pushTest: nodePushTests_1.IsNode,
};
// tslint:disable-next-line:no-invalid-template-strings
const npmCacheClassifier = "${repo.owner}/${repo.name}/${sha}";
const npmNodeModulesCacheClassifier = `${npmCacheClassifier}/node_modules`;
/**
 * Listener that stores the `node_modules` directory in the configured
 * cache after a goal invocation.
 */
exports.NpmNodeModulesCachePut = goalCaching_1.cachePut({
    entries: [{ classifier: npmNodeModulesCacheClassifier, pattern: { directory: "node_modules" } }],
    pushTest: nodePushTests_1.IsNode,
});
/**
 * Install Node.js dependencies using NPM and cache the results.  If
 * install the dependencies fails, nothing is cached.
 *
 * @param p Project to install dependencies for
 * @param gi SDM goal invocation triggering this preparation
 * @param event SDM goal event triggering this preparation
 * @return Success or failure
 */
async function cachingNpmInstallPreparation(p, gi, event) {
    const log = gi.progressLog;
    const prepResult = await npmInstallPreparation(p, gi);
    if (prepResult.code !== 0) {
        log.write(`Failed to install dependencies using npm: ${prepResult.message}`);
        return prepResult;
    }
    try {
        await exports.NpmNodeModulesCachePut.listener(p, gi, event);
    }
    catch (e) {
        log.write(`Failed to cache node_modules: ${e.message}`);
    }
    return prepResult;
}
/**
 * Listener that restores the `node_modules` directory from the
 * configured cache before a goal invocation.
 */
exports.NpmNodeModulesCacheRestore = goalCaching_1.cacheRestore({
    entries: [{ classifier: npmNodeModulesCacheClassifier }],
    onCacheMiss: {
        name: "cache-miss-npm-install",
        listener: cachingNpmInstallPreparation,
    },
    pushTest: nodePushTests_1.IsNode,
});
const typescriptCompileCacheClassifier = `${npmCacheClassifier}/ts-compile`;
/**
 * Listener that stores the output from TypeScript compilation in the
 * configured cache after a goal invocation.
 */
exports.TypeScriptCompileCachePut = goalCaching_1.cachePut({
    entries: [
        {
            classifier: typescriptCompileCacheClassifier,
            pattern: {
                globPattern: [
                    "*.{d.ts,js}{,.map}",
                    "!(node_modules)/**/*.{d.ts,js}{,.map}",
                    "lib/typings/types.ts",
                    "git-info.json",
                ],
            },
        },
    ],
    pushTest: nodePushTests_1.IsNode,
});
/**
 * Use NPM to compile sources and cache the results.  If compilation
 * fails, nothing is cached.
 *
 * @param p Project to run compile in
 * @param gi SDM goal invocation triggering this preparation
 * @param event SDM goal event triggering this preparation
 * @return Success or failure
 */
async function cachingNpmCompilePreparation(p, gi, event) {
    const log = gi.progressLog;
    const prepResult = await npmCompilePreparation(p, gi);
    if (prepResult.code !== 0) {
        log.write(`Failed to compile using npm: ${prepResult.message}`);
        return prepResult;
    }
    try {
        await exports.TypeScriptCompileCachePut.listener(p, gi, event);
    }
    catch (e) {
        log.write(`Failed to cache compiled files: ${e.message}`);
    }
    return prepResult;
}
/**
 * Listener that restores the output from TypeScript compilation from
 * the configured cache before a goal invocation.
 */
exports.TypeScriptCompileCacheRestore = goalCaching_1.cacheRestore({
    entries: [{ classifier: typescriptCompileCacheClassifier }],
    onCacheMiss: {
        name: "cache-miss-typescript-compile",
        listener: cachingNpmCompilePreparation,
    },
    pushTest: nodePushTests_1.IsNode,
});
//# sourceMappingURL=npm.js.map