2018-03-01 13:41:35 -05:00
|
|
|
/**
|
|
|
|
* @license
|
2020-05-19 15:08:49 -04:00
|
|
|
* Copyright Google LLC All Rights Reserved.
|
2018-03-01 13:41:35 -05:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2018-03-02 17:19:01 -05:00
|
|
|
import {createPatch} from 'diff';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as path from 'path';
|
|
|
|
|
2020-04-13 19:40:21 -04:00
|
|
|
import {publicApi, SerializationOptions} from './serializer';
|
|
|
|
|
|
|
|
export {publicApi, SerializationOptions} from './serializer';
|
2018-03-02 17:19:01 -05:00
|
|
|
|
|
|
|
export function generateGoldenFile(
|
|
|
|
entrypoint: string, outFile: string, options: SerializationOptions = {}): void {
|
|
|
|
const output = publicApi(entrypoint, options);
|
2020-02-25 16:05:49 -05:00
|
|
|
|
2018-03-02 17:19:01 -05:00
|
|
|
ensureDirectory(path.dirname(outFile));
|
|
|
|
fs.writeFileSync(outFile, output);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function verifyAgainstGoldenFile(
|
|
|
|
entrypoint: string, goldenFile: string, options: SerializationOptions = {}): string {
|
|
|
|
const actual = publicApi(entrypoint, options);
|
2020-02-25 16:05:49 -05:00
|
|
|
const expected = fs.existsSync(goldenFile) ? fs.readFileSync(goldenFile).toString() : '';
|
2018-03-02 17:19:01 -05:00
|
|
|
|
|
|
|
if (actual === expected) {
|
|
|
|
return '';
|
|
|
|
} else {
|
2020-03-17 06:30:36 -04:00
|
|
|
// The patch should not show absolute paths, as these are pretty long and obfuscated
|
|
|
|
// the printed golden diff. Additionally, path separators in the patch should be forward
|
|
|
|
// slashes for consistency and to enable easier integration testing.
|
|
|
|
const displayFileName = path.relative(process.cwd(), goldenFile).replace(/\\/g, '/');
|
|
|
|
const patch = createPatch(displayFileName, expected, actual, 'Golden file', 'Generated API');
|
2018-03-02 17:19:01 -05:00
|
|
|
|
|
|
|
// Remove the header of the patch
|
|
|
|
const start = patch.indexOf('\n', patch.indexOf('\n') + 1) + 1;
|
|
|
|
|
|
|
|
return patch.substring(start);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function ensureDirectory(dir: string) {
|
|
|
|
if (!fs.existsSync(dir)) {
|
|
|
|
ensureDirectory(path.dirname(dir));
|
|
|
|
fs.mkdirSync(dir);
|
|
|
|
}
|
|
|
|
}
|
2020-02-25 16:05:49 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine if the provided path is a directory.
|
|
|
|
*/
|
|
|
|
function isDirectory(dirPath: string) {
|
|
|
|
try {
|
2020-02-26 12:09:35 -05:00
|
|
|
return fs.lstatSync(dirPath).isDirectory();
|
2020-02-25 16:05:49 -05:00
|
|
|
} catch {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets an array of paths to the typings files for each of the recursively discovered
|
|
|
|
* package.json
|
|
|
|
* files from the directory provided.
|
|
|
|
*/
|
|
|
|
export function discoverAllEntrypoints(dirPath: string) {
|
|
|
|
// Determine all of the package.json files
|
|
|
|
const packageJsons: string[] = [];
|
|
|
|
const entryPoints: string[] = [];
|
|
|
|
const findPackageJsonsInDir = (nextPath: string) => {
|
|
|
|
for (const file of fs.readdirSync(nextPath)) {
|
|
|
|
const fullPath = path.join(nextPath, file);
|
|
|
|
if (isDirectory(fullPath)) {
|
|
|
|
findPackageJsonsInDir(fullPath);
|
|
|
|
} else {
|
|
|
|
if (file === 'package.json') {
|
|
|
|
packageJsons.push(fullPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
findPackageJsonsInDir(dirPath);
|
|
|
|
|
|
|
|
// Get all typings file locations from package.json files
|
|
|
|
for (const packageJson of packageJsons) {
|
2021-02-04 17:42:42 -05:00
|
|
|
const packageJsonObj =
|
|
|
|
JSON.parse(fs.readFileSync(packageJson, {encoding: 'utf8'})) as {typings: string};
|
2020-02-25 16:05:49 -05:00
|
|
|
const typings = packageJsonObj.typings;
|
|
|
|
if (typings) {
|
|
|
|
entryPoints.push(path.join(path.dirname(packageJson), typings));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return entryPoints;
|
|
|
|
}
|