Skip to content

Commit 6b749c3

Browse files
committed
Added reporter factory and moved reporter initialization to base command class.
1 parent 2f6c6bb commit 6b749c3

10 files changed

Lines changed: 116 additions & 97 deletions

File tree

package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,45 @@
44
"codify": "./bin/run.js"
55
},
66
"dependencies": {
7+
"@inkjs/ui": "^1.0.0",
78
"@oclif/core": "^3",
89
"@oclif/plugin-help": "^5",
910
"@oclif/plugin-plugins": "^3.8.4",
10-
"semver": "^7.5.4",
11-
"codify-schemas": "1.0.32",
1211
"ajv": "^8.12.0",
1312
"ajv-formats": "^3.0.1",
14-
"tsx": "^4.7.3",
15-
"ink": "^4.4.1",
16-
"@inkjs/ui": "^1.0.0",
17-
"react": "^18.3.1",
1813
"chalk": "^5.3.0",
14+
"codify-schemas": "1.0.32",
15+
"debug": "^4.3.4",
16+
"ink": "^4.4.1",
1917
"parse-json": "^8.1.0",
20-
"debug": "^4.3.4"
18+
"react": "^18.3.1",
19+
"semver": "^7.5.4",
20+
"supports-color": "^9.4.0"
2121
},
2222
"description": "Codify is a set up as code tool for developers",
2323
"devDependencies": {
2424
"@oclif/prettier-config": "^0.2.1",
2525
"@oclif/test": "^3",
2626
"@types/chai": "^4",
2727
"@types/chai-as-promised": "^7.1.7",
28+
"@types/chalk": "^2.2.0",
29+
"@types/debug": "^4.1.12",
2830
"@types/mocha": "^9.0.0",
2931
"@types/mock-fs": "^4.13.3",
3032
"@types/node": "^18",
31-
"@types/semver": "^7.5.4",
3233
"@types/react": "^18.3.1",
33-
"@types/chalk": "^2.2.0",
34-
"@types/debug": "^4.1.12",
35-
"eslint-config-prettier": "^9.0.0",
34+
"@types/semver": "^7.5.4",
3635
"chai": "^4",
3736
"chai-as-promised": "^7.1.1",
3837
"eslint": "^8.51.0",
3938
"eslint-config-oclif": "^5",
4039
"eslint-config-oclif-typescript": "^3",
40+
"eslint-config-prettier": "^9.0.0",
4141
"mocha": "^10",
4242
"mock-fs": "^5.2.0",
4343
"oclif": "^4.5.7",
4444
"shx": "^0.3.3",
45-
"ts-node": "^10.9.1",
45+
"tsx": "^4.7.3",
4646
"typescript": "^5",
4747
"vitest": "^1.4.0"
4848
},

src/commands/apply/index.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import { Args, Command, Flags } from '@oclif/core'
2-
import chalk from 'chalk';
1+
import { Args, Flags } from '@oclif/core'
32
import { ResourceOperation } from 'codify-schemas';
43
import * as path from 'node:path';
54

65
import { ApplyOrchestrator } from '../../orchestrators/apply.js';
76
import { PlanOrchestrator } from '../../orchestrators/plan.js';
8-
import { DefaultReporter } from '../../ui/reporters/default-reporter.js';
7+
import { BaseCommand } from '../../common/base-command.js';
98

10-
export default class Apply extends Command {
9+
export default class Apply extends BaseCommand {
1110
static args = {
1211
file: Args.string({ description: 'file to read' }),
1312
}
@@ -23,14 +22,8 @@ export default class Apply extends Command {
2322
path: Flags.string({ char: 'p', description: 'path to project' }),
2423
}
2524

26-
protected async catch(err: Error): Promise<void> {
27-
console.log(chalk.red(err.message));
28-
process.exit(1);
29-
}
30-
3125
public async run(): Promise<void> {
3226
const { flags } = await this.parse(Apply)
33-
const reporter = new DefaultReporter()
3427

3528
if (flags.path) {
3629
this.log(`Applying Codify from: ${flags.path}`);
@@ -39,15 +32,15 @@ export default class Apply extends Command {
3932
const resolvedPath = path.resolve(flags.path ?? '.');
4033

4134
const planResult = await PlanOrchestrator.run(resolvedPath);
42-
reporter.displayPlan(planResult.plan);
35+
this.reporter.displayPlan(planResult.plan);
4336

4437
// Short circuit and exit if every change is NOOP
4538
if (planResult.plan.every((p) => p.operation === ResourceOperation.NOOP)) {
4639
console.log('No changes necessary. Exiting');
4740
return process.exit(0);
4841
}
4942

50-
const confirm = await reporter.promptApplyConfirmation()
43+
const confirm = await this.reporter.promptApplyConfirmation()
5144
if (!confirm) {
5245
return process.exit(0);
5346
}

src/commands/hello/index.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/commands/hello/world.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/commands/plan/index.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { Args, Command, Flags } from '@oclif/core'
2-
import chalk from 'chalk';
1+
import { Args, Flags } from '@oclif/core'
32
import * as path from 'node:path';
43

54
import { PlanOrchestrator } from '../../orchestrators/plan.js';
6-
import { DebugReporter } from '../../ui/reporters/debug-reporter.js';
5+
import { BaseCommand } from '../../common/base-command.js';
76

8-
export default class Plan extends Command {
7+
export default class Plan extends BaseCommand {
98
static args = {
109
file: Args.string({ description: 'file to read' }),
1110
}
@@ -16,11 +15,6 @@ export default class Plan extends Command {
1615
'<%= config.bin %> <%= command.id %>',
1716
]
1817

19-
protected async catch(err: Error): Promise<void> {
20-
console.log(chalk.red(err.message));
21-
process.exit(1);
22-
}
23-
2418
static flags = {
2519
// flag with no value (-f, --force)
2620
force: Flags.boolean({ char: 'f' }),
@@ -32,7 +26,6 @@ export default class Plan extends Command {
3226

3327
public async run(): Promise<void> {
3428
const { flags } = await this.parse(Plan)
35-
const reporter = new DebugReporter()
3629

3730
if (flags.path) {
3831
this.log(`Applying Codify from: ${flags.path}`);
@@ -41,7 +34,7 @@ export default class Plan extends Command {
4134
const resolvedPath = path.resolve(flags.path ?? '.');
4235

4336
const { plan } = await PlanOrchestrator.run(resolvedPath);
44-
reporter.displayPlan(plan);
37+
this.reporter.displayPlan(plan);
4538

4639
process.exit(0);
4740
}

src/commands/uninstall.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { Args, Command } from '@oclif/core'
2-
import chalk from 'chalk';
1+
import { Args } from '@oclif/core'
32

43
import { UninstallOrchestrator } from '../orchestrators/uninstall.js';
5-
import { DefaultReporter } from '../ui/reporters/default-reporter.js';
4+
import { BaseCommand } from '../common/base-command.js';
65

7-
export default class Uninstall extends Command {
6+
export default class Uninstall extends BaseCommand {
87
static description = 'describe the command here'
98

109
static examples = [
@@ -22,22 +21,13 @@ export default class Uninstall extends Command {
2221
}),
2322
}
2423

25-
protected async catch(err: Error): Promise<void> {
26-
console.log(chalk.red(err.message));
27-
process.exit(1);
28-
}
29-
3024
public async run(): Promise<void> {
3125
const { raw } = await this.parse(Uninstall)
32-
new DefaultReporter()
3326

3427
const args = raw
3528
.filter((r) => r.type === 'arg')
3629
.map((r) => r.input);
3730

38-
39-
// const name = flags.name ?? 'world'
40-
// this.log(`hello ${name} from /Users/kevinwang/Projects/codify2/codify/src/commands/uninstall.ts`)
4131
if (args.length === 0) {
4232
throw new Error('A resource id must be specified for uninstall. Ex: "codify uninstall homebrew"')
4333
}

src/common/base-command.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Command, Flags } from '@oclif/core';
2+
import { Reporter, ReporterFactory, ReporterType } from '../ui/reporters/reporter.js';
3+
import { FlagOutput } from '@oclif/core/lib/interfaces/parser.js';
4+
import createDebug from 'debug';
5+
import chalk from 'chalk';
6+
7+
export abstract class BaseCommand extends Command {
8+
9+
static enableJsonFlag = true;
10+
static baseFlags = {
11+
'output': Flags.option({
12+
default: 'default',
13+
char: 'o',
14+
options: ['plain', 'default', 'debug', 'json'],
15+
})(),
16+
'debug': Flags.boolean()
17+
}
18+
protected reporter!: Reporter;
19+
20+
public async init(): Promise<void> {
21+
await super.init();
22+
23+
const { flags } = await this.parse({
24+
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
25+
});
26+
27+
const reporterType = this.getReporterType(flags);
28+
this.reporter = ReporterFactory.create(reporterType)
29+
}
30+
31+
protected async catch(err: Error): Promise<void> {
32+
console.log(chalk.red(err.message));
33+
process.exit(1);
34+
}
35+
36+
private getReporterType(flags: FlagOutput): ReporterType {
37+
const debug = createDebug('codify');
38+
39+
if (debug.enabled || flags.debug) {
40+
createDebug.enable('*');
41+
return ReporterType.DEBUG;
42+
}
43+
44+
if (this.jsonEnabled()) {
45+
return ReporterType.JSON;
46+
}
47+
48+
if (flags.output) {
49+
switch (flags.output) {
50+
case 'debug':
51+
return ReporterType.DEBUG;
52+
case 'json':
53+
return ReporterType.JSON;
54+
case 'plain':
55+
return ReporterType.PLAIN;
56+
case 'default':
57+
return ReporterType.DEFAULT;
58+
}
59+
}
60+
61+
return ReporterType.DEFAULT;
62+
}
63+
}

src/ui/reporters/debug-reporter.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export class DebugReporter implements Reporter {
1212
private debuggerCache = new Map<string, Debugger>();
1313

1414
constructor() {
15-
ctx.on(Event.PLUGIN_STDOUT, (name, args) => this.getPluginDebug(name)(args));
16-
ctx.on(Event.PLUGIN_STDERR, (name, args) => this.getPluginDebug(name)(args));
15+
ctx.on(Event.PLUGIN_STDOUT, (name, args) => this.getDebug(name)(args));
16+
ctx.on(Event.PLUGIN_STDERR, (name, args) => this.getDebug(name)(args));
1717
ctx.on(Event.STDOUT, (args) => debug(args));
1818
ctx.on(Event.STDERR, (args) => debug(args));
1919
ctx.on(Event.DEBUG, (args) => debug(args));
@@ -35,11 +35,11 @@ export class DebugReporter implements Reporter {
3535
console.log(JSON.stringify(plan));
3636
}
3737

38-
private getPluginDebug(name: string): Debugger {
38+
private getDebug(name: string): Debugger {
3939
const debuggerName = `plugin:${name}`;
4040

4141
if (!this.debuggerCache.has(name)) {
42-
this.debuggerCache.set(name, createDebug(debuggerName));
42+
this.debuggerCache.set(name, createDebug(`plugin:${name}`));
4343
}
4444

4545
return this.debuggerCache.get(name)!;

src/ui/reporters/plain-reporter.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { Reporter } from './reporter.js';
77
export class PlainReporter implements Reporter {
88
private readonly rl = readline.createInterface(process.stdin, process.stdout);
99

10-
1110
constructor() {
1211
ctx.on(Event.OUTPUT, (...args) => console.log(...args))
1312
ctx.on(Event.PROCESS_START, (name) => console.log(name))

src/ui/reporters/reporter.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { PlanResponseData } from 'codify-schemas';
2+
import { DebugReporter } from './debug-reporter.js';
3+
import { PlainReporter } from './plain-reporter.js';
4+
import { DefaultReporter } from './default-reporter.js';
25

36
export enum RenderEvent {
47
LOG = 'log',
@@ -30,3 +33,25 @@ export interface Reporter {
3033

3134
promptApplyConfirmation(): Promise<boolean>
3235
}
36+
37+
export enum ReporterType {
38+
DEBUG,
39+
DEFAULT,
40+
PLAIN,
41+
JSON
42+
}
43+
44+
export class ReporterFactory {
45+
static create(type: ReporterType): Reporter {
46+
switch (type) {
47+
case ReporterType.DEBUG:
48+
return new DebugReporter();
49+
case ReporterType.PLAIN:
50+
return new PlainReporter();
51+
case ReporterType.JSON:
52+
return new DefaultReporter();
53+
default:
54+
return new DefaultReporter();
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)