angular-docs-cn/dev-infra/bazel/api-golden/find_entry_points.ts
Paul Gschwendtner 56bd21de6f feat(dev-infra): introduce shared tool for validating API signature (#42688)
For the last years the Angular repositories relied on `ts-api-guardian`
for testing the public API signature. This project worked well in
general but its another inconvenience to maintain if we could rely on
Microsoft's `api-extractor` tool.

Especially since with TypeScript 4.3 issues with export aliases appeared
that would require us to extend TS API guardian to support such exports.
This is not as straightforward as it sounds, given it requires rewriting
of declarations to show-case the proper name in the API golden. Microsoft's
API extractor has integrated support for this.

As of TypeScript 4.3, we want to start using the new `override` keyword.
We are not able to use that keyword currently because an old version of
API extractor is used in the `ng_module` rule to flatten the types into
a single file. To fix this, we need to update `api-extractor`, but this
unveils the issue with TS API guardian because the most recent version
of api-extractor uses alias exports to avoid potential conflicts
with globals available through the TypeScript default libraries (e.g.
`dom.d.ts`).

PR Close #42688
2021-06-30 11:43:48 -07:00

63 lines
1.8 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {lstatSync, readdirSync, readFileSync} from 'fs';
import {dirname, join} from 'path';
/** Interface describing a resolved NPM package entry point. */
export interface PackageEntryPoint {
typesEntryPointPath: string;
packageJsonPath: string;
}
/** Interface describing contents of a `package.json`. */
interface PackageJson {
types?: string;
typings?: string;
}
/** Finds all entry points within a given NPM package directory. */
export function findEntryPointsWithinNpmPackage(dirPath: string): PackageEntryPoint[] {
const entryPoints: PackageEntryPoint[] = [];
for (const packageJsonFilePath of findPackageJsonFilesInDirectory(dirPath)) {
const packageJson = JSON.parse(readFileSync(packageJsonFilePath, 'utf8')) as PackageJson;
const typesFile = packageJson.types || packageJson.typings;
if (typesFile) {
entryPoints.push({
packageJsonPath: packageJsonFilePath,
typesEntryPointPath: join(dirname(packageJsonFilePath), typesFile),
});
}
}
return entryPoints;
}
/** Determine if the provided path is a directory. */
function isDirectory(dirPath: string) {
try {
return lstatSync(dirPath).isDirectory();
} catch {
return false;
}
}
/** Finds all `package.json` files within a directory. */
function* findPackageJsonFilesInDirectory(directoryPath: string): IterableIterator<string> {
for (const fileName of readdirSync(directoryPath)) {
const fullPath = join(directoryPath, fileName);
if (isDirectory(fullPath)) {
yield* findPackageJsonFilesInDirectory(fullPath);
} else if (fileName === 'package.json') {
yield fullPath;
}
}
}