Skip to content

Commit

Permalink
feat(openapi-generator): make node_module resolving more generic by r…
Browse files Browse the repository at this point in the history
…emoving @BitGo prefix
  • Loading branch information
ad-world committed May 21, 2024
1 parent 1c21cab commit 62b2f14
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 65 deletions.
96 changes: 43 additions & 53 deletions packages/openapi-generator/src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,23 @@ export class Project {
this.add(path, sourceFile);

for (const sym of Object.values(sourceFile.symbols.imports)) {
const filePath = p.dirname(path);
const absImportPathE = this.resolve(filePath, sym.from);
if (E.isLeft(absImportPathE)) {
return absImportPathE;
} else if (!this.has(absImportPathE.right)) {
queue.push(absImportPathE.right);
if (!sym.from.startsWith('.')) {
// If we are not resolving a relative path, we need to resolve the entry point
const baseDir = p.dirname(sourceFile.path);
let entryPoint = this.resolveEntryPoint(baseDir, sym.from);
if (E.isLeft(entryPoint)) {
continue;
} else if (!this.has(entryPoint.right)) {
queue.push(entryPoint.right);
}
} else {
const filePath = p.dirname(path);
const absImportPathE = this.resolve(filePath, sym.from);
if (E.isLeft(absImportPathE)) {
return absImportPathE;
} else if (!this.has(absImportPathE.right)) {
queue.push(absImportPathE.right);
}
}
}
for (const starExport of sourceFile.symbols.exportStarFiles) {
Expand All @@ -80,66 +91,45 @@ export class Project {
return await readFile(filename, 'utf8');
}

private resolvePath(path: string, basedir: string): E.Either<string, string> {
resolveEntryPoint(basedir: string, library: string): E.Either<string, string> {
try {
const result = resolve.sync(path, {
const packageJson = resolve.sync(`${library}/package.json`, {
basedir,
extensions: ['.ts', '.js', '.d.ts'],
extensions: ['.json'],
});
const packageInfo = JSON.parse(fs.readFileSync(packageJson, 'utf8'));

return E.right(result);
} catch (e: unknown) {
if (e instanceof Error && e.message) {
return E.left(e.message);
let typesEntryPoint = '';

if (packageInfo['types']) {
typesEntryPoint = packageInfo['types'];
}

return E.left(JSON.stringify(e));
}
}
if (packageInfo['typings']) {
typesEntryPoint = packageInfo['typings'];
}

private findSourceFileFromPackage(path: string): E.Either<string, string> {
const mapName = path.replace('.js', '.js.map');
if (!typesEntryPoint) {
return E.left(`Could not find types entry point for ${library}`);
}

if (fs.existsSync(mapName)) {
const mapJson = JSON.parse(fs.readFileSync(mapName, 'utf8'));
const dirName = p.dirname(path);
const source = mapJson.sources[0];
const response = resolve.sync(source, { basedir: dirName });
return E.right(response);
const entryPoint = resolve.sync(`${library}/${typesEntryPoint}`, {
basedir,
extensions: ['.ts', '.js'],
});
return E.right(entryPoint);
} catch (err) {
return E.left(`Could not resolve entry point for ${library}: ${err}`);
}

return E.left('Map file not found for ' + path);
}

resolve(basedir: string, path: string): E.Either<string, string> {
const BITGO_PREFIX = '@bitgo';
try {
let resolved = this.resolvePath(path, basedir);
if (E.isLeft(resolved)) {
// Could not resolve the path, try resolving in the types package
resolved = this.resolvePath('@types/' + path, basedir);
}

// Types package wasn't found, return an error
if (E.isLeft(resolved)) {
return E.left('Could not resolve ' + path + ' from ' + basedir);
}

const result = resolved.right;

// If we are parsing an internal type package, we want to return the path to the source TS file
if (path.startsWith(BITGO_PREFIX)) {
return this.findSourceFileFromPackage(result);
} else {
// Else - find the declaration file and return it if it exists
const dTsName = result.replace('.js', '.d.ts');

if (fs.existsSync(dTsName)) {
return E.right(dTsName);
}

return E.right(result);
}
const result = resolve.sync(path, {
basedir,
extensions: ['.ts', '.js'],
});
return E.right(result);
} catch (e: unknown) {
if (e instanceof Error && e.message) {
return E.left(e.message);
Expand Down
8 changes: 7 additions & 1 deletion packages/openapi-generator/src/resolveInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ function resolveImportPath(
sourceFile: SourceFile,
path: string,
): E.Either<string, SourceFile> {
const importPathE = project.resolve(dirname(sourceFile.path), path);
let importPathE;
if (path.startsWith('.')) {
importPathE = project.resolve(dirname(sourceFile.path), path);
} else {
importPathE = project.resolveEntryPoint(dirname(sourceFile.path), path);
}

if (E.isLeft(importPathE)) {
return importPathE;
}
Expand Down
14 changes: 3 additions & 11 deletions packages/openapi-generator/test/externalModule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as p from 'path';

import { parsePlainInitializer, Project, type Schema } from '../src';
import { KNOWN_IMPORTS } from '../src/knownImports';
// import { resolve } from 'node:path';

/** External library parsing test case
*
Expand All @@ -18,23 +19,16 @@ async function testCase(
entryPoint: string,
expected: Record<string, Record<string, Schema>>,
expectedErrors: Record<string, string[]> = {},
parseErrorRegex: RegExp | undefined = undefined,
) {
test(description, async () => {
const project = new Project({}, KNOWN_IMPORTS);
const entryPointPath = p.resolve(entryPoint);
const parsed = await project.parseEntryPoint(entryPointPath);

if (parseErrorRegex !== undefined) {
assert(E.isLeft(parsed));
assert(parseErrorRegex.test(parsed.left));
return;
}
await project.parseEntryPoint(entryPointPath);

for (const path of Object.keys(expected)) {
const resolvedPath = p.resolve(path);
const sourceFile = project.get(resolvedPath);

if (sourceFile === undefined) {
throw new Error(`Source file ${path} not found`);
}
Expand Down Expand Up @@ -193,13 +187,11 @@ testCase(
'test/sample-types/importPathError.ts',
{},
{},
/Could not resolve io-tsg from .*\/test\/sample-types\/node_modules\/@bitgo\/foobar3\/src/,
);

testCase(
'type from external library with export path error',
'test/sample-types/exportPathError.ts',
{},
{},
/Could not resolve .\/foobart from .*\/test\/sample-types\/node_modules\/@bitgo\/foobar6\/src/,
);

0 comments on commit 62b2f14

Please sign in to comment.