providence-analytics
Version:
Providence is the 'All Seeing Eye' that measures effectivity and popularity of software. Release management will become highly efficient due to an accurate impact analysis of (breaking) changes
148 lines (133 loc) • 4.45 kB
JavaScript
/* eslint-disable import/no-extraneous-dependencies */
import { performance } from 'perf_hooks';
import path from 'path';
import { InputDataService } from '../program/core/InputDataService.js';
import MatchPathsAnalyzer from '../program/analyzers/match-paths.js';
import { toPosixPath } from '../program/utils/to-posix-path.js';
import { QueryService } from '../program/core/QueryService.js';
import { _providenceModule } from '../program/providence.js';
import { LogService } from '../program/core/LogService.js';
import { fsAdapter } from '../program/utils/fs-adapter.js';
import { flatten } from './cli-helpers.js';
/**
* @typedef {import('../../types/index.js').PathFromSystemRoot} PathFromSystemRoot
* @typedef {import('../../types/index.js').GatherFilesConfig} GatherFilesConfig
*/
/**
* @param {{
* referenceProjectPaths: PathFromSystemRoot[];
* prefixCfg:{from:string;to:string};
* extensions:GatherFilesConfig['extensions'];
* allowlist?:string[];
* allowlistReference?:string[];
* cwd:PathFromSystemRoot
* }} opts
* @returns
*/
export async function getExtendDocsResults({
referenceProjectPaths,
allowlistReference,
extensions,
prefixCfg,
allowlist,
cwd,
}) {
const monoPkgs = await InputDataService.getMonoRepoPackages(cwd);
const results = await _providenceModule.providence(
await QueryService.getQueryConfigFromAnalyzer(MatchPathsAnalyzer, { prefix: prefixCfg }),
{
gatherFilesConfig: {
extensions: extensions || /** @type {GatherFilesConfig['extensions']} */ (['.js']),
allowlist: allowlist || ['!coverage', '!test'],
},
gatherFilesConfigReference: {
extensions: extensions || ['.js'],
allowlist: allowlistReference || ['!coverage', '!test'],
},
queryMethod: 'ast',
report: false,
targetProjectPaths: [cwd],
referenceProjectPaths,
// For mono repos, a match between root package.json and ref project will not exist.
// Disable this check, so it won't be a blocker for extendin docs
skipCheckMatchCompatibility: Boolean(monoPkgs),
},
);
const queryOutputs = flatten(
results.map(result => result.queryOutput).filter(o => typeof o !== 'string'), // filter out '[no-dependency]' etc.
);
/**
* @param {string} pathStr ./packages/lea-tabs/lea-tabs.js
* @param {{path:string;name:string}[]} pkgs ['packages/lea-tabs', ...]
*/
function replaceToMonoRepoPath(pathStr, pkgs) {
let result = pathStr;
pkgs.some(({ path: p, name }) => {
// for instance ./packages/lea-tabs/lea-tabs.js starts with 'packages/lea-tabs'
const normalizedP = `./${p}`;
if (pathStr.startsWith(normalizedP)) {
const localPath = pathStr.replace(normalizedP, ''); // 'lea-tabs.js'
result = toPosixPath(path.join(name, localPath)); // 'lea-tabs/lea-tabs.js'
return true;
}
return false;
});
return result;
}
if (monoPkgs) {
queryOutputs.forEach(resultObj => {
if (resultObj.variable) {
resultObj.variable.paths.forEach(pathObj => {
// eslint-disable-next-line no-param-reassign
pathObj.to = replaceToMonoRepoPath(pathObj.to, monoPkgs);
});
}
if (resultObj.tag) {
resultObj.tag.paths.forEach(pathObj => {
// eslint-disable-next-line no-param-reassign
pathObj.to = replaceToMonoRepoPath(pathObj.to, monoPkgs);
});
}
});
}
return queryOutputs;
}
/**
*
* @param {*} opts
*/
export async function launchProvidenceWithExtendDocs({
referenceProjectPaths,
prefixCfg,
outputFolder,
extensions,
allowlist,
allowlistReference,
cwd = process.cwd(),
}) {
const t0 = performance.now();
const queryOutputs = await getExtendDocsResults({
referenceProjectPaths,
prefixCfg,
extensions,
allowlist,
allowlistReference,
cwd,
});
// Write results
const outputFilePath = path.join(outputFolder, 'providence-extend-docs-data.json');
if (fsAdapter.fs.existsSync(outputFilePath)) {
fsAdapter.fs.unlinkSync(outputFilePath);
}
fsAdapter.fs.writeFile(outputFilePath, JSON.stringify(queryOutputs, null, 2), err => {
if (err) {
throw err;
}
});
const t1 = performance.now();
LogService.info(`"extend-docs" completed in ${Math.round((t1 - t0) / 1000)} seconds`);
}
export const _extendDocsModule = {
launchProvidenceWithExtendDocs,
getExtendDocsResults,
};