Skip to content

Commit 0b919e7

Browse files
committed
feat: Added new flow for saving import to file
1 parent a18b107 commit 0b919e7

File tree

9 files changed

+67
-13
lines changed

9 files changed

+67
-13
lines changed

new.codify.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

src/entities/plan.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('Unit tests for Plan entity', () => {
1414
new ResourceConfig({ type: 'type2', dependsOn: ['type1'] }),
1515
new ResourceConfig({ type: 'type3', dependsOn: ['type1', 'type2']}),
1616
],
17-
'./somewhere',
17+
['codify.json']
1818
);
1919

2020
project.resolveDependenciesAndCalculateEvalOrder()

src/orchestrators/import.ts

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import path from 'node:path';
2+
13
import { Project } from '../entities/project.js';
24
import { ResourceConfig } from '../entities/resource-config.js';
35
import { ResourceInfo } from '../entities/resource-info.js';
46
import { ProcessName, SubProcessName, ctx } from '../events/context.js';
57
import { CodifyParser } from '../parser/index.js';
68
import { DependencyMap, PluginManager } from '../plugins/plugin-manager.js';
79
import { PromptType, Reporter } from '../ui/reporters/reporter.js';
10+
import { FileUtils } from '../utils/file.js';
811
import { InitializeOrchestrator } from './initialize.js';
912

1013
export type RequiredParameters = Map<string, RequiredParameter[]>;
@@ -70,6 +73,7 @@ export class ImportOrchestrator {
7073
ctx.processFinished(ProcessName.IMPORT)
7174
reporter.displayImportResult(importResult);
7275

76+
ImportOrchestrator.attachResourceInfo(importResult, resourceInfoList);
7377
await ImportOrchestrator.saveResults(reporter, importResult, project)
7478
}
7579

@@ -131,16 +135,60 @@ ${JSON.stringify(unsupportedTypeIds)}`);
131135

132136
private static async saveResults(reporter: Reporter, importResult: ImportResult, project: Project): Promise<void> {
133137
const projectExists = !project.isEmpty();
138+
const multipleCodifyFiles = project.codifyFiles.length > 1;
134139

135-
const continueSaving = await reporter.promptOptions(
140+
const promptResult = await reporter.promptOptions(
136141
'\nDo you want to save the results?',
137-
[projectExists ? `Update ${project.path}` : undefined, 'Save in a new file', 'No'].filter(Boolean) as string[]
142+
[projectExists ? multipleCodifyFiles ? 'Update existing file (multiple found)' : `Update existing file (${project.codifyFiles})` : undefined, 'In a new file', 'No'].filter(Boolean) as string[]
138143
)
139-
if (!continueSaving) {
140-
process.exit(0)
144+
145+
if (promptResult === 'Update existing file (multiple found)') {
146+
const file = await reporter.promptOptions(
147+
'\nWhich file would you like to update?',
148+
project.codifyFiles,
149+
)
150+
await ImportOrchestrator.saveToFile(file, importResult);
151+
152+
} else if (promptResult.startsWith('Update existing file')) {
153+
await ImportOrchestrator.saveToFile(project.codifyFiles[0], importResult);
154+
155+
} else if (promptResult === 'In a new file') {
156+
const newFileName = await ImportOrchestrator.generateNewImportFileName();
157+
await ImportOrchestrator.saveToFile(newFileName, importResult);
141158
}
159+
}
160+
161+
private static async saveToFile(filePath: string, importResult: ImportResult): Promise<void> {
162+
const existing = await CodifyParser.parse(filePath);
142163

164+
for (const resource of importResult.result) {
165+
existing.addOrReplace(resource);
166+
}
143167

168+
console.log(JSON.stringify(existing.resourceConfigs.map((r) => r.raw), null, 2))
169+
}
170+
171+
private static async generateNewImportFileName(): Promise<string> {
172+
const cwd = process.cwd();
173+
174+
let fileName = path.join(cwd, 'import.codify.json')
175+
let counter = 1;
176+
177+
while(true) {
178+
if (!(await FileUtils.fileExists(fileName))) {
179+
return fileName;
180+
}
181+
182+
fileName = path.join(cwd, `import-${counter}.codify.json`);
183+
counter++;
184+
}
185+
}
144186

187+
// We have to attach additional info to the imported configs to make saving easier
188+
private static attachResourceInfo(importResult: ImportResult, resourceInfoList: ResourceInfo[]): void {
189+
importResult.result.forEach((resource) => {
190+
const matchedInfo = resourceInfoList.find((info) => info.type === resource.type)!;
191+
resource.attachResourceInfo(matchedInfo);
192+
})
145193
}
146194
}

src/parser/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ class Parser {
2222
async parse(dirOrFile: string): Promise<Project> {
2323
const absolutePath = path.resolve(dirOrFile);
2424
const sourceMaps = new SourceMapCache()
25+
const codifyFiles = await this.getFilePaths(absolutePath)
2526

26-
const configs = await this.getFilePaths(absolutePath)
27-
.then((paths) => this.readFiles(paths))
27+
const configs = await this.readFiles(codifyFiles)
2828
.then((files) => this.parseContents(files, sourceMaps))
2929
.then((config) => this.createConfigBlocks(config, sourceMaps))
3030

31-
return Project.create(configs, dirOrFile, sourceMaps);
31+
return Project.create(configs, codifyFiles, sourceMaps);
3232
}
3333

3434
private async getFilePaths(dirOrFile: string): Promise<string[]> {

src/ui/components/plan/plan.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export function PlanComponent(props: {
1414
<Box borderColor="green" borderStyle="round">
1515
<Text>Codify Plan</Text>
1616
</Box>
17-
<Text>Path: {props.plan.project.path}</Text>
17+
<Text>Path: {props.plan.project.codifyFiles}</Text>
1818
<Text>The following actions will be performed: </Text>
1919
<Text> </Text>
2020
<Box flexDirection="column" marginLeft={1}>{

src/ui/plan-pretty-printer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function prettyFormatPlan(plan: Plan) {
88
'',
99
'',
1010
chalk.bold('Codify Plan'),
11-
`Path: ${plan.project.path}`,
11+
`Path: ${plan.project.codifyFiles}`,
1212
'The following actions will be performed',
1313
'',
1414
];

src/ui/reporters/default-reporter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ export class DefaultReporter implements Reporter {
137137
return result;
138138
}
139139

140-
async promptOptions(message:string, options:string[]): Promise<number> {
141-
const result = await this.updateStateAndAwaitEvent<number>(
140+
async promptOptions(message:string, options:string[]): Promise<string> {
141+
const result = await this.updateStateAndAwaitEvent<string>(
142142
() => this.updateRenderState(RenderStatus.PROMPT_OPTIONS, { message, options }),
143143
RenderEvent.PROMPT_RESULT
144144
)

src/ui/reporters/reporter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export interface Reporter {
4747

4848
promptConfirmation(message: string): Promise<boolean>
4949

50-
promptOptions(message: string, options: string[]): Promise<number>;
50+
promptOptions(message: string, options: string[]): Promise<string>;
5151

5252
promptSudo(pluginName: string, data: SudoRequestData, secureMode: boolean): Promise<SudoRequestResponseData>;
5353

src/utils/file.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,9 @@ export class FileUtils {
2626
const lstat = await fs.lstat(path.resolve(fileOrDir))
2727
return lstat.isDirectory()
2828
}
29+
30+
static async readFile(filePath: string): Promise<string | undefined> {
31+
const resolvedPath = path.resolve(filePath);
32+
return fs.readFile(resolvedPath, 'utf8')
33+
}
2934
}

0 commit comments

Comments
 (0)