Skip to content

Commit

Permalink
feat: Add clean and environment commands
Browse files Browse the repository at this point in the history
  • Loading branch information
angelmadames committed Feb 16, 2024
1 parent 086c9d9 commit bbb0e6a
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 45 deletions.
4 changes: 4 additions & 0 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Command } from 'commander';
import { configCommand } from './src/commands/config';
import { setupCommand } from './src/commands/setup';
import { cloneCommand } from './src/commands/clone';
import { cleanCommand } from './src/commands/clean';
import { environmentCommand } from './src/commands/environment';

const cli = new Command();

Expand All @@ -14,5 +16,7 @@ cli
.addCommand(configCommand())
.addCommand(setupCommand())
.addCommand(cloneCommand())
.addCommand(cleanCommand())
.addCommand(environmentCommand())

cli.parse();
35 changes: 35 additions & 0 deletions src/commands/clean/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Command } from 'commander';
import { projectConfig } from '../../config/project';
import { deletePath } from '../../utils/file-system';
import log from '../../utils/log';
import sharedOptions from '../../utils/shared-options';

export const cleanCommand = () => {
const command = new Command();
const config = projectConfig();

command
.name('clean')
.summary('Cleanup DEMS-managed resources')
.description(
'Cleans all configured resources and services initialized\n' +
'by DEMS. Resets your local development environment.',
)
.addOption(sharedOptions.force().default(false))
.action(async (options) => {
log.info('Cleaning DEMS-related resources...');
if (options.force) {
log.info('User interactivity disabled due to --force flag.');
}

await deletePath({ path: config.paths.repos_root, force: options.force });
await deletePath({ path: config.paths.data, force: options.force });
await deletePath({ path: config.paths.env_file, force: options.force });

log.success('Clean completed for current project.');
});

return command;
};

export default cleanCommand();
6 changes: 2 additions & 4 deletions src/commands/clone/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import chalk from 'chalk';
import { Command } from 'commander';
import { projectConfig, projectEnvVars } from '../../config/project';
import { projectConfig } from '../../config/project';
import Git from '../../utils/git';
import log from '../../utils/log';
import sharedOptions from '../../utils/shared-options';

export const cloneCommand = () => {
Expand All @@ -19,7 +17,7 @@ export const cloneCommand = () => {
.addOption(sharedOptions.gitRef().default(config.git.default_ref))
.addOption(sharedOptions.reposRoot().default(config.paths.repos_root))
.addOption(sharedOptions.gitOrg().default(config.git.org_url))
.addOption(sharedOptions.repos())
.addOption(sharedOptions.repos().default(config.repositories))
.addOption(sharedOptions.info())
.action((options) => {
console.log(`Git org > ${options.gitOrg}`);
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import fs from 'node:fs';
import { Command } from 'commander';
import cliConfig from '../../config/cli';
import { createFile, createPath } from '../../utils/file-system';
import log from '../../utils/log';
import { currentProjectCommand } from './current-project';
import { projectConfigCommand } from './project';
import fs from 'node:fs';

export const configCommand = () => {
const command = new Command();
Expand Down
37 changes: 37 additions & 0 deletions src/commands/environment/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Command } from 'commander';
import { projectConfig, projectEnvVars } from '../../config/project';
import { deletePath } from '../../utils/file-system';
import log from '../../utils/log';
import sharedOptions from '../../utils/shared-options';
import dotEnv from '../../config/env';

export const environmentCommand = () => {
const command = new Command();
const config = projectConfig();

command
.name('environment')
.alias('env')
.summary('Updates application environment config (.env)')
.description(
'Apps are run in different environments throughout their development\n' +
"life cycle. To ensure their configuration matches what's\n" +
'expected for DEMS, we override some of the default env settings.',
)
.option(
'-g, --generate-dot-env',
"Generates the dot env file for current project's config.json",
)
.action(async (options) => {
if (options.generateDotEnv) {
log.info('Generating project\'s dot env file...');
dotEnv.generate(config.paths.env_file, config);
} else {
console.log(projectEnvVars());
};
});

return command;
};

export default environmentCommand();
37 changes: 17 additions & 20 deletions src/commands/setup/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import fs from 'node:fs';
import { homedir } from 'node:os';
import { confirm, input } from '@inquirer/prompts';
import { file } from 'bun';
import chalk from 'chalk';
import { Command } from 'commander';
import cliConfig from '../../config/cli';
import {
type DEMSProjectConfig,
defaultConfig,
demsEnvVars,
} from '../../config/dems';
import { defaultConfig, demsEnvVars } from '../../config/dems';
import dotEnv from '../../config/env';
import { createFile, createPath, isFile } from '../../utils/file-system';
import log from '../../utils/log';
Expand Down Expand Up @@ -41,11 +36,9 @@ export const setupCommand = () => {
)
.action(async (options) => {
log.info('Welcome to the DEMS CLI setup process!');
log.warning(
`${chalk.dim(
'If DEMS has been initialized for another project, CLI config files\n' +
'will not be touched by default. Use --override to re-create them.',
)}`,
log.dimmedWarning(
'If DEMS has been initialized for another project, CLI config files\n' +
'will not be touched by default. Use --override to re-create them.',
);
log.info('Creating initial files for DEMS...');
createPath(cliConfig.root);
Expand All @@ -59,10 +52,13 @@ export const setupCommand = () => {

const currentProject = await input({
message: 'What is the name of project DEMS will manage?',
default: demsEnvVars.projectName || options.projectName || 'demo',
default:
demsEnvVars.projectName ||
options.projectName ||
cliConfig.currentProject ||
'demo',
});
fs.writeFileSync(cliConfig.currentProjectFile, currentProject);
createPath(`${cliConfig.root}/${currentProject}`);
const projectRootPath = `${cliConfig.root}/${currentProject}`;
config.compose.project_name = currentProject;

const reposRoot = await input({
Expand Down Expand Up @@ -105,17 +101,15 @@ export const setupCommand = () => {
default:
demsEnvVars.envFilePath ||
options.dotEnv ||
`${cliConfig.root}/${currentProject}/.env`,
`${projectRootPath}/.env`,
});
config.paths.env_file = dotEnvFile;

const dataPath = await input({
message:
'What would be the directory to store all project persistent data?',
default:
demsEnvVars.dataPath ||
options.dataPath ||
`${cliConfig.root}/${currentProject}/data`,
demsEnvVars.dataPath || options.dataPath || `${projectRootPath}/data`,
});
config.paths.data = dataPath;

Expand All @@ -127,7 +121,7 @@ export const setupCommand = () => {
message: 'Create config file (.env) using provided values?',
});
if (confirmConfig) {
const configJson = `${cliConfig.root}/${currentProject}/config.json`;
const configJson = `${projectRootPath}/config.json`;

let confirmOverride = false;
if (isFile(configJson)) {
Expand All @@ -137,11 +131,14 @@ export const setupCommand = () => {
});
}

fs.writeFileSync(cliConfig.currentProjectFile, currentProject);
createPath(`${projectRootPath}`);
createFile({
file: `${cliConfig.root}/${currentProject}/config.json`,
file: `${projectRootPath}/config.json`,
content: JSON.stringify(config, null, 2),
override: confirmOverride,
});
createPath(dataPath);
dotEnv.generate(dotEnvFile, config);
}
});
Expand Down
46 changes: 29 additions & 17 deletions src/utils/file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,40 @@ export const createPath = (path: string, verbose = true): void => {
}
};

interface PathDeletionParams {
path: string;
force?: boolean;
verbose?: boolean;
}

export const deletePath = async ({
path,
force = false,
verbose = true,
}: {
path: string;
force?: boolean;
verbose?: boolean;
}): Promise<void> => {
if (!isDirectory(path)) {
if (verbose)
log.warning(`⏩ Path: ${path} is not a valid directory. Not removing.`);
return;
}: PathDeletionParams) => {
if (isDirectory(path)) {
if (
force ||
(await confirm({ message: `Delete directory ${path} recursively?` }))
) {
fs.rmdirSync(path, { recursive: true });
if (verbose) log.success(`Directory ${path} deleted.`);
return;
}
}

if (
force ||
(await confirm({ message: `Delete path ${path} recursively?` }))
) {
fs.rmSync(path, { recursive: true, force: true });
if (verbose) log.success(`🗑️ Path: ${path} recursively deleted.`);
} else {
if (verbose) log.info('⏩ Skipping...');
if (isFile(path)) {
if (force || await confirm({
message: `Delete file ${path}?`,
})) {
fs.rmSync(path, { force: true });
if (verbose) log.success(`File ${path} deleted.`);
return;
}
}

if (verbose) {
log.info(`${path} is not a valid file or directory.`);
return;
}
};
2 changes: 1 addition & 1 deletion src/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class Git {

clone({ workingDir, repo, ref }: GitParams) {
this.remoteRepoExists(repo);
createPath(workingDir);
createPath(workingDir, false);
if (this.localRepoExists(this.repoPath)) {
log.warning(`Repo ${repo} already cloned.`);
} else {
Expand Down
4 changes: 4 additions & 0 deletions src/utils/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const log = {
console.log(chalk.yellow(text));
},

dimmedWarning: (...text: string[]): void => {
console.log(chalk.dim.yellow(text));
},

error: (...text: string[]): void => {
console.log(chalk.red(text));
},
Expand Down
11 changes: 10 additions & 1 deletion src/utils/shared-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ export const sharedOptions = {
);
},
repos() {
return new Option('-r, --repos [repos...]', 'Git repositories to clone');
return new Option(
'-r, --repos [repos...]',
'Git repositories to manage/operate',
);
},
force() {
return new Option(
'-f, --force',
'Prevents user interactivity and assumes default values',
).default(false);
},
};

Expand Down
2 changes: 1 addition & 1 deletion test/commands/config.current-project.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describe, expect, test } from 'bun:test';
import fs from 'node:fs';
import { spawnSync } from 'bun';
import { currentProjectCommand } from '../../src/commands/config/current-project';
import cliConfig from '../../src/config/cli';
import fs from 'node:fs';
import { createFile, createPath } from '../../src/utils/file-system';

describe("Command: 'config current-project'", () => {
Expand Down

0 comments on commit bbb0e6a

Please sign in to comment.