Skip to content

Commit 73744b2

Browse files
committed
Added uninstall command
1 parent fc55291 commit 73744b2

15 files changed

Lines changed: 190 additions & 21 deletions

File tree

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ USAGE
4141
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin-1)
4242
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin-2)
4343
* [`codify plugins update`](#codify-plugins-update)
44+
* [`codify uninstall [RESOURCE]`](#codify-uninstall-resource)
4445

4546
## `codify apply [FILE]`
4647

@@ -400,4 +401,24 @@ DESCRIPTION
400401
```
401402

402403
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/update.ts)_
404+
405+
## `codify uninstall [RESOURCE]`
406+
407+
describe the command here
408+
409+
```
410+
USAGE
411+
$ codify uninstall [RESOURCE]
412+
413+
ARGUMENTS
414+
RESOURCE resource type to uninstall
415+
416+
DESCRIPTION
417+
describe the command here
418+
419+
EXAMPLES
420+
$ codify uninstall
421+
```
422+
423+
_See code: [src/commands/uninstall.ts](https://github.com/kevinwang5658/codify/blob/v0.0.0/src/commands/uninstall.ts)_
403424
<!-- commandsstop -->

src/commands/apply/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export default class Apply extends Command {
5151
await ApplyOrchestrator.run(planResult);
5252
} catch (error: unknown) {
5353
console.error(error);
54+
process.exit(1);
5455
}
5556

5657
process.exit(0);

src/commands/uninstall.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Args, Command } from '@oclif/core'
2+
import { UninstallOrchestrator } from '../orchestrators/uninstall.js';
3+
import { DefaultReporter } from '../ui/reporters/default-reporter.js';
4+
import { ctx } from '../events/context.js';
5+
6+
export default class Uninstall extends Command {
7+
static description = 'describe the command here'
8+
9+
static examples = [
10+
'<%= config.bin %> <%= command.id %>',
11+
]
12+
13+
static flags = {}
14+
15+
static strict = false;
16+
17+
static args = {
18+
resources: Args.string({
19+
description: 'A resource typeId for uninstalling. Ex: "codify uninstall homebrew"',
20+
required: true,
21+
}),
22+
}
23+
24+
public async run(): Promise<void> {
25+
const { raw } = await this.parse(Uninstall)
26+
new DefaultReporter()
27+
28+
const args = raw
29+
.filter((r) => r.type === 'arg')
30+
.map((r) => r.input);
31+
32+
33+
// const name = flags.name ?? 'world'
34+
// this.log(`hello ${name} from /Users/kevinwang/Projects/codify2/codify/src/commands/uninstall.ts`)
35+
if (args.length === 0) {
36+
throw new Error('A resource id must be specified for uninstall. Ex: "codify uninstall homebrew"')
37+
}
38+
39+
try {
40+
await UninstallOrchestrator.run(args);
41+
} catch (error) {
42+
ctx.log(error);
43+
process.exit(1);
44+
}
45+
46+
process.exit(0);
47+
}
48+
}

src/events/context.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export enum Event {
1515

1616
export enum ProcessName {
1717
PLAN = 'plan',
18-
APPLY = 'apply'
18+
APPLY = 'apply',
19+
UNINSTALL = 'uninstall',
1920
}
2021

2122
export enum SubProcessName {

src/orchestrators/apply.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export const ApplyOrchestrator = {
1010
.filter((p) => p.operation !== ResourceOperation.NOOP)
1111

1212
ctx.processStarted(ProcessName.APPLY);
13+
1314
await pluginCollection.apply(filteredPlan);
1415
await pluginCollection.destroy();
16+
1517
ctx.processFinished(ProcessName.APPLY);
1618
},
1719
};

src/orchestrators/common.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Project } from '../entities/project.js';
2+
import { ctx, SubProcessName } from '../events/context.js';
3+
import { DependencyMap, PluginCollection } from '../plugins/plugin-collection.js';
4+
5+
export const CommonOrchestrator = {
6+
async initializePlugins(project?: Project): Promise<{
7+
dependencyMap: DependencyMap
8+
pluginCollection: PluginCollection,
9+
}> {
10+
ctx.subprocessStarted(SubProcessName.INITIALIZE_PLUGINS)
11+
const pluginCollection = new PluginCollection();
12+
const dependencyMap = await pluginCollection.initialize(project);
13+
ctx.subprocessFinished(SubProcessName.INITIALIZE_PLUGINS)
14+
15+
return { dependencyMap, pluginCollection };
16+
},
17+
};

src/orchestrators/plan.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Project } from '../entities/project.js';
44
import { ctx, ProcessName, SubProcessName } from '../events/context.js';
55
import { Parser } from '../parser/index.js';
66
import { PluginCollection } from '../plugins/plugin-collection.js';
7+
import { CommonOrchestrator } from './common.js';
78

89
export interface PlanOrchestratorResponse {
910
plan: PlanResponseData[],
@@ -19,10 +20,7 @@ export const PlanOrchestrator = {
1920
const project = await Parser.parseProject(path);
2021
ctx.subprocessFinished(SubProcessName.PARSE);
2122

22-
ctx.subprocessStarted(SubProcessName.INITIALIZE_PLUGINS)
23-
const pluginCollection = new PluginCollection();
24-
const dependencyMap = await pluginCollection.initialize(project);
25-
ctx.subprocessFinished(SubProcessName.INITIALIZE_PLUGINS)
23+
const { dependencyMap, pluginCollection } = await CommonOrchestrator.initializePlugins(project);
2624

2725
ctx.subprocessStarted(SubProcessName.VALIDATE)
2826
project.validateWithResourceMap(dependencyMap);

src/orchestrators/uninstall.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { PlanResponseData, ResourceOperation } from 'codify-schemas';
2+
import { randomUUID } from 'node:crypto';
3+
4+
import { ctx, ProcessName } from '../events/context.js';
5+
import { CommonOrchestrator } from './common.js';
6+
7+
export const UninstallOrchestrator = {
8+
async run(typeIds: string[]): Promise<void> {
9+
if (typeIds.length === 0) {
10+
return;
11+
}
12+
13+
const plan = typeIds.map((type) => ({
14+
operation: ResourceOperation.DESTROY,
15+
parameters: [] as any[],
16+
planId: randomUUID(),
17+
resourceType: type,
18+
} as PlanResponseData))
19+
20+
const { pluginCollection } = await CommonOrchestrator.initializePlugins();
21+
22+
ctx.processStarted(ProcessName.UNINSTALL);
23+
24+
await pluginCollection.apply(plan);
25+
await pluginCollection.destroy();
26+
27+
ctx.processFinished(ProcessName.UNINSTALL);
28+
},
29+
};

src/plugins/plugin-collection.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class PluginCollection {
2020
private resourceToPluginMapping = new Map<string, string>()
2121
private pluginToResourceMapping = new Map<string, string[]>()
2222

23-
async initialize(project: Project): Promise<Map<string, string[]>> {
23+
async initialize(project?: Project): Promise<Map<string, string[]>> {
2424
const plugins = await this.resolvePlugins(project);
2525

2626
for (const plugin of plugins) {
@@ -62,15 +62,17 @@ export class PluginCollection {
6262
}
6363

6464
async apply(planResponseData: PlanResponseData[]): Promise<void> {
65-
for (const { planId, resourceType } of planResponseData) {
65+
for (const plan of planResponseData) {
66+
const { resourceType } = plan;
67+
6668
ctx.subprocessStarted(SubProcessName.APPLYING_RESOURCE, resourceType);
6769

6870
const pluginName = this.resourceToPluginMapping.get(resourceType);
6971
if (!pluginName) {
7072
throw new Error(`Internal error: unable to determine plugin for apply: ${resourceType}`);
7173
}
7274

73-
await this.plugins.get(pluginName)!.apply(planId);
75+
await this.plugins.get(pluginName)!.apply(plan);
7476

7577
ctx.subprocessFinished(SubProcessName.APPLYING_RESOURCE, resourceType);
7678
}
@@ -82,15 +84,19 @@ export class PluginCollection {
8284
}
8385
}
8486

85-
private async resolvePlugins(project: Project): Promise<Plugin[]> {
87+
private async resolvePlugins(project?: Project): Promise<Plugin[]> {
8688
const pluginDefinitions: Record<string, string> = {
8789
...DEFAULT_PLUGINS,
88-
...project.projectConfig?.plugins,
90+
...project?.projectConfig?.plugins,
8991
};
9092

91-
return Promise.all(Object.entries(pluginDefinitions).map(([name, version]) =>
93+
const configPlugins = await Promise.all(Object.entries(pluginDefinitions).map(([name, version]) =>
9294
PluginResolver.resolve(name, version)
9395
));
96+
97+
const existingPlugins = await PluginResolver.resolveExisting(Object.keys(pluginDefinitions));
98+
99+
return [...existingPlugins, ...configPlugins];
94100
}
95101

96102
private async initializePlugins(plugins: Plugin[]): Promise<Map<string, string[]>> {

src/plugins/plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ export class Plugin {
6767
return response;
6868
}
6969

70-
async apply(planId: string): Promise<void> {
71-
await this.process!.sendMessageForResult({ cmd: 'apply', data: { planId } });
70+
async apply(plan: PlanResponseData): Promise<void> {
71+
await this.process!.sendMessageForResult({ cmd: 'apply', data: { plan } });
7272
}
7373

7474
destroy() {

0 commit comments

Comments
 (0)