UNPKG

@webda/shell

Version:

Deploy a Webda app or configure it

316 lines 9.81 kB
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; }; import { Cache, FileUtils, JSONUtils, UnpackedApplication, WebdaError } from "@webda/core"; import { execSync } from "child_process"; import dateFormat from "dateformat"; import * as fs from "fs"; import * as merge from "merge"; import * as path from "path"; import semver from "semver"; import { Compiler } from "./compiler.js"; export class SourceApplication extends UnpackedApplication { constructor() { super(...arguments); /** * Flag if application has been compiled already */ this.compiled = false; } getCompiler() { this.compiler ?? (this.compiler = new Compiler(this)); return this.compiler; } /** * Get the Webda namespace */ getNamespace() { return this.getPackageWebda().namespace || "webda"; } /** * Retrieve Git Repository information * * {@link GitInformation} for more details on how the information is gathered * @return the git information */ getGitInformation(packageName = "", version = "") { let options = { cwd: this.getAppPath() }; try { // If git information are defined in env - useful for container build if (process.env.GIT_INFO) { return JSON.parse(Buffer.from(process.env.GIT_INFO, "base64").toString()); } let tags = execSync(`git tag --points-at HEAD`, options) .toString() .trim() .split("\n") .filter(t => t !== ""); let tag = ""; if (tags.includes(`${packageName}@${version}`)) { tag = `${packageName}@${version}`; } else if (tags.includes(`v${version}`)) { tag = `v${version}`; } else { version = semver.inc(version, "patch") + "+" + dateFormat(new Date(), "yyyymmddHHMMssl"); } // Search for what would be the tag // packageName@version // or version if single repo // if not included create a nextVersion+SNAPSHOT.${commit}.${now} return { commit: execSync(`git rev-parse HEAD`, options).toString().trim(), branch: execSync("git symbolic-ref --short HEAD", options).toString().trim(), short: execSync(`git rev-parse --short HEAD`, options).toString().trim(), tag, tags, version }; } catch (err) { return { commit: "unknown", branch: "unknown", tag: "", short: "00000000", tags: [], version }; } } /** * Set the status of the compilation * * @param compile true will avoid trigger new compilation */ preventCompilation(compile) { this.compiled = compile; } /** * Generate the module for current application */ async generateModule() { // Compile if (!this.compile()) { return false; } // Write module FileUtils.save(this.getCompiler().generateModule(), this.getAppPath("webda.module.json")); return true; } /** * Get the application files */ getPackagesLocations() { return this.baseConfiguration.cachedModules?.project?.package?.files || ["lib/**/*.js"]; } /** * Compile the application if it is a Typescript application * Do nothing otherwise */ compile() { if (!this.compiled) { this.compiled = this.getCompiler().compile(); } return this.compiled; } /** * Return the application Configuration for a deployment * * Given this inputs: * * webda.config.json * ```json * { * "parameters": { * "param3": "test" * }, * "services": { * "MyService": { * "param1": { * "sub": "test" * }, * "param2": "value" * } * } * } * ``` * * deployment.json * ```json * { * "parameters": { * "param4": "deployment" * } * "services": { * "MyService": { * "param1": { * "sub2": "deploymentSub" * }, * "param2": "${package.version}" * } * } * } * ``` * * The result would be: * ```json * { * "parameters": { * "param3": "test", * "param4": "deployment" * }, * "services": { * "MyService": { * "param1": { * "sub": "test", * "sub2": "deploymentSub" * }, * "param2": "1.1.0" * } * } * } * ``` * This map can also use parameters {@link replaceVariables} * * @param deploymentName to use for the Configuration */ getConfiguration(deploymentName = undefined) { if (!deploymentName) { return this.baseConfiguration; } let config = JSONUtils.duplicate(this.baseConfiguration); let deploymentModel = this.getDeployment(deploymentName); config.parameters = this.replaceVariables(merge.recursive(config.parameters, deploymentModel.parameters)); config.services = this.replaceVariables(merge.recursive(config.services, deploymentModel.services)); return config; } /** * Return current Configuration of the Application * * Same as calling * * ```js * getConfiguration(this.currentDeployment); * ``` */ getCurrentConfiguration() { return this.getConfiguration(this.currentDeployment); } /** * Get current deployment name */ getCurrentDeployment() { return this.currentDeployment; } /** * Set the current deployment for the application * Call to getCurrentConfiguration will resolve to the computed configuration for the deployment * If needed, you can call the method with undefined to reset to default configuration * * @param deployment to set */ setCurrentDeployment(deployment) { this.currentDeployment = deployment; } /** * Load a deployment configuration * * @param deploymentName * @returns */ getDeployment(deploymentName = undefined) { if (!deploymentName) { deploymentName = this.currentDeployment; } this.deploymentFile = undefined; let deploymentConfig; for (let ext of [".jsonc", ".json", ".yaml", ".yml"]) { deploymentConfig = path.join(this.appPath, "deployments", `${deploymentName}${ext}`); if (fs.existsSync(deploymentConfig)) { break; } } if (!fs.existsSync(deploymentConfig)) { throw new WebdaError.CodeError("UNKNOWN_DEPLOYMENT", "Unknown deployment"); } let deploymentModel; try { deploymentModel = FileUtils.load(deploymentConfig); deploymentModel.name = deploymentName; } catch (err) { throw new WebdaError.CodeError("INVALID_DEPLOYMENT", `Invalid deployment configuration ${deploymentConfig}: ${err.toString()}`); } this.deploymentFile = deploymentConfig; return deploymentModel; } /** * Check if a deployment exists for this application * This method cannot be called for a packaged application * as we do not keep deployments files when deployed * * @param deploymentName */ hasDeployment(deploymentName) { return fs.existsSync(path.join(this.appPath, "deployments", deploymentName + ".json")); } } __decorate([ Cache() ], SourceApplication.prototype, "getGitInformation", null); /** * Used to generate module * We do not want to load any module, we only compile the sources and then analyze * to generate the webda.module.json */ export class BuildSourceApplication extends SourceApplication { constructor() { super(...arguments); /** * Module has been generated */ this.moduleReady = false; } /** * @returns */ filterModule(file) { return this.moduleReady && super.filterModule(file); } /** * Override to empty if moduleReady is false * @returns */ getModulesCache() { if (!this.moduleReady) { return {}; } // @ts-ignore const cacheModules = process.webdaModules || {}; // @ts-ignore process.webdaModules ?? (process.webdaModules = cacheModules); return cacheModules; } /** * @override */ async generateModule() { if (!(await super.generateModule())) { return false; } // Module is generated this.moduleReady = true; // Reload all modules now this.mergeModules(this.baseConfiguration); await this.loadModule(this.baseConfiguration.cachedModules); return true; } } //# sourceMappingURL=sourceapplication.js.map