@yolkai/nx-workspace
Version:
98 lines (97 loc) • 4.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const project_graph_builder_1 = require("./project-graph-builder");
const app_root_1 = require("../../utils/app-root");
const fileutils_1 = require("../../utils/fileutils");
const file_utils_1 = require("../file-utils");
const file_graph_1 = require("../file-graph");
const build_nodes_1 = require("./build-nodes");
const build_dependencies_1 = require("./build-dependencies");
const assert_workspace_validity_1 = require("../assert-workspace-validity");
function createProjectGraph(workspaceJson = file_utils_1.readWorkspaceJson(), nxJson = file_utils_1.readNxJson(), workspaceFiles = file_utils_1.readWorkspaceFiles(), fileRead = defaultFileRead, cache = readCache()) {
assert_workspace_validity_1.assertWorkspaceValidity(workspaceJson, nxJson);
if (!cache || maxMTime(workspaceFiles) > cache.mtime) {
const builder = new project_graph_builder_1.ProjectGraphBuilder(cache ? cache.data.projectGraph : undefined);
const buildNodesFns = [build_nodes_1.buildWorkspaceProjectNodes];
const buildDependenciesFns = [
build_dependencies_1.buildExplicitTypeScriptDependencies,
build_dependencies_1.buildImplicitProjectDependencies
];
// TODO: File graph needs to be handled separately from project graph, or
// we need a way to support project extensions (e.g. npm project).
const fileMap = file_graph_1.createFileMap(workspaceJson, workspaceFiles);
const ctx = {
workspaceJson,
nxJson,
fileMap: modifiedSinceCache(fileMap, cache)
};
buildNodesFns.forEach(f => f(ctx, builder.addNode.bind(builder), fileRead));
buildDependenciesFns.forEach(f => f(ctx, builder.nodes, builder.addDependency.bind(builder), fileRead));
const projectGraph = builder.build();
writeCache({
projectGraph,
fileMap
});
return projectGraph;
}
else {
// Cache file was modified _after_ all workspace files.
// Safe to return the cached graph.
return cache.data.projectGraph;
}
}
exports.createProjectGraph = createProjectGraph;
function defaultFileRead(filePath) {
return fs_1.readFileSync(`${app_root_1.appRootPath}/${filePath}`, 'UTF-8');
}
const nxDepsPath = `${app_root_1.appRootPath}/dist/nxdeps.json`;
function readCache() {
if (!fileutils_1.directoryExists(`${app_root_1.appRootPath}/dist`)) {
fs_1.mkdirSync(`${app_root_1.appRootPath}/dist`);
}
const data = getValidCache(fileutils_1.fileExists(nxDepsPath) ? fileutils_1.readJsonFile(nxDepsPath) : null);
return data ? { data, mtime: file_utils_1.mtime(nxDepsPath) } : false;
}
function getValidCache(cache) {
if (!cache) {
return null;
}
return cache.projectGraph && cache.fileMap ? cache : null;
}
function writeCache(cache) {
fileutils_1.writeJsonFile(nxDepsPath, cache);
}
function maxMTime(files) {
return Math.max(...files.map(f => f.mtime));
}
function modifiedSinceCache(fileMap, c) {
// No cache -> compute entire graph
if (!c) {
return fileMap;
}
const currentProjects = Object.keys(fileMap).sort();
const previousProjects = Object.keys(c.data.fileMap).sort();
// Projects changed -> compute entire graph
if (currentProjects.length !== previousProjects.length ||
currentProjects.some((val, idx) => val !== previousProjects[idx])) {
return fileMap;
}
// Projects are same, only compute changed projects
const modifiedSince = currentProjects.reduce((acc, k) => {
acc[k] = [];
return acc;
}, {});
currentProjects.forEach(p => {
for (const f of fileMap[p]) {
const fromCache = c.data.fileMap[p].find(x => x.file === f.file);
if (!fromCache) {
modifiedSince[p].push(f);
}
else if (f.mtime > fromCache.mtime) {
modifiedSince[p].push(f);
}
}
});
return modifiedSince;
}