Skip to content

Commit

Permalink
refactor: implment stage-runner
Browse files Browse the repository at this point in the history
  • Loading branch information
hankchiutw committed Apr 24, 2021
1 parent 718c7dc commit 6693db6
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 53 deletions.
68 changes: 15 additions & 53 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Command, flags } from '@oclif/command';
import execa from 'execa';
import * as fse from 'fs-extra';
import * as inquirer from 'inquirer';
import { bold, underline } from 'kleur';
import ora from 'ora';
import { renderToFolder } from 'template-file';
import {
Params,
ParamsContext,
PROMPT_CONFIGS,
paramArgs,
paramFlags,
} from './params';
import { StageRunner, Stage } from './stage-runner';

class CreateKromeApp extends Command {
static description = 'Generate the krome starter app';
Expand All @@ -26,23 +24,16 @@ class CreateKromeApp extends Command {

// TODO: better way to inject {@link ParamsContext}
context: ParamsContext = ParamsContext.create();
stageRunner: StageRunner = new StageRunner(this.context);
spinner = ora({ indent: 2 });

async run(): Promise<void> {
await this.initContext();
this.configStageRunner();

this.log('');

await this.copyFiles();
this.log('');

await this.renderTemplates();
this.log('');

if (this.context.doInstall) {
await this.installDependencies();
this.log('');
}
await this.stageRunner.runAll();

this.log(bold(underline('Quickstart')));
this.log('');
Expand All @@ -56,46 +47,6 @@ class CreateKromeApp extends Command {
Object.assign(this.context, params);
}

async copyFiles(): Promise<void> {
const { baseDir, sourceDir, frameworkDir, targetDir } = this.context;
this.spinner.text = 'Copy files';

await fse.copy(baseDir, targetDir);
await fse.copy(sourceDir, targetDir);
await fse.copy(frameworkDir, targetDir);

this.spinner.succeed();
}

async renderTemplates(): Promise<void> {
const { appName, author, description } = this.context;
this.spinner.text = 'Render templates';

// TODO: create PR on template-file
await renderToFolder(
`${this.context.targetDir}/*.*`,
this.context.targetDir,
{ appName, author, description },
);
await renderToFolder(
`${this.context.targetDir}/LICENSE`,
this.context.targetDir,
{ appName, author, description },
);
await renderToFolder(
`${this.context.targetDir}/src/*.*`,
`${this.context.targetDir}/src`,
{ appName, author, description },
);
this.spinner.succeed();
}

async installDependencies(): Promise<void> {
await execa('yarn', [], { cwd: this.context.targetDir, stdio: 'inherit' });
this.spinner.text = 'Install dependencies';
this.spinner.succeed();
}

/**
* Collect all the required information from args, flags, or prompt
*/
Expand Down Expand Up @@ -134,6 +85,17 @@ class CreateKromeApp extends Command {
...safeParams,
};
}

configStageRunner(): void {
this.stageRunner.beforeEach = (stage: Stage) => {
this.spinner.text = stage.label;
};

this.stageRunner.afterEach = () => {
this.spinner.succeed();
this.log('');
};
}
}

export = CreateKromeApp;
2 changes: 2 additions & 0 deletions src/stage-runner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './interfaces';
export * from './stage-runner';
7 changes: 7 additions & 0 deletions src/stage-runner/interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ParamsContext } from '../params';

export interface Stage {
label: string;
callback: (context: ParamsContext) => Promise<unknown>;
shouldRun?: (context: ParamsContext) => boolean;
}
43 changes: 43 additions & 0 deletions src/stage-runner/stage-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { ParamsContext } from '../params';
import type { Stage } from './interfaces';
import { copyFiles, renderTemplates, installDependencies } from './stages';

export class StageRunner {
beforeEach: (stage: Stage) => void = () => null;
afterEach: (stage: Stage) => void = () => null;

private stages: Stage[] = [];

constructor(private context: ParamsContext) {
this.initStages();
}

async runAll(): Promise<void> {
for (const stage of this.stages) {
const shouldRun = stage.shouldRun || (() => true);
this.beforeEach(stage);
if (shouldRun(this.context)) {
await stage.callback(this.context);
}
this.afterEach(stage);
}
}

private initStages() {
this.stages = [
{
label: 'Copy files',
callback: copyFiles,
},
{
label: 'Render templates',
callback: renderTemplates,
},
{
label: 'Install dependencies',
callback: installDependencies,
shouldRun: () => this.context.doInstall,
},
];
}
}
10 changes: 10 additions & 0 deletions src/stage-runner/stages/copyFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as fse from 'fs-extra';
import type { ParamsContext } from '../../params';

export async function copyFiles(context: ParamsContext): Promise<void> {
const { baseDir, sourceDir, frameworkDir, targetDir } = context;

await fse.copy(baseDir, targetDir);
await fse.copy(sourceDir, targetDir);
await fse.copy(frameworkDir, targetDir);
}
3 changes: 3 additions & 0 deletions src/stage-runner/stages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './copyFiles';
export * from './renderTemplates';
export * from './installDependencies';
8 changes: 8 additions & 0 deletions src/stage-runner/stages/installDependencies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import execa from 'execa';
import type { ParamsContext } from '../../params';

export async function installDependencies(
context: ParamsContext,
): Promise<void> {
await execa('yarn', [], { cwd: context.targetDir, stdio: 'inherit' });
}
23 changes: 23 additions & 0 deletions src/stage-runner/stages/renderTemplates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { renderToFolder } from 'template-file';
import type { ParamsContext } from '../../params';

export async function renderTemplates(context: ParamsContext): Promise<void> {
const { appName, author, description, targetDir } = context;

// TODO: create PR on template-file
await renderToFolder(`${targetDir}/*.*`, targetDir, {
appName,
author,
description,
});
await renderToFolder(`${targetDir}/LICENSE`, targetDir, {
appName,
author,
description,
});
await renderToFolder(`${targetDir}/src/*.*`, `${targetDir}/src`, {
appName,
author,
description,
});
}

0 comments on commit 6693db6

Please sign in to comment.