Skip to content

Commit 18d8b41

Browse files
Merge pull request #1002 from BitGo/lazy-file-processing
fix: implement lazy file processing with improved dependency handling
2 parents 047d2f2 + dda6fcd commit 18d8b41

File tree

1 file changed

+65
-54
lines changed

1 file changed

+65
-54
lines changed

packages/openapi-generator/src/project.ts

Lines changed: 65 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,96 +13,107 @@ const readFile = promisify(fs.readFile);
1313
export class Project {
1414
private readonly knownImports: Record<string, Record<string, KnownCodec>>;
1515

16-
private files: Record<string, SourceFile>;
16+
private processedFiles: Record<string, SourceFile>;
17+
private pendingFiles: Set<string>;
1718
private types: Record<string, string>;
19+
private visitedPackages: Set<string>;
1820

1921
constructor(files: Record<string, SourceFile> = {}, knownImports = KNOWN_IMPORTS) {
20-
this.files = files;
22+
this.processedFiles = files;
23+
this.pendingFiles = new Set();
2124
this.knownImports = knownImports;
2225
this.types = {};
26+
this.visitedPackages = new Set();
2327
}
2428

2529
add(path: string, sourceFile: SourceFile): void {
26-
this.files[path] = sourceFile;
30+
this.processedFiles[path] = sourceFile;
31+
this.pendingFiles.delete(path);
32+
33+
// Update types mapping
34+
for (const exp of sourceFile.symbols.exports) {
35+
this.types[exp.exportedName] = path;
36+
}
2737
}
2838

2939
get(path: string): SourceFile | undefined {
30-
return this.files[path];
40+
return this.processedFiles[path];
3141
}
3242

3343
has(path: string): boolean {
34-
return this.files.hasOwnProperty(path);
44+
return this.processedFiles.hasOwnProperty(path);
3545
}
3646

3747
async parseEntryPoint(entryPoint: string): Promise<E.Either<string, Project>> {
3848
const queue: string[] = [entryPoint];
3949
let path: string | undefined;
40-
const visitedPackages = new Set<string>();
50+
4151
while (((path = queue.pop()), path !== undefined)) {
4252
if (!['.ts', '.js'].includes(p.extname(path))) {
4353
continue;
4454
}
4555

46-
const src = await this.readFile(path);
47-
const sourceFile = await parseSource(path, src);
48-
49-
if (sourceFile === undefined) continue;
56+
try {
57+
const src = await this.readFile(path);
58+
const sourceFile = await parseSource(path, src);
5059

51-
// map types to their file path
52-
for (const exp of sourceFile.symbols.exports) {
53-
this.types[exp.exportedName] = path;
54-
}
55-
56-
this.add(path, sourceFile);
60+
if (!sourceFile) {
61+
console.error(`Error parsing source file: ${path}`);
62+
continue;
63+
}
5764

58-
for (const sym of Object.values(sourceFile.symbols.imports)) {
59-
if (!sym.from.startsWith('.')) {
60-
// If we are not resolving a relative path, we need to resolve the entry point
61-
const baseDir = p.dirname(sourceFile.path);
62-
let entryPoint = this.resolveEntryPoint(baseDir, sym.from);
65+
// map types to their file path
66+
for (const exp of sourceFile.symbols.exports) {
67+
this.types[exp.exportedName] = path;
68+
}
6369

64-
if (!visitedPackages.has(sym.from)) {
65-
// This is a step that checks if this import has custom codecs, and loads them into known imports
66-
const codecs = await this.getCustomCodecs(baseDir, sym.from);
67-
if (E.isLeft(codecs)) {
68-
return codecs;
70+
this.add(path, sourceFile);
71+
72+
// Process imports
73+
const baseDir = p.dirname(path);
74+
for (const sym of Object.values(sourceFile.symbols.imports)) {
75+
if (!sym.from.startsWith('.')) {
76+
if (!this.visitedPackages.has(sym.from)) {
77+
const codecs = await this.getCustomCodecs(baseDir, sym.from);
78+
if (E.isLeft(codecs)) {
79+
return codecs;
80+
}
81+
82+
if (Object.keys(codecs.right).length > 0) {
83+
this.knownImports[sym.from] = {
84+
...codecs.right,
85+
...this.knownImports[sym.from],
86+
};
87+
logInfo(`Loaded custom codecs for ${sym.from}`);
88+
}
89+
90+
this.visitedPackages.add(sym.from);
6991
}
7092

71-
if (Object.keys(codecs.right).length > 0) {
72-
this.knownImports[sym.from] = {
73-
...codecs.right,
74-
...this.knownImports[sym.from],
75-
};
76-
77-
logInfo(`Loaded custom codecs for ${sym.from}`);
93+
const entryPoint = this.resolveEntryPoint(baseDir, sym.from);
94+
if (E.isRight(entryPoint) && !this.has(entryPoint.right)) {
95+
queue.push(entryPoint.right);
96+
}
97+
} else {
98+
const absImportPathE = this.resolve(baseDir, sym.from);
99+
if (E.isRight(absImportPathE) && !this.has(absImportPathE.right)) {
100+
queue.push(absImportPathE.right);
78101
}
79102
}
103+
}
80104

81-
visitedPackages.add(sym.from);
82-
83-
if (E.isLeft(entryPoint)) {
84-
continue;
85-
} else if (!this.has(entryPoint.right)) {
86-
queue.push(entryPoint.right);
87-
}
88-
} else {
89-
const filePath = p.dirname(path);
90-
const absImportPathE = this.resolve(filePath, sym.from);
91-
if (E.isLeft(absImportPathE)) {
92-
return absImportPathE;
93-
} else if (!this.has(absImportPathE.right)) {
105+
// Process star exports
106+
for (const starExport of sourceFile.symbols.exportStarFiles) {
107+
const absImportPathE = this.resolve(baseDir, starExport);
108+
if (E.isRight(absImportPathE) && !this.has(absImportPathE.right)) {
94109
queue.push(absImportPathE.right);
95110
}
96111
}
97-
}
98-
for (const starExport of sourceFile.symbols.exportStarFiles) {
99-
const filePath = p.dirname(path);
100-
const absImportPathE = this.resolve(filePath, starExport);
101-
if (E.isLeft(absImportPathE)) {
102-
return absImportPathE;
103-
} else if (!this.has(absImportPathE.right)) {
104-
queue.push(absImportPathE.right);
112+
} catch (err) {
113+
if (err instanceof Error) {
114+
return E.left(err.message);
105115
}
116+
return E.left('Unknown error occurred while processing files');
106117
}
107118
}
108119

0 commit comments

Comments
 (0)