UNPKG

clever-tools

Version:

Command Line Interface for Clever Cloud.

188 lines (161 loc) 6 kB
import _ from 'lodash'; import { promises as fs } from 'node:fs'; import path from 'node:path'; import { slugify } from '../lib/slugify.js'; import { styleText } from '../lib/style-text.js'; import { Logger } from '../logger.js'; import { conf } from './configuration.js'; import * as User from './user.js'; // TODO: Maybe use fs-utils findPath() export async function loadApplicationConf(ignoreParentConfig = false, pathToFolder) { if (pathToFolder == null) { pathToFolder = path.dirname(conf.APP_CONFIGURATION_FILE); } const fileName = path.basename(conf.APP_CONFIGURATION_FILE); const fullPath = path.join(pathToFolder, fileName); Logger.debug('Loading app configuration from ' + fullPath); try { const contents = await fs.readFile(fullPath); return JSON.parse(contents); } catch (error) { Logger.info('Cannot load app configuration from ' + conf.APP_CONFIGURATION_FILE + ' (' + error + ')'); if (ignoreParentConfig || path.parse(pathToFolder).root === pathToFolder) { return { apps: [] }; } return loadApplicationConf(ignoreParentConfig, path.normalize(path.join(pathToFolder, '..'))); } } export async function addLinkedApplication(appData, alias, ignoreParentConfig) { const currentConfig = await loadApplicationConf(ignoreParentConfig); const appEntry = { app_id: appData.id, org_id: appData.ownerId, deploy_url: appData.deployment.httpUrl || appData.deployment.url, git_ssh_url: appData.deployment.url, name: appData.name, alias: alias || slugify(appData.name), }; const isPresent = currentConfig.apps.find((app) => app.app_id === appEntry.app_id) != null; if (isPresent) { throw new Error( `Application ${styleText('red', appEntry.app_id)} is already linked with alias ${styleText('red', appEntry.alias)}`, ); } currentConfig.apps.push(appEntry); return persistConfig(currentConfig).then(() => { return appEntry; }); } export async function removeLinkedApplication({ appId, alias }) { const currentConfig = await loadApplicationConf(); const appToUnlink = currentConfig.apps.find((a) => a.app_id === appId || a.alias === alias); if (appToUnlink == null) { return false; } const newConfig = { ...currentConfig, apps: currentConfig.apps.filter((a) => a !== appToUnlink), }; const isDefault = currentConfig.default === appToUnlink.app_id; if (isDefault) { delete newConfig.default; } await persistConfig(newConfig); return true; } export function findApp(config, alias) { if (_.isEmpty(config.apps)) { throw new Error('There is no linked or targeted application. Use `--app` option or `clever link` command.'); } if (alias != null) { const [appByAlias, secondAppByAlias] = _.filter(config.apps, { alias }); if (appByAlias == null) { throw new Error(`There are no applications matching alias ${alias}`); } if (secondAppByAlias != null) { throw new Error( `There are several applications matching alias ${alias}. This should not happen, your \`.clever.json\` should be fixed.`, ); } return appByAlias; } return findDefaultApp(config); } export function checkAlreadyLinked(apps, name, alias) { const appAliasExists = apps.some((app) => app.alias != null && app.alias === alias); if (appAliasExists) { throw new Error(`An application is already linked with the alias '${alias}'`); } const appNameExists = apps.some((app) => app.name === name); if (appNameExists) { throw new Error(`An application is already linked with the name '${name}'`); } } function findDefaultApp(config) { if (_.isEmpty(config.apps)) { throw new Error('There is no linked or targeted application. Use `--app` option or `clever link` command.'); } if (config.default != null) { const defaultApp = _.find(config.apps, { app_id: config.default }); if (defaultApp == null) { throw new Error( 'The default application is not listed anymore. This should not happen, your `.clever.json` should be fixed.', ); } return defaultApp; } if (config.apps.length === 1) { return config.apps[0]; } const aliases = _.map(config.apps, 'alias').join(', '); throw new Error( `Several applications are linked. You can specify one with the "--alias" option. Run "clever applications" to list linked applications. Available aliases: ${aliases}`, ); } async function getAppDetailsForId(appId) { const config = await loadApplicationConf(); if (_.isEmpty(config.apps)) { throw new Error('There is no linked or targeted application. Use `--app` option or `clever link` command.'); } const [appById, secondAppById] = _.filter(config.apps, { app_id: appId }); if (appById == null) { throw new Error(`There are no applications matching id '${appId}'`); } if (secondAppById != null) { throw new Error( `There are several applications matching id '${appId}'.` + 'This should not happen, your `.clever.json` should be fixed.', ); } return appById; } export async function getAppDetails({ alias }) { const config = await loadApplicationConf(); const app = findApp(config, alias); const ownerId = app.org_id != null ? app.org_id : await User.getCurrentId(); return { appId: app.app_id, ownerId: ownerId, deployUrl: app.deploy_url, name: app.name, alias: app.alias, }; } export async function getMostNaturalName(appId) { try { const details = await getAppDetailsForId(appId); return details.alias || details.name || appId; } catch { return appId; } } function persistConfig(modifiedConfig) { const jsonContents = JSON.stringify(modifiedConfig, null, 2); return fs.writeFile(conf.APP_CONFIGURATION_FILE, jsonContents); } export async function setDefault(alias) { const config = await loadApplicationConf(); const app = findApp(config, alias); const newConfig = { ...config, default: app.app_id }; return persistConfig(newConfig); }