@topgroup/diginext
Version:
A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.
598 lines (597 loc) • 32.6 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppService = void 0;
const lodash_1 = require("lodash");
const path_1 = __importDefault(require("path"));
const const_1 = require("../config/const");
const App_1 = require("../entities/App");
const generate_deployment_name_1 = __importDefault(require("../modules/deploy/generate-deployment-name"));
const dx_domain_1 = require("../modules/diginext/dx-domain");
const git_1 = require("../modules/git");
const git_provider_api_1 = __importDefault(require("../modules/git/git-provider-api"));
const git_utils_1 = require("../modules/git/git-utils");
const initalizeAndCreateDefaultBranches_1 = require("../modules/git/initalizeAndCreateDefaultBranches");
const k8s_1 = __importDefault(require("../modules/k8s"));
const check_quota_1 = require("../modules/workspace/check-quota");
const plugins_1 = require("../plugins");
const array_1 = require("../plugins/array");
const env_var_1 = require("../plugins/env-var");
const mask_sensitive_info_1 = require("../plugins/mask-sensitive-info");
const mongodb_1 = require("../plugins/mongodb");
const slug_1 = require("../plugins/slug");
const string_1 = require("../plugins/string");
const user_utils_1 = require("../plugins/user-utils");
const BaseService_1 = __importDefault(require("./BaseService"));
class AppService extends BaseService_1.default {
constructor(ownership) {
super(App_1.appSchema, ownership);
}
async create(data, options) {
// validate
let project;
let appDto = { ...data };
// ownership
const { WorkspaceService, ProjectService, GitProviderService } = await Promise.resolve().then(() => __importStar(require("./index")));
const wsSvc = new WorkspaceService();
const projectSvc = new ProjectService();
const workspace = this.ownership.workspace ||
(data.workspace && mongodb_1.MongoDB.isValidObjectId(data.workspace) ? await wsSvc.findOne({ _id: data.workspace }) : undefined);
if (!workspace)
throw new Error(`Workspace not found.`);
// check dx quota
const quotaRes = await (0, check_quota_1.checkQuota)(workspace);
if (!quotaRes.status)
throw new Error(quotaRes.messages.join(". "));
if (quotaRes.data && quotaRes.data.isExceed)
throw new Error(`You've exceeded the limit amount of apps (${quotaRes.data.type} / Max. ${quotaRes.data.limits.apps} apps).`);
// validate
if (!data.project)
throw new Error(`Project ID or slug or instance is required.`);
if (!data.name)
throw new Error(`App's name is required.`);
if ((0, string_1.containsSpecialCharacters)(data.name))
throw new Error(`App's name should not contain special characters.`);
// find parent project of this app
if (mongodb_1.MongoDB.isValidObjectId(data.project)) {
project = await projectSvc.findOne({ _id: data.project });
}
else if ((0, lodash_1.isString)(data.project)) {
project = await projectSvc.findOne({ slug: data.project });
}
else {
throw new Error(`"project" is not a valid ID or slug.`);
}
if (!project)
throw new Error(`Project "${data.project}" not found.`);
appDto.projectSlug = project.slug;
// check access permissions
(0, user_utils_1.checkProjectPermissions)(project, this.user);
// framework
if (!data.framework)
data.framework = { name: "none", slug: "none", repoURL: "unknown", repoSSH: "unknown" };
if (data.framework === "none")
data.framework = { name: "none", slug: "none", repoURL: "unknown", repoSSH: "unknown" };
appDto.framework = data.framework;
// git repo
if (options.shouldCreateGitRepo) {
// create repo if needed
if (!data.gitProvider)
throw new Error(`"gitProvider" is required.`);
const gitSvc = new GitProviderService();
const gitProvider = await gitSvc.findOne({ _id: data.gitProvider });
if (!gitProvider)
throw new Error(`Git provider not found.`);
const repoSlug = `${project.slug}-${(0, slug_1.makeSlug)(data.name)}`.toLowerCase();
if (options === null || options === void 0 ? void 0 : options.force) {
try {
await git_provider_api_1.default.deleteGitRepository(gitProvider, gitProvider.org, repoSlug);
}
catch (e) { }
}
const newRepo = await git_provider_api_1.default.createGitRepository(gitProvider, { name: repoSlug, private: true });
// assign to app data:
appDto.git = {
repoSSH: newRepo.ssh_url,
repoURL: newRepo.repo_url,
provider: gitProvider.type,
};
}
else {
if ((0, lodash_1.isString)(data.git)) {
const gitData = (0, git_utils_1.parseGitRepoDataFromRepoSSH)(data.git);
if (!gitData)
throw new Error(`Git repository information is not valid.`);
data.git = {
repoSSH: data.git,
repoURL: (0, git_1.getRepoURLFromRepoSSH)(gitData.providerType, gitData.fullSlug),
provider: gitData.providerType,
};
}
if (!data.git)
throw new Error(`Git info is required.`);
appDto.git = data.git;
}
if (!appDto.ownerSlug)
appDto.ownerSlug = this.user.username || this.ownership.owner.username;
let newApp;
try {
newApp = await super.create(appDto, options);
if (!newApp)
throw new Error(`Unable to create new app: "${appDto.name}".`);
}
catch (e) {
throw new Error(e.toString());
}
const newAppId = newApp._id;
/**
* @deprecated
*/
// migrate app environment variables if needed (convert {Object} to {Array})
// const migratedApp = await migrateAppEnvironmentVariables(newApp);
// if (migratedApp) newApp = migratedApp;
// add this new app to the project info
if (project) {
projectSvc.ownership = this.ownership;
const projectApps = [...(project.apps || []), newAppId];
const projectAppSlugs = (0, array_1.uniqueStrings)([...(project.appSlugs || []), newApp.slug]);
project = await projectSvc.updateOne({ _id: project._id }, { apps: projectApps, appSlugs: projectAppSlugs });
}
return newApp;
}
async createWithGitURL(repoSSH, gitProviderID, ownership, options) {
const appDto = {};
const workspace = ownership.workspace;
const owner = ownership.owner;
if (options === null || options === void 0 ? void 0 : options.isDebugging)
console.log("createWithGitURL() > ownership :>> ", { workspace, owner });
// parse git data
const repoData = (0, git_utils_1.parseGitRepoDataFromRepoSSH)(repoSSH);
if (options === null || options === void 0 ? void 0 : options.isDebugging)
console.log("createWithGitURL() > repoData :>> ", repoData);
if (!repoData)
throw new Error(`Unable to read git repo SSH.`);
const { repoSlug } = repoData;
// default project
const { ProjectService, GitProviderService } = await Promise.resolve().then(() => __importStar(require("./index")));
const projectSvc = new ProjectService();
projectSvc.ownership = this.ownership;
let project = await projectSvc.findOne({ isDefault: true, workspace: workspace._id }, options);
if (!project)
project = await projectSvc.create({ name: "Default", isDefault: true, workspace: workspace._id, owner: owner._id });
// check permissions
(0, user_utils_1.checkProjectPermissions)(project, this.user);
// git provider
const gitSvc = new GitProviderService();
const gitProvider = await gitSvc.findOne({ _id: gitProviderID });
if (options === null || options === void 0 ? void 0 : options.isDebugging)
console.log("createWithGitURL() > gitProvider :>> ", gitProvider);
if (!gitProvider)
throw new Error(`Unable to import git repo, git provider not found.`);
// new repo slug
const newRepoSlug = `${project.slug}-${(0, slug_1.makeSlug)(repoSlug)}`.toLowerCase();
const newRepoSSH = `git@${gitProvider.host}:${gitProvider.org}/${newRepoSlug}.git`;
// check app is existed
const existingApp = await this.findOne({ "git.repoSSH": newRepoSSH, workspace: workspace._id }, options);
if (options === null || options === void 0 ? void 0 : options.isDebugging)
console.log("createWithGitURL() > existingApp :>> ", existingApp);
if (existingApp) {
// [DANGEROUS] delete existing app when `--force` is specified:
if (options === null || options === void 0 ? void 0 : options.force) {
await this.delete({ "git.repoSSH": newRepoSSH, workspace: workspace._id });
}
else {
if (options === null || options === void 0 ? void 0 : options.returnExisting)
return existingApp;
throw new Error(`Unable to import: app was existed with name "${existingApp.slug}" (Project: "${project.name}").`);
}
}
// clone/pull that repo url
const branch = (options === null || options === void 0 ? void 0 : options.gitBranch) || "main";
const SOURCE_CODE_DIR = `cache/${project.slug}/${newRepoSlug}/${branch}`;
const APP_DIR = path_1.default.resolve(const_1.CLI_CONFIG_DIR, SOURCE_CODE_DIR);
// try with "repoSSH" first, if failed, try "repoURL"...
try {
await (0, plugins_1.pullOrCloneGitRepo)(repoSSH, APP_DIR, branch, {
isDebugging: options === null || options === void 0 ? void 0 : options.isDebugging,
removeGitOnFinish: true,
removeCIOnFinish: options.removeCI,
});
}
catch (e) {
const repoURL = (0, git_utils_1.repoSshToRepoURL)(repoSSH);
await (0, git_utils_1.pullOrCloneGitRepoHTTP)(repoURL, APP_DIR, branch, {
isDebugging: options === null || options === void 0 ? void 0 : options.isDebugging,
removeGitOnFinish: true,
removeCIOnFinish: options.removeCI,
useAccessToken: {
type: gitProvider.method === "basic" ? "Basic" : "Bearer",
value: gitProvider.access_token,
},
});
}
if (options === null || options === void 0 ? void 0 : options.force) {
try {
await git_provider_api_1.default.deleteGitRepository(gitProvider, gitProvider.org, newRepoSlug);
}
catch (e) { }
}
// create git repo
const gitRepo = await git_provider_api_1.default.createGitRepository(gitProvider, {
name: newRepoSlug,
private: true,
description: `Forked from ${repoSSH}`,
}, options);
// setup initial repo: default branches, locked,...
await (0, initalizeAndCreateDefaultBranches_1.initalizeAndCreateDefaultBranches)({
targetDirectory: APP_DIR,
repoSSH: newRepoSSH,
git: gitProvider,
username: owner.slug,
isDebugging: options === null || options === void 0 ? void 0 : options.isDebugging,
});
// prepare app data
appDto.name = repoSlug;
appDto.owner = owner._id;
appDto.ownerSlug = owner.slug;
appDto.workspace = workspace._id;
appDto.workspaceSlug = workspace.slug;
appDto.project = project._id;
appDto.projectSlug = project.slug;
appDto.gitProvider = gitProvider._id;
appDto.git = { provider: gitProvider.type, repoSSH: gitRepo.ssh_url, repoURL: gitRepo.repo_url };
appDto.framework = { name: "none", slug: "none", repoURL: "unknown", repoSSH: "unknown" };
// ownership
appDto.workspace = workspace._id;
appDto.workspaceSlug = workspace.slug;
appDto.owner = owner._id;
appDto.ownerSlug = owner.slug;
// save to database
const newApp = await this.create(appDto, options);
// add app & app slug to project
projectSvc.ownership = this.ownership;
await projectSvc.updateOne({ _id: project._id }, { $push: { apps: newApp._id, appSlugs: newApp.slug } }, { raw: true });
return newApp;
}
async find(filter, options, pagination) {
var _a, _b, _c, _d, _e;
// check access permissions
if ((_c = (_b = (_a = this.user) === null || _a === void 0 ? void 0 : _a.allowAccess) === null || _b === void 0 ? void 0 : _b.apps) === null || _c === void 0 ? void 0 : _c.length)
filter = { $or: [filter, { _id: { $in: (_e = (_d = this.user) === null || _d === void 0 ? void 0 : _d.allowAccess) === null || _e === void 0 ? void 0 : _e.apps } }] };
const { status = false } = options || {};
const apps = await super.find(filter, options, pagination);
// if skip status checking, return apps
if (!status) {
return apps.map((app) => {
if (app && app.deployEnvironment) {
for (const env of Object.keys(app.deployEnvironment)) {
if (app.deployEnvironment[env] && app.deployEnvironment[env].envVars) {
app.deployEnvironment[env].envVars = (0, env_var_1.formatEnvVars)(app.deployEnvironment[env].envVars);
}
}
}
return app;
});
}
// start checking status -> get cluster info
const { ClusterService } = await Promise.resolve().then(() => __importStar(require("./index")));
const clusterSvc = new ClusterService();
const clusterFilter = {};
if (filter === null || filter === void 0 ? void 0 : filter.workspace)
clusterFilter.workspace = filter.workspace;
const clusters = await clusterSvc.find(clusterFilter);
// check app deploy environment's status in clusters
const appsWithStatus = await Promise.all(apps
.map(async (app) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
if (app && app.deployEnvironment) {
for (const env of Object.keys(app.deployEnvironment)) {
if (!app.deployEnvironment[env])
app.deployEnvironment[env] = { buildTag: "" };
// format environment variables (if any)
if (app.deployEnvironment[env] && app.deployEnvironment[env].envVars) {
app.deployEnvironment[env].envVars = (0, env_var_1.formatEnvVars)(app.deployEnvironment[env].envVars);
}
// default values
app.deployEnvironment[env].readyCount = 0;
app.deployEnvironment[env].status = "undeployed";
if (!app.deployEnvironment[env].cluster)
return app;
// find cluster & namespace
const clusterSlug = app.deployEnvironment[env].cluster;
const cluster = clusters.find((_cluster) => _cluster.slug === clusterSlug);
if (!cluster)
return app;
const { contextName: context } = cluster;
if (!context)
return app;
const { namespace } = app.deployEnvironment[env];
if (!namespace)
return app;
// find workloads base on "main-app" label
const mainAppName = await (0, generate_deployment_name_1.default)(app);
let [deployOnCluster] = await k8s_1.default.getDeploys(namespace, {
filterLabel: `main-app=${mainAppName}`,
context,
metrics: true,
});
console.log(`----- ${app.name} -----`);
// console.log("- mainAppName :>> ", mainAppName);
// console.log("- deployOnCluster.metadata.name :>> ", deployOnCluster?.metadata?.name);
console.log("- deployOnCluster.status.replicas :>> ", (_a = deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.status) === null || _a === void 0 ? void 0 : _a.replicas);
console.log("- deployOnCluster.resources.limits :>> ", (_f = (_e = (_d = (_c = (_b = deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.spec) === null || _b === void 0 ? void 0 : _b.template) === null || _c === void 0 ? void 0 : _c.spec) === null || _d === void 0 ? void 0 : _d.containers) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.resources.limits);
console.log("- deployOnCluster.cpuAvg :>> ", deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.cpuAvg);
console.log("- deployOnCluster.memoryAvg :>> ", deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.memoryAvg);
// console.log("- deployOnCluster.status.readyReplicas :>> ", deployOnCluster?.status?.readyReplicas);
// console.log("- deployOnCluster.status.availableReplicas :>> ", deployOnCluster?.status?.availableReplicas);
// console.log("- deployOnCluster.status.unavailableReplicas :>> ", deployOnCluster?.status?.unavailableReplicas);
app.deployEnvironment[env].resources = {};
app.deployEnvironment[env].resources.limits = (_l = (_k = (_j = (_h = (_g = deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.spec) === null || _g === void 0 ? void 0 : _g.template) === null || _h === void 0 ? void 0 : _h.spec) === null || _j === void 0 ? void 0 : _j.containers) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.resources.limits;
app.deployEnvironment[env].resources.usage = {
cpu: deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.cpuAvg,
memory: deployOnCluster === null || deployOnCluster === void 0 ? void 0 : deployOnCluster.memoryAvg,
};
if (!deployOnCluster) {
app.deployEnvironment[env].status = "undeployed";
return app;
}
app.deployEnvironment[env].readyCount =
(_o = (_m = deployOnCluster.status.readyReplicas) !== null && _m !== void 0 ? _m : deployOnCluster.status.availableReplicas) !== null && _o !== void 0 ? _o : 0;
// console.log("- app.deployEnvironment[env].readyCount :>> ", app.deployEnvironment[env].readyCount);
if (deployOnCluster.status.replicas === deployOnCluster.status.availableReplicas ||
deployOnCluster.status.replicas === deployOnCluster.status.readyReplicas) {
app.deployEnvironment[env].status = "healthy";
return app;
}
if (deployOnCluster.status.unavailableReplicas && deployOnCluster.status.unavailableReplicas > 0) {
app.deployEnvironment[env].status = "partial_healthy";
return app;
}
if (deployOnCluster.status.availableReplicas === 0 ||
deployOnCluster.status.unavailableReplicas === deployOnCluster.status.replicas ||
deployOnCluster.status.readyReplicas === 0) {
app.deployEnvironment[env].status = "failed";
return app;
}
app.deployEnvironment[env].status = "unknown";
}
}
return app;
})
.filter((app) => typeof app !== "undefined"));
return appsWithStatus;
}
async update(filter, data, options) {
// permissions
await (0, user_utils_1.checkAppPermissionsByFilter)(this, filter, this.user);
// const allApps = await this.find({});
// console.log("AppService > allApps :>> ", allApps);
// if (options?.isDebugging) console.log("AppService > update > filter :>>", filter);
let apps = await this.find(filter, data, options);
if ((0, lodash_1.isEmpty)(apps)) {
console.error(`AppService > update :>>`, { filter });
throw new Error(`Apps not found.`);
}
// console.log("AppService > update > apps :>>", apps);
const { ProjectService, WorkspaceService } = await Promise.resolve().then(() => __importStar(require("./index")));
const projectSvc = new ProjectService(this.ownership);
let project;
if (data.project) {
// find a project of this app
if (mongodb_1.MongoDB.isValidObjectId(data.project)) {
project = await projectSvc.findOne({ _id: data.project });
}
else if ((0, lodash_1.isString)(data.project)) {
project = await projectSvc.findOne({ slug: data.project });
}
else {
throw new Error(`Param "project" is not a valid ID or slug.`);
}
if (!project)
throw new Error(`Project "${data.project}" not found.`);
data.projectSlug = project.slug;
data.project = project._id;
// add this app._id and app.slug to project.apps and project.appSlugs
if (!project.apps)
project.apps = [];
if (!project.appSlugs)
project.appSlugs = [];
if (!project.apps.includes(data._id))
project.apps.push(data._id);
if (!project.appSlugs.includes(data.slug))
project.appSlugs.push(data.slug);
// update project
apps.forEach(async (app) => {
if (app._id && !project.apps.includes(app._id))
project.apps.push(app._id);
if (app._id && !project.appSlugs.includes(app.slug))
project.appSlugs.push(app.slug);
await projectSvc.updateOne({ _id: project._id }, { apps: project.apps, appSlugs: project.appSlugs });
});
}
// delete deploy environment of this app
if (data.deployEnvironment) {
const [app] = apps;
const wsId = app.workspace ? (mongodb_1.MongoDB.isValidObjectId(app.workspace) ? app.workspace : app.workspace._id) : undefined;
if (!wsId)
throw new Error(`Workspace ID is not valid.`);
const wsSvc = new WorkspaceService();
const workspace = this.workspace || (await wsSvc.findOne({ _id: wsId }));
if (!workspace)
throw new Error(`Workspace not found.`);
for (const env of Object.keys(data.deployEnvironment)) {
const deployEnvironment = data.deployEnvironment[env];
if (deployEnvironment) {
// TODO: Check quota based on CPU & memory (NEW)
// if (Config.NODE_ENV === "production") {
// const { size } = deployEnvironment;
// if (size) {
// const quotaRes = await checkQuota(workspace, { resourceSize: size });
// if (!quotaRes.status) throw new Error(quotaRes.messages.join(". "));
// if (quotaRes.data && quotaRes.data.isExceed) {
// throw new Error(`You've exceeded the limit amount of container size.`);
// }
// }
// }
// IMPORTANT: Only update specific paths
for (const key of Object.keys(deployEnvironment)) {
data[`deployEnvironment.${env}.${key}`] = deployEnvironment[key];
}
}
}
// ! CAUTION: Delete deployEnvironment before updating
delete data.deployEnvironment;
}
// if (options?.isDebugging) console.log("AppService > update > data :>>", data);
apps = await super.update(filter, data, options);
// if (options?.isDebugging) console.log("AppService > update > [UPDATED] apps :>>", apps);
return apps;
}
async updateOne(filter, data, options) {
const [app] = await this.update(filter, data, options);
return app;
}
async delete(filter, options) {
// permissions
await (0, user_utils_1.checkProjectAndAppPermissions)(this, filter, this.user);
const app = await this.findOne(filter, { populate: ["project"] });
if (!app)
throw new Error(`App not found.`);
const { DeployEnvironmentService } = await Promise.resolve().then(() => __importStar(require("../services")));
const deployEnvSvc = new DeployEnvironmentService();
if (app.deployEnvironment) {
// take down all deploy environments of this app
Object.entries(app.deployEnvironment).map(async ([env, deployEnvironment]) => {
// take down environment
if (!(0, lodash_1.isEmpty)(deployEnvironment)) {
await deployEnvSvc.takeDownDeployEnvironment(app, env).catch((e) => {
console.error(`AppService > delete() > takeDownDeployEnvironment() :>>`, e);
});
}
// delete diginext domain record (if any)
if (deployEnvironment.domains && deployEnvironment.domains.filter((domain) => domain.indexOf(const_1.DIGINEXT_DOMAIN) > -1).length > 0) {
if (this.workspace && this.workspace.dx_key) {
for (const domain of deployEnvironment.domains.filter((_domain) => _domain.indexOf(const_1.DIGINEXT_DOMAIN) > -1)) {
const recordName = domain.replace(const_1.DIGINEXT_DOMAIN, "");
(0, dx_domain_1.dxDeleteDomainRecord)({ name: recordName, type: "A" }, this.workspace.dx_key).catch(console.error);
}
}
else {
console.error("AppService > delete() > Delete domain A record > No WORKSPACE or DX_KEY found.");
}
}
});
}
// remove this app ID from project.apps
const { ProjectService } = await Promise.resolve().then(() => __importStar(require("../services")));
const project = await new ProjectService().updateOne({
_id: app.project._id,
}, {
$pull: { apps: app._id, appSlugs: app.slug },
}, { raw: true });
return super.delete(filter, options);
}
async softDelete(filter, options) {
// permissions
await (0, user_utils_1.checkProjectAndAppPermissions)(this, filter, this.user);
const app = await this.findOne(filter, options);
if (!app)
throw new Error(`Unable to delete: App not found.`);
// take down all deploy environments of this app
try {
await this.takeDown(app, options);
}
catch (e) {
// ignore on error
console.error(e);
}
return super.softDelete(filter, options);
}
async deleteGitRepo(filter, options) {
const app = await this.findOne(filter, { populate: ["gitProvider"] });
if (!app)
throw new Error(`Unable to delete: App not found.`);
// permissions
(0, user_utils_1.checkAppPermissions)(app, this.user);
const provider = app.gitProvider;
const repoData = await (0, git_utils_1.parseGitRepoDataFromRepoSSH)(app.git.repoSSH);
if (!repoData)
throw new Error(`Unable to read repo data of "${app.slug}" app: ${app.git.repoSSH}`);
// delete git repo via API
const { GitProviderService } = await Promise.resolve().then(() => __importStar(require("./index")));
const gitSvc = new GitProviderService(this.ownership);
return gitSvc.deleteGitRepository(provider, repoData.repoSlug, options);
}
async takeDown(app, options) {
// validate
if (!app.deployEnvironment)
throw new Error(`Unable to take down "${app.slug}" app, no deploy environtments found.`);
// initialize
const { DeployEnvironmentService } = await Promise.resolve().then(() => __importStar(require("../services")));
const deployEnvSvc = new DeployEnvironmentService();
// permissions
(0, user_utils_1.checkAppPermissions)(app, this.user);
// take down all deploy environments
const deployEnvs = Object.keys(app.deployEnvironment);
console.log("AppSvc.takeDown() > deployEnvs :>> ", deployEnvs);
await Promise.all(deployEnvs.map((env) => deployEnvSvc.takeDownDeployEnvironment(app, env, options)));
return app;
}
async archiveApp(app, ownership) {
const { DeployEnvironmentService } = await Promise.resolve().then(() => __importStar(require("../services")));
const deployEnvSvc = new DeployEnvironmentService();
// permissions
(0, user_utils_1.checkAppPermissions)(app, this.user);
// take down all deploy environments
const deployEnvs = Object.keys(app.deployEnvironment);
await Promise.all(deployEnvs.map((env) => deployEnvSvc.takeDownDeployEnvironment(app, env)));
// update database
const archivedApp = await this.updateOne({ _id: app._id }, { archivedAt: new Date() });
return archivedApp;
}
async unarchiveApp(app, ownership) {
// permissions
(0, user_utils_1.checkAppPermissions)(app, this.user);
// update database
const unarchivedApp = await this.updateOne({ _id: app._id }, { $unset: { archivedAt: true } }, { raw: true });
return unarchivedApp;
}
/**
* Get all users that participated in this app.
*/
async getParticipants(app, options) {
const { BuildService, UserService } = await Promise.resolve().then(() => __importStar(require("./index")));
const buildSvc = new BuildService();
const userSvc = new UserService();
buildSvc.ownership = this.ownership;
const listOwners = await buildSvc.distinct("owner", { app: app._id });
const ids = listOwners.map((item) => item.owner);
return userSvc.find({ _id: { $in: ids } }, { select: mask_sensitive_info_1.basicUserFields }, options);
}
}
exports.AppService = AppService;