Skip to content

Commit

Permalink
refactor: replace command inputs by dictionary-like data abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
micalevisk committed Jul 16, 2023
1 parent b262fad commit fcda32b
Show file tree
Hide file tree
Showing 18 changed files with 165 additions and 159 deletions.
4 changes: 2 additions & 2 deletions actions/abstract.action.ts
@@ -1,9 +1,9 @@
import { Input } from '../commands';
import { Input, CommandInputsContainer } from '../commands';

export abstract class AbstractAction {
public abstract handle(
inputs?: Input[],
options?: Input[],
options?: CommandInputsContainer,
extraFlags?: string[],
): Promise<void>;
}
14 changes: 8 additions & 6 deletions actions/add.action.ts
@@ -1,5 +1,5 @@
import * as chalk from 'chalk';
import { Input } from '../commands';
import { CommandInputsContainer, Input } from '../commands';
import { getValueOrDefault } from '../lib/compiler/helpers/get-value-or-default';
import {
AbstractPackageManager,
Expand All @@ -23,7 +23,7 @@ import { AbstractAction } from './abstract.action';
const schematicName = 'nest-add';

export class AddAction extends AbstractAction {
public async handle(inputs: Input[], options: Input[], extraFlags: string[]) {
public async handle(inputs: Input[], options: CommandInputsContainer, extraFlags: string[]) {
const libraryName = this.getLibraryName(inputs);
const packageName = this.getPackageName(libraryName);
const collectionName = this.getCollectionName(libraryName, packageName);
Expand All @@ -33,9 +33,11 @@ export class AddAction extends AbstractAction {
skipInstall || (await this.installPackage(collectionName, tagName));
if (packageInstallSuccess) {
const sourceRootOption: Input = await this.getSourceRoot(
inputs.concat(options),
inputs.concat(options.toArray()),
);
options.push(sourceRootOption);
if (sourceRootOption) {
options.addInput(sourceRootOption)
}

await this.addLibrary(collectionName, options, extraFlags);
} else {
Expand Down Expand Up @@ -117,15 +119,15 @@ export class AddAction extends AbstractAction {

private async addLibrary(
collectionName: string,
options: Input[],
options: CommandInputsContainer,
extraFlags: string[],
) {
console.info(MESSAGES.LIBRARY_INSTALLATION_STARTS);
const schematicOptions: SchematicOption[] = [];
schematicOptions.push(
new SchematicOption(
'sourceRoot',
options.find((option) => option.name === 'sourceRoot')!.value as string,
options.resolveInput<string>('sourceRoot', true).value,
),
);
const extraFlagsString = extraFlags ? extraFlags.join(' ') : undefined;
Expand Down
36 changes: 11 additions & 25 deletions actions/build.action.ts
@@ -1,7 +1,7 @@
import * as chalk from 'chalk';
import { join } from 'path';
import * as ts from 'typescript';
import { Input } from '../commands';
import { Input, CommandInputsContainer } from '../commands';
import { AssetsManager } from '../lib/compiler/assets-manager';
import { Compiler } from '../lib/compiler/compiler';
import { getBuilder } from '../lib/compiler/helpers/get-builder';
Expand Down Expand Up @@ -40,19 +40,10 @@ export class BuildAction extends AbstractAction {
protected readonly assetsManager = new AssetsManager();
protected readonly workspaceUtils = new WorkspaceUtils();

public async handle(commandInputs: Input[], commandOptions: Input[]) {
public async handle(commandInputs: Input[], commandOptions: CommandInputsContainer) {
try {
const watchModeOption = commandOptions.find(
(option) => option.name === 'watch',
);
const watchMode = !!(watchModeOption && watchModeOption.value);

const watchAssetsModeOption = commandOptions.find(
(option) => option.name === 'watchAssets',
);
const watchAssetsMode = !!(
watchAssetsModeOption && watchAssetsModeOption.value
);
const watchMode = !!commandOptions.resolveInput<boolean>('watch')?.value;
const watchAssetsMode = !!commandOptions.resolveInput<boolean>('watchAssets')?.value;

await this.runBuild(
commandInputs,
Expand All @@ -72,15 +63,13 @@ export class BuildAction extends AbstractAction {

public async runBuild(
commandInputs: Input[],
commandOptions: Input[],
commandOptions: CommandInputsContainer,
watchMode: boolean,
watchAssetsMode: boolean,
isDebugEnabled = false,
onSuccess?: () => void,
) {
const configFileName = commandOptions.find(
(option) => option.name === 'config',
)!.value as string;
const configFileName = commandOptions.resolveInput<string>('config', true).value
const configuration = await this.loader.load(configFileName);
const appName = commandInputs.find((input) => input.name === 'app')!
.value as string;
Expand Down Expand Up @@ -155,7 +144,7 @@ export class BuildAction extends AbstractAction {
appName: string,
pathToTsconfig: string,
watchMode: boolean,
options: Input[],
options: CommandInputsContainer,
tsOptions: ts.CompilerOptions,
onSuccess: (() => void) | undefined,
) {
Expand Down Expand Up @@ -183,7 +172,7 @@ export class BuildAction extends AbstractAction {
private runWebpack(
configuration: Required<Configuration>,
appName: string,
commandOptions: Input[],
commandOptions: CommandInputsContainer,
pathToTsconfig: string,
debug: boolean,
watchMode: boolean,
Expand Down Expand Up @@ -216,7 +205,7 @@ export class BuildAction extends AbstractAction {

private runTsc(
watchMode: boolean,
options: Input[],
options: CommandInputsContainer,
configuration: Required<Configuration>,
pathToTsconfig: string,
appName: string,
Expand All @@ -228,15 +217,12 @@ export class BuildAction extends AbstractAction {
this.tsConfigProvider,
this.tsLoader,
);
const isPreserveWatchOutputEnabled = options.find(
(option) =>
option.name === 'preserveWatchOutput' && option.value === true,
);
const isPreserveWatchOutputEnabled = options.resolveInput<boolean>('preserveWatchOutput')?.value || false
watchCompiler.run(
configuration,
pathToTsconfig,
appName,
{ preserveWatchOutput: !!isPreserveWatchOutputEnabled },
{ preserveWatchOutput: isPreserveWatchOutputEnabled },
onSuccess,
);
} else {
Expand Down
6 changes: 3 additions & 3 deletions actions/generate.action.ts
@@ -1,6 +1,6 @@
import * as chalk from 'chalk';
import { Answers } from 'inquirer';
import { Input } from '../commands';
import { Input, CommandInputsContainer } from '../commands';
import { getValueOrDefault } from '../lib/compiler/helpers/get-value-or-default';
import {
AbstractCollection,
Expand All @@ -21,8 +21,8 @@ import {
import { AbstractAction } from './abstract.action';

export class GenerateAction extends AbstractAction {
public async handle(inputs: Input[], options: Input[]) {
await generateFiles(inputs.concat(options));
public async handle(inputs: Input[], options: CommandInputsContainer) {
await generateFiles(inputs.concat(options.toArray()));
}
}

Expand Down
46 changes: 19 additions & 27 deletions actions/new.action.ts
Expand Up @@ -4,7 +4,7 @@ import * as fs from 'fs';
import * as inquirer from 'inquirer';
import { Answers, Question } from 'inquirer';
import { join } from 'path';
import { Input } from '../commands';
import { CommandInputsContainer, Input } from '../commands';
import { defaultGitIgnore } from '../lib/configuration/defaults';
import {
AbstractPackageManager,
Expand All @@ -24,22 +24,16 @@ import { normalizeToKebabOrSnakeCase } from '../lib/utils/formatting';
import { AbstractAction } from './abstract.action';

export class NewAction extends AbstractAction {
public async handle(inputs: Input[], options: Input[]) {
const directoryOption = options.find(
(option) => option.name === 'directory',
);
const dryRunOption = options.find((option) => option.name === 'dry-run');
const isDryRunEnabled = dryRunOption && dryRunOption.value;
public async handle(inputs: Input[], options: CommandInputsContainer) {
const directoryOption = options.resolveInput<string>('directory');
const dryRunOption = options.resolveInput<boolean>('dry-run');
const isDryRunEnabled = !!dryRunOption?.value;

await askForMissingInformation(inputs, options);
await generateApplicationFiles(inputs, options).catch(exit);

const shouldSkipInstall = options.some(
(option) => option.name === 'skip-install' && option.value === true,
);
const shouldSkipGit = options.some(
(option) => option.name === 'skip-git' && option.value === true,
);
const shouldSkipInstall = options.resolveInput<boolean>('skip-install')?.value
const shouldSkipGit = options.resolveInput<boolean>('skip-git')?.value;
const projectDirectory = getProjectDirectory(
getApplicationNameInput(inputs)!,
directoryOption,
Expand Down Expand Up @@ -67,9 +61,6 @@ export class NewAction extends AbstractAction {
const getApplicationNameInput = (inputs: Input[]) =>
inputs.find((input) => input.name === 'name');

const getPackageManagerInput = (inputs: Input[]) =>
inputs.find((options) => options.name === 'packageManager');

const getProjectDirectory = (
applicationName: Input,
directoryOption?: Input,
Expand All @@ -80,7 +71,7 @@ const getProjectDirectory = (
);
};

const askForMissingInformation = async (inputs: Input[], options: Input[]) => {
const askForMissingInformation = async (inputs: Input[], options: CommandInputsContainer) => {
console.info(MESSAGES.PROJECT_INFORMATION_START);
console.info();

Expand All @@ -94,33 +85,34 @@ const askForMissingInformation = async (inputs: Input[], options: Input[]) => {
replaceInputMissingInformation(inputs, answers);
}

const packageManagerInput = getPackageManagerInput(options);
if (!packageManagerInput!.value) {
const packageManagerInput = options.resolveInput<string>('packageManager')
if (!packageManagerInput?.value) {
const answers = await askForPackageManager();
replaceInputMissingInformation(options, answers);
}
};

const replaceInputMissingInformation = (
inputs: Input[],
inputs: Input[] | CommandInputsContainer,
answers: Answers,
): Input[] => {
if (!Array.isArray(inputs)) {
inputs = inputs.toArray()
}
return inputs.map(
(input) =>
(input.value =
input.value !== undefined ? input.value : answers[input.name]),
);
};

const generateApplicationFiles = async (args: Input[], options: Input[]) => {
const collectionName = options.find(
(option) => option.name === 'collection' && option.value != null,
)!.value;
const generateApplicationFiles = async (args: Input[], options: CommandInputsContainer) => {
const collectionName = options.resolveInput<string>('collection', true)?.value
const collection: AbstractCollection = CollectionFactory.create(
(collectionName as Collection) || Collection.NESTJS,
);
const schematicOptions: SchematicOption[] = mapSchematicOptions(
args.concat(options),
args.concat(options.toArray()),
);
await collection.execute('application', schematicOptions);
console.info();
Expand All @@ -139,11 +131,11 @@ const mapSchematicOptions = (options: Input[]): SchematicOption[] => {
};

const installPackages = async (
options: Input[],
options: CommandInputsContainer,
dryRunMode: boolean,
installDirectory: string,
) => {
const inputPackageManager = getPackageManagerInput(options)!.value as string;
const inputPackageManager = options.resolveInput<string>('packageManager', true).value;

let packageManager: AbstractPackageManager;
if (dryRunMode) {
Expand Down
25 changes: 6 additions & 19 deletions actions/start.action.ts
Expand Up @@ -3,7 +3,7 @@ import { spawn } from 'child_process';
import * as fs from 'fs';
import { join } from 'path';
import * as killProcess from 'tree-kill';
import { Input } from '../commands';
import { Input, CommandInputsContainer } from '../commands';
import { getTscConfigPath } from '../lib/compiler/helpers/get-tsc-config.path';
import { getValueOrDefault } from '../lib/compiler/helpers/get-value-or-default';
import {
Expand All @@ -15,11 +15,9 @@ import { treeKillSync as killProcessSync } from '../lib/utils/tree-kill';
import { BuildAction } from './build.action';

export class StartAction extends BuildAction {
public async handle(commandInputs: Input[], commandOptions: Input[]) {
public async handle(commandInputs: Input[], commandOptions: CommandInputsContainer) {
try {
const configFileName = commandOptions.find(
(option) => option.name === 'config',
)!.value as string;
const configFileName = commandOptions.resolveInput<string>('config', true).value;
const configuration = await this.loader.load(configFileName);
const appName = commandInputs.find((input) => input.name === 'app')!
.value as string;
Expand All @@ -30,20 +28,9 @@ export class StartAction extends BuildAction {
appName,
);

const debugModeOption = commandOptions.find(
(option) => option.name === 'debug',
);
const watchModeOption = commandOptions.find(
(option) => option.name === 'watch',
);
const isWatchEnabled = !!(watchModeOption && watchModeOption.value);
const watchAssetsModeOption = commandOptions.find(
(option) => option.name === 'watchAssets',
);
const isWatchAssetsEnabled = !!(
watchAssetsModeOption && watchAssetsModeOption.value
);
const debugFlag = debugModeOption && debugModeOption.value;
const isWatchEnabled = !!commandOptions.resolveInput<boolean>('watch')?.value;
const isWatchAssetsEnabled = !!commandOptions.resolveInput<boolean>('watchAssets')?.value;
const debugFlag = commandOptions.resolveInput<boolean>('debug')?.value;
const binaryToRun = getValueOrDefault(
configuration,
'exec',
Expand Down
13 changes: 7 additions & 6 deletions commands/add.command.ts
@@ -1,7 +1,7 @@
import { Command, CommanderStatic } from 'commander';
import { getRemainingFlags } from '../lib/utils/remaining-flags';
import { AbstractCommand } from './abstract.command';
import { Input } from './command.input';
import { Input, CommandInputsContainer } from './command.input';

export class AddCommand extends AbstractCommand {
public load(program: CommanderStatic): void {
Expand All @@ -17,10 +17,11 @@ export class AddCommand extends AbstractCommand {
.option('-p, --project [project]', 'Project in which to generate files.')
.usage('<library> [options] [library-specific-options]')
.action(async (library: string, command: Command) => {
const options: Input[] = [];
options.push({ name: 'dry-run', value: !!command.dryRun });
options.push({ name: 'skip-install', value: command.skipInstall });
options.push({
const commandOptions = new CommandInputsContainer();

commandOptions.addInput({ name: 'dry-run', value: !!command.dryRun });
commandOptions.addInput({ name: 'skip-install', value: command.skipInstall });
commandOptions.addInput({
name: 'project',
value: command.project,
});
Expand All @@ -30,7 +31,7 @@ export class AddCommand extends AbstractCommand {

const flags = getRemainingFlags(program);
try {
await this.action.handle(inputs, options, flags);
await this.action.handle(inputs, commandOptions, flags);
} catch (err) {
process.exit(1);
}
Expand Down

0 comments on commit fcda32b

Please sign in to comment.