chore(graph): provide task data to graph app (#13058)
This commit is contained in:
parent
c842535fa1
commit
7557bd4f48
@ -589,7 +589,7 @@ describe('Nx Affected and Graph Tests', () => {
|
|||||||
|
|
||||||
const environmentJs = readFile('static/environment.js');
|
const environmentJs = readFile('static/environment.js');
|
||||||
const affectedProjects = environmentJs
|
const affectedProjects = environmentJs
|
||||||
.match(/"affected":\[(.*)\],/)[1]
|
.match(/"affected":\[(.*?)\]/)[1]
|
||||||
?.split(',');
|
?.split(',');
|
||||||
|
|
||||||
expect(affectedProjects).toContain(`"${myapp}"`);
|
expect(affectedProjects).toContain(`"${myapp}"`);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ window.appConfig = {
|
|||||||
{
|
{
|
||||||
id: 'local',
|
id: 'local',
|
||||||
label: 'local',
|
label: 'local',
|
||||||
url: 'projectGraph.json',
|
url: 'project-graph.json',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
defaultProjectGraph: 'local',
|
defaultProjectGraph: 'local',
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import * as open from 'open';
|
|||||||
import { basename, dirname, extname, isAbsolute, join, parse } from 'path';
|
import { basename, dirname, extname, isAbsolute, join, parse } from 'path';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import { URL, URLSearchParams } from 'url';
|
import { URL, URLSearchParams } from 'url';
|
||||||
import { workspaceLayout } from '../config/configuration';
|
import { readNxJson, workspaceLayout } from '../config/configuration';
|
||||||
import { defaultFileHasher } from '../hasher/file-hasher';
|
import { defaultFileHasher } from '../hasher/file-hasher';
|
||||||
import { output } from '../utils/output';
|
import { output } from '../utils/output';
|
||||||
import { writeJsonFile } from '../utils/fileutils';
|
import { writeJsonFile } from '../utils/fileutils';
|
||||||
@ -21,6 +21,9 @@ import {
|
|||||||
} from '../config/project-graph';
|
} from '../config/project-graph';
|
||||||
import { pruneExternalNodes } from '../project-graph/operators';
|
import { pruneExternalNodes } from '../project-graph/operators';
|
||||||
import { createProjectGraphAsync } from '../project-graph/project-graph';
|
import { createProjectGraphAsync } from '../project-graph/project-graph';
|
||||||
|
import { createTaskGraph } from 'nx/src/tasks-runner/create-task-graph';
|
||||||
|
import { TargetDefaults, TargetDependencies } from 'nx/src/config/nx-json';
|
||||||
|
import { TaskGraph } from 'nx/src/config/task-graph';
|
||||||
|
|
||||||
export interface DepGraphClientResponse {
|
export interface DepGraphClientResponse {
|
||||||
hash: string;
|
hash: string;
|
||||||
@ -33,6 +36,14 @@ export interface DepGraphClientResponse {
|
|||||||
exclude: string[];
|
exclude: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TaskGraphDependencies = Record<
|
||||||
|
string,
|
||||||
|
Record<string, Record<string, TaskGraph>>
|
||||||
|
>;
|
||||||
|
export interface TaskGraphClientResponse {
|
||||||
|
dependencies: TaskGraphDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
// maps file extention to MIME types
|
// maps file extention to MIME types
|
||||||
const mimeType = {
|
const mimeType = {
|
||||||
'.ico': 'image/x-icon',
|
'.ico': 'image/x-icon',
|
||||||
@ -55,7 +66,8 @@ function buildEnvironmentJs(
|
|||||||
exclude: string[],
|
exclude: string[],
|
||||||
watchMode: boolean,
|
watchMode: boolean,
|
||||||
localMode: 'build' | 'serve',
|
localMode: 'build' | 'serve',
|
||||||
depGraphClientResponse?: DepGraphClientResponse
|
depGraphClientResponse?: DepGraphClientResponse,
|
||||||
|
taskGraphClientResponse?: TaskGraphClientResponse
|
||||||
) {
|
) {
|
||||||
let environmentJs = `window.exclude = ${JSON.stringify(exclude)};
|
let environmentJs = `window.exclude = ${JSON.stringify(exclude)};
|
||||||
window.watch = ${!!watchMode};
|
window.watch = ${!!watchMode};
|
||||||
@ -69,7 +81,7 @@ function buildEnvironmentJs(
|
|||||||
{
|
{
|
||||||
id: 'local',
|
id: 'local',
|
||||||
label: 'local',
|
label: 'local',
|
||||||
url: 'projectGraph.json',
|
url: 'project-graph.json',
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultProjectGraph: 'local',
|
defaultProjectGraph: 'local',
|
||||||
@ -79,9 +91,16 @@ function buildEnvironmentJs(
|
|||||||
if (localMode === 'build') {
|
if (localMode === 'build') {
|
||||||
environmentJs += `window.projectGraphResponse = ${JSON.stringify(
|
environmentJs += `window.projectGraphResponse = ${JSON.stringify(
|
||||||
depGraphClientResponse
|
depGraphClientResponse
|
||||||
)};`;
|
)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
environmentJs += `window.taskGraphResponse = ${JSON.stringify(
|
||||||
|
taskGraphClientResponse
|
||||||
|
)};
|
||||||
|
`;
|
||||||
} else {
|
} else {
|
||||||
environmentJs += `window.projectGraphResponse = null;`;
|
environmentJs += `window.projectGraphResponse = null;`;
|
||||||
|
environmentJs += `window.taskGraphResponse = null;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return environmentJs;
|
return environmentJs;
|
||||||
@ -234,11 +253,14 @@ export async function generateGraph(
|
|||||||
affectedProjects
|
affectedProjects
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const taskGraphClientResponse = await createTaskGraphClientResponse();
|
||||||
|
|
||||||
const environmentJs = buildEnvironmentJs(
|
const environmentJs = buildEnvironmentJs(
|
||||||
args.exclude || [],
|
args.exclude || [],
|
||||||
args.watch,
|
args.watch,
|
||||||
!!args.file && args.file.endsWith('html') ? 'build' : 'serve',
|
!!args.file && args.file.endsWith('html') ? 'build' : 'serve',
|
||||||
depGraphClientResponse
|
depGraphClientResponse,
|
||||||
|
taskGraphClientResponse
|
||||||
);
|
);
|
||||||
html = html.replace(/src="/g, 'src="static/');
|
html = html.replace(/src="/g, 'src="static/');
|
||||||
html = html.replace(/href="styles/g, 'href="static/styles');
|
html = html.replace(/href="styles/g, 'href="static/styles');
|
||||||
@ -316,7 +338,7 @@ async function startServer(
|
|||||||
currentDepGraphClientResponse.groupByFolder = groupByFolder;
|
currentDepGraphClientResponse.groupByFolder = groupByFolder;
|
||||||
currentDepGraphClientResponse.exclude = exclude;
|
currentDepGraphClientResponse.exclude = exclude;
|
||||||
|
|
||||||
const app = http.createServer((req, res) => {
|
const app = http.createServer(async (req, res) => {
|
||||||
// parse URL
|
// parse URL
|
||||||
const parsedUrl = new URL(req.url, `http://${host}:${port}`);
|
const parsedUrl = new URL(req.url, `http://${host}:${port}`);
|
||||||
// extract URL path
|
// extract URL path
|
||||||
@ -326,12 +348,18 @@ async function startServer(
|
|||||||
|
|
||||||
const sanitizePath = basename(parsedUrl.pathname);
|
const sanitizePath = basename(parsedUrl.pathname);
|
||||||
|
|
||||||
if (sanitizePath === 'projectGraph.json') {
|
if (sanitizePath === 'project-graph.json') {
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify(currentDepGraphClientResponse));
|
res.end(JSON.stringify(currentDepGraphClientResponse));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sanitizePath === 'task-graph.json') {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
|
res.end(JSON.stringify(await createTaskGraphClientResponse()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sanitizePath === 'currentHash') {
|
if (sanitizePath === 'currentHash') {
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify({ hash: currentDepGraphClientResponse.hash }));
|
res.end(JSON.stringify({ hash: currentDepGraphClientResponse.hash }));
|
||||||
@ -486,6 +514,7 @@ async function createDepGraphClientResponse(
|
|||||||
tags: project.data.tags,
|
tags: project.data.tags,
|
||||||
root: project.data.root,
|
root: project.data.root,
|
||||||
files: project.data.files,
|
files: project.data.files,
|
||||||
|
targets: project.data.targets,
|
||||||
},
|
},
|
||||||
} as ProjectGraphProjectNode)
|
} as ProjectGraphProjectNode)
|
||||||
);
|
);
|
||||||
@ -520,3 +549,86 @@ async function createDepGraphClientResponse(
|
|||||||
affected,
|
affected,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function createTaskGraphClientResponse(): Promise<TaskGraphClientResponse> {
|
||||||
|
let graph = pruneExternalNodes(
|
||||||
|
await createProjectGraphAsync({ exitOnError: true })
|
||||||
|
);
|
||||||
|
|
||||||
|
performance.mark('task graph generation:start');
|
||||||
|
|
||||||
|
const tasks = getAllTaskGraphsForWorkspace(graph);
|
||||||
|
|
||||||
|
performance.mark('task graph generation:end');
|
||||||
|
|
||||||
|
performance.measure(
|
||||||
|
'task graph generation',
|
||||||
|
'task graph generation:start',
|
||||||
|
'task graph generation:end'
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dependencies: tasks,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAllTaskGraphsForWorkspace(
|
||||||
|
projectGraph: ProjectGraph
|
||||||
|
): TaskGraphDependencies {
|
||||||
|
const nxJson = readNxJson();
|
||||||
|
|
||||||
|
const defaultDependencyConfigs = mapTargetDefaultsToDependencies(
|
||||||
|
nxJson.targetDefaults
|
||||||
|
);
|
||||||
|
|
||||||
|
const taskGraphs: TaskGraphDependencies = {};
|
||||||
|
|
||||||
|
for (const projectName in projectGraph.nodes) {
|
||||||
|
const project = projectGraph.nodes[projectName];
|
||||||
|
const targets = Object.keys(project.data.targets);
|
||||||
|
|
||||||
|
taskGraphs[projectName] = {};
|
||||||
|
|
||||||
|
targets.forEach((target) => {
|
||||||
|
taskGraphs[projectName][target] = {};
|
||||||
|
|
||||||
|
const configurations = Object.keys(
|
||||||
|
project.data.targets[target]?.configurations || {}
|
||||||
|
);
|
||||||
|
if (configurations.length > 0) {
|
||||||
|
configurations.forEach((configuration) => {
|
||||||
|
taskGraphs[projectName][target][configuration] = createTaskGraph(
|
||||||
|
projectGraph,
|
||||||
|
defaultDependencyConfigs,
|
||||||
|
[projectName],
|
||||||
|
[target],
|
||||||
|
configuration,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
taskGraphs[projectName][target]['no-configurations'] = createTaskGraph(
|
||||||
|
projectGraph,
|
||||||
|
defaultDependencyConfigs,
|
||||||
|
[projectName],
|
||||||
|
[target],
|
||||||
|
undefined,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return taskGraphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapTargetDefaultsToDependencies(
|
||||||
|
defaults: TargetDefaults
|
||||||
|
): TargetDependencies {
|
||||||
|
const res = {};
|
||||||
|
Object.keys(defaults).forEach((k) => {
|
||||||
|
res[k] = defaults[k].dependsOn;
|
||||||
|
});
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user