feat(graph): add project details view (#20466)
Co-authored-by: FrozenPandaz <jasonjean1993@gmail.com>
This commit is contained in:
parent
a08fdf0e36
commit
75cc561e9d
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@ jest.debug.config.js
|
|||||||
/graph/client/src/assets/generated-project-graphs
|
/graph/client/src/assets/generated-project-graphs
|
||||||
/graph/client/src/assets/generated-task-graphs
|
/graph/client/src/assets/generated-task-graphs
|
||||||
/graph/client/src/assets/generated-task-inputs
|
/graph/client/src/assets/generated-task-inputs
|
||||||
|
/graph/client/src/assets/generated-source-maps
|
||||||
/nx-dev/nx-dev/public/documentation
|
/nx-dev/nx-dev/public/documentation
|
||||||
/nx-dev/nx-dev/public/images/open-graph
|
/nx-dev/nx-dev/public/images/open-graph
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,7 @@
|
|||||||
"graph/client/src/assets/generated-project-graphs/",
|
"graph/client/src/assets/generated-project-graphs/",
|
||||||
"graph/client/src/assets/generated-task-graphs/",
|
"graph/client/src/assets/generated-task-graphs/",
|
||||||
"graph/client/src/assets/generated-task-inputs/",
|
"graph/client/src/assets/generated-task-inputs/",
|
||||||
|
"graph/client/src/assets/generated-source-maps/",
|
||||||
{
|
{
|
||||||
"input": "graph/client/src/assets/dev",
|
"input": "graph/client/src/assets/dev",
|
||||||
"output": "/",
|
"output": "/",
|
||||||
@ -81,6 +82,7 @@
|
|||||||
"graph/client/src/assets/project-graphs/",
|
"graph/client/src/assets/project-graphs/",
|
||||||
"graph/client/src/assets/task-graphs/",
|
"graph/client/src/assets/task-graphs/",
|
||||||
"graph/client/src/assets/task-inputs/",
|
"graph/client/src/assets/task-inputs/",
|
||||||
|
"graph/client/src/assets/source-maps/",
|
||||||
{
|
{
|
||||||
"input": "graph/client/src/assets/dev-e2e",
|
"input": "graph/client/src/assets/dev-e2e",
|
||||||
"output": "/",
|
"output": "/",
|
||||||
@ -116,6 +118,11 @@
|
|||||||
"output": "/assets/task-graphs",
|
"output": "/assets/task-graphs",
|
||||||
"glob": "e2e.json"
|
"glob": "e2e.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"input": "graph/client/src/assets/source-maps",
|
||||||
|
"output": "/assets/source-maps",
|
||||||
|
"glob": "e2e.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"input": "graph/client/src/assets/release",
|
"input": "graph/client/src/assets/release",
|
||||||
"output": "/",
|
"output": "/",
|
||||||
|
|||||||
@ -34,6 +34,16 @@ export class FetchProjectGraphService implements ProjectGraphService {
|
|||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSourceMaps(
|
||||||
|
url: string
|
||||||
|
): Promise<Record<string, Record<string, string[]>>> {
|
||||||
|
const request = new Request(url, { mode: 'no-cors' });
|
||||||
|
|
||||||
|
const response = await fetch(request);
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
setTaskInputsUrl(url: string) {
|
setTaskInputsUrl(url: string) {
|
||||||
this.taskInputsUrl = url;
|
this.taskInputsUrl = url;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export interface WorkspaceData {
|
|||||||
projectGraphUrl: string;
|
projectGraphUrl: string;
|
||||||
taskGraphUrl: string;
|
taskGraphUrl: string;
|
||||||
taskInputsUrl: string;
|
taskInputsUrl: string;
|
||||||
|
sourceMapsUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WorkspaceLayout {
|
export interface WorkspaceLayout {
|
||||||
@ -25,6 +26,9 @@ export interface ProjectGraphService {
|
|||||||
getTaskGraph: (url: string) => Promise<TaskGraphClientResponse>;
|
getTaskGraph: (url: string) => Promise<TaskGraphClientResponse>;
|
||||||
setTaskInputsUrl?: (url: string) => void;
|
setTaskInputsUrl?: (url: string) => void;
|
||||||
getExpandedTaskInputs?: (taskId: string) => Promise<Record<string, string[]>>;
|
getExpandedTaskInputs?: (taskId: string) => Promise<Record<string, string[]>>;
|
||||||
|
getSourceMaps?: (
|
||||||
|
url: string
|
||||||
|
) => Promise<Record<string, Record<string, string[]>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Environment {
|
export interface Environment {
|
||||||
|
|||||||
@ -27,4 +27,10 @@ export class LocalProjectGraphService implements ProjectGraphService {
|
|||||||
resolve(window.expandedTaskInputsResponse[taskId])
|
resolve(window.expandedTaskInputsResponse[taskId])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSourceMaps(
|
||||||
|
url: string
|
||||||
|
): Promise<Record<string, Record<string, string[]>>> {
|
||||||
|
return new Promise((resolve) => resolve(window.sourceMapsResponse));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { ProjectGraphClientResponse } from 'nx/src/command-line/graph/graph';
|
|||||||
/* eslint-enable @nx/enforce-module-boundaries */
|
/* eslint-enable @nx/enforce-module-boundaries */
|
||||||
import { getProjectGraphDataService } from './hooks/get-project-graph-data-service';
|
import { getProjectGraphDataService } from './hooks/get-project-graph-data-service';
|
||||||
import { TasksSidebarErrorBoundary } from './feature-tasks/tasks-sidebar-error-boundary';
|
import { TasksSidebarErrorBoundary } from './feature-tasks/tasks-sidebar-error-boundary';
|
||||||
|
import { ProjectDetails } from '@nx/graph/project-details';
|
||||||
|
|
||||||
const { appConfig } = getEnvironmentConfig();
|
const { appConfig } = getEnvironmentConfig();
|
||||||
const projectGraphDataService = getProjectGraphDataService();
|
const projectGraphDataService = getProjectGraphDataService();
|
||||||
@ -47,11 +48,37 @@ const workspaceDataLoader = async (selectedWorkspaceId: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const taskDataLoader = async (selectedWorkspaceId: string) => {
|
const taskDataLoader = async (selectedWorkspaceId: string) => {
|
||||||
const projectInfo = appConfig.workspaces.find(
|
const workspaceInfo = appConfig.workspaces.find(
|
||||||
(graph) => graph.id === selectedWorkspaceId
|
(graph) => graph.id === selectedWorkspaceId
|
||||||
);
|
);
|
||||||
|
|
||||||
return await projectGraphDataService.getTaskGraph(projectInfo.taskGraphUrl);
|
return await projectGraphDataService.getTaskGraph(workspaceInfo.taskGraphUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const sourceMapsLoader = async (selectedWorkspaceId: string) => {
|
||||||
|
const workspaceInfo = appConfig.workspaces.find(
|
||||||
|
(graph) => graph.id === selectedWorkspaceId
|
||||||
|
);
|
||||||
|
|
||||||
|
return await projectGraphDataService.getSourceMaps(
|
||||||
|
workspaceInfo.sourceMapsUrl
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const projectDetailsLoader = async (
|
||||||
|
selectedWorkspaceId: string,
|
||||||
|
projectName: string
|
||||||
|
) => {
|
||||||
|
const workspaceData = await workspaceDataLoader(selectedWorkspaceId);
|
||||||
|
const sourceMaps = await sourceMapsLoader(selectedWorkspaceId);
|
||||||
|
|
||||||
|
const project = workspaceData.projects.find(
|
||||||
|
(project) => project.name === projectName
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
project,
|
||||||
|
sourceMap: sourceMaps[project.data.root],
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const childRoutes: RouteObject[] = [
|
const childRoutes: RouteObject[] = [
|
||||||
@ -146,6 +173,15 @@ export const devRoutes: RouteObject[] = [
|
|||||||
},
|
},
|
||||||
children: childRoutes,
|
children: childRoutes,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: ':selectedWorkspaceId/project-details/:projectName',
|
||||||
|
id: 'selectedProjectDetails',
|
||||||
|
element: <ProjectDetails />,
|
||||||
|
loader: async ({ request, params }) => {
|
||||||
|
const projectName = params.projectName;
|
||||||
|
return projectDetailsLoader(params.selectedWorkspaceId, projectName);
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -174,4 +210,13 @@ export const releaseRoutes: RouteObject[] = [
|
|||||||
...childRoutes,
|
...childRoutes,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'project-details/:projectName',
|
||||||
|
id: 'selectedProjectDetails',
|
||||||
|
element: <ProjectDetails />,
|
||||||
|
loader: async ({ request, params }) => {
|
||||||
|
const projectName = params.projectName;
|
||||||
|
return projectDetailsLoader(appConfig.defaultWorkspaceId, projectName);
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -13,6 +13,7 @@ window.appConfig = {
|
|||||||
projectGraphUrl: 'assets/project-graphs/e2e.json',
|
projectGraphUrl: 'assets/project-graphs/e2e.json',
|
||||||
taskGraphUrl: 'assets/task-graphs/e2e.json',
|
taskGraphUrl: 'assets/task-graphs/e2e.json',
|
||||||
taskInputsUrl: 'assets/task-inputs/e2e.json',
|
taskInputsUrl: 'assets/task-inputs/e2e.json',
|
||||||
|
sourceMapsUrl: 'assets/source-maps/e2e.json',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
defaultWorkspaceId: 'local',
|
defaultWorkspaceId: 'local',
|
||||||
|
|||||||
1753
graph/client/src/assets/source-maps/e2e-affected.json
Normal file
1753
graph/client/src/assets/source-maps/e2e-affected.json
Normal file
File diff suppressed because it is too large
Load Diff
1753
graph/client/src/assets/source-maps/e2e.json
Normal file
1753
graph/client/src/assets/source-maps/e2e.json
Normal file
File diff suppressed because it is too large
Load Diff
4
graph/client/src/globals.d.ts
vendored
4
graph/client/src/globals.d.ts
vendored
@ -8,6 +8,9 @@ import type {
|
|||||||
/* eslint-enable @nx/enforce-module-boundaries */
|
/* eslint-enable @nx/enforce-module-boundaries */
|
||||||
import { AppConfig } from './app/interfaces';
|
import { AppConfig } from './app/interfaces';
|
||||||
import { ExternalApi } from './app/external-api';
|
import { ExternalApi } from './app/external-api';
|
||||||
|
/* eslint-disable @nx/enforce-module-boundaries */
|
||||||
|
// nx-ignore-next-line
|
||||||
|
import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils';
|
||||||
|
|
||||||
export declare global {
|
export declare global {
|
||||||
export interface Window {
|
export interface Window {
|
||||||
@ -17,6 +20,7 @@ export declare global {
|
|||||||
projectGraphResponse?: ProjectGraphClientResponse;
|
projectGraphResponse?: ProjectGraphClientResponse;
|
||||||
taskGraphResponse?: TaskGraphClientResponse;
|
taskGraphResponse?: TaskGraphClientResponse;
|
||||||
expandedTaskInputsResponse?: ExpandedTaskInputsReponse;
|
expandedTaskInputsResponse?: ExpandedTaskInputsReponse;
|
||||||
|
sourceMapsResponse?: ConfigurationSourceMaps;
|
||||||
environment: 'dev' | 'watch' | 'release' | 'nx-console';
|
environment: 'dev' | 'watch' | 'release' | 'nx-console';
|
||||||
appConfig: AppConfig;
|
appConfig: AppConfig;
|
||||||
useXstateInspect: boolean;
|
useXstateInspect: boolean;
|
||||||
|
|||||||
12
graph/project-details/.babelrc
Normal file
12
graph/project-details/.babelrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@nx/react/babel",
|
||||||
|
{
|
||||||
|
"runtime": "automatic",
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": []
|
||||||
|
}
|
||||||
18
graph/project-details/.eslintrc.json
Normal file
18
graph/project-details/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
|
||||||
|
"ignorePatterns": ["!**/*"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.ts", "*.tsx"],
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.js", "*.jsx"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
7
graph/project-details/README.md
Normal file
7
graph/project-details/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# project-details
|
||||||
|
|
||||||
|
This library was generated with [Nx](https://nx.dev).
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `nx test project-details` to execute the unit tests via [Jest](https://jestjs.io).
|
||||||
16
graph/project-details/project.json
Normal file
16
graph/project-details/project.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "graph-project-details",
|
||||||
|
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||||
|
"sourceRoot": "graph/project-details/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"tags": [],
|
||||||
|
"targets": {
|
||||||
|
"lint": {
|
||||||
|
"executor": "@nx/eslint:lint",
|
||||||
|
"outputs": ["{options.outputFile}"],
|
||||||
|
"options": {
|
||||||
|
"lintFilePatterns": ["graph/project-details/**/*.{ts,tsx,js,jsx}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
graph/project-details/src/index.ts
Normal file
1
graph/project-details/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './lib/project-details';
|
||||||
16
graph/project-details/src/lib/get-source-information.ts
Normal file
16
graph/project-details/src/lib/get-source-information.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export function getSourceInformation(
|
||||||
|
sourceMap: Record<string, string[]>,
|
||||||
|
key: string
|
||||||
|
): string | undefined {
|
||||||
|
const sourceInfo = sourceMap?.[key];
|
||||||
|
if (sourceInfo) {
|
||||||
|
return `${key} was set by plugin \n \n ${sourceInfo[1]} \n \n while processing \n \n ${sourceInfo[0]}`;
|
||||||
|
}
|
||||||
|
if (!key.includes('.')) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return getSourceInformation(
|
||||||
|
sourceMap,
|
||||||
|
key.substring(0, key.lastIndexOf('.'))
|
||||||
|
);
|
||||||
|
}
|
||||||
66
graph/project-details/src/lib/project-details.tsx
Normal file
66
graph/project-details/src/lib/project-details.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
import styles from './app.module.css';
|
||||||
|
import Target from './target';
|
||||||
|
|
||||||
|
import PropertyRenderer from './property-renderer';
|
||||||
|
import { useRouteLoaderData } from 'react-router-dom';
|
||||||
|
|
||||||
|
/* eslint-disable @nx/enforce-module-boundaries */
|
||||||
|
// nx-ignore-next-line
|
||||||
|
import { ProjectGraphProjectNode } from '@nx/devkit';
|
||||||
|
|
||||||
|
export function ProjectDetails() {
|
||||||
|
const {
|
||||||
|
project: {
|
||||||
|
name,
|
||||||
|
data: { targets, root, ...projectData },
|
||||||
|
},
|
||||||
|
sourceMap,
|
||||||
|
} = useRouteLoaderData('selectedProjectDetails') as {
|
||||||
|
project: ProjectGraphProjectNode;
|
||||||
|
sourceMap: Record<string, string[]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-4 overflow-auto w-full">
|
||||||
|
<h1 className="text-2xl">{name}</h1>
|
||||||
|
<h2 className="text-lg pl-6 mb-3 flex flex-row gap-2">
|
||||||
|
{root}{' '}
|
||||||
|
{projectData.tags?.map((tag) => (
|
||||||
|
<p className="bg-slate-300">{tag}</p>
|
||||||
|
))}
|
||||||
|
</h2>
|
||||||
|
<div>
|
||||||
|
<div className="mb-2">
|
||||||
|
<h2 className="text-xl">Targets</h2>
|
||||||
|
{Object.entries(targets ?? {}).map(([targetName, target]) =>
|
||||||
|
Target({
|
||||||
|
targetName: targetName,
|
||||||
|
targetConfiguration: target,
|
||||||
|
sourceMap,
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{Object.entries(projectData).map(([key, value]) => {
|
||||||
|
if (
|
||||||
|
key === 'targets' ||
|
||||||
|
key === 'root' ||
|
||||||
|
key === 'name' ||
|
||||||
|
key === '$schema' ||
|
||||||
|
key === 'tags' ||
|
||||||
|
key === 'files'
|
||||||
|
)
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
return PropertyRenderer({
|
||||||
|
propertyKey: key,
|
||||||
|
propertyValue: value,
|
||||||
|
sourceMap,
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProjectDetails;
|
||||||
116
graph/project-details/src/lib/property-renderer.tsx
Normal file
116
graph/project-details/src/lib/property-renderer.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { getSourceInformation } from './get-source-information';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface PropertyRendererProps {
|
||||||
|
propertyKey: string;
|
||||||
|
propertyValue: any;
|
||||||
|
keyPrefix?: string;
|
||||||
|
sourceMap: Record<string, string[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PropertyRenderer(props: PropertyRendererProps) {
|
||||||
|
const { propertyValue, propertyKey, sourceMap, keyPrefix } = props;
|
||||||
|
const sourceMapKey = `${keyPrefix ? `${keyPrefix}.` : ''}${propertyKey}`;
|
||||||
|
const isCollapsible = propertyValue && typeof propertyValue === 'object';
|
||||||
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
||||||
|
|
||||||
|
const toggleCollapse = () => {
|
||||||
|
setIsCollapsed(!isCollapsed);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div title={getSourceInformation(sourceMap, sourceMapKey)}>
|
||||||
|
{isCollapsible && (
|
||||||
|
<button className="text-xs" onClick={toggleCollapse}>
|
||||||
|
{isCollapsed ? '\u25B6' : '\u25BC'}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<span className="font-medium">{propertyKey}</span>:{' '}
|
||||||
|
{renderOpening(propertyValue)}
|
||||||
|
{!isCollapsed || !isCollapsible ? (
|
||||||
|
<PropertyValueRenderer {...props} />
|
||||||
|
) : (
|
||||||
|
'...'
|
||||||
|
)}
|
||||||
|
{renderClosing(propertyValue)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type PropertValueRendererProps = PropertyRendererProps & {
|
||||||
|
nested?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
function PropertyValueRenderer(props: PropertValueRendererProps) {
|
||||||
|
const { propertyKey, propertyValue, sourceMap, keyPrefix, nested } = props;
|
||||||
|
|
||||||
|
if (Array.isArray(propertyValue) && propertyValue.length) {
|
||||||
|
return (
|
||||||
|
<div className="ml-3">
|
||||||
|
{nested && renderOpening(propertyValue)}
|
||||||
|
{propertyValue.map((v) =>
|
||||||
|
PropertyValueRenderer({
|
||||||
|
propertyKey,
|
||||||
|
propertyValue: v,
|
||||||
|
sourceMap,
|
||||||
|
keyPrefix: `${keyPrefix ? `${keyPrefix}.` : ''}${v}`,
|
||||||
|
nested: true,
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
{nested && renderClosing(propertyValue)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else if (propertyValue && typeof propertyValue === 'object') {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
title={getSourceInformation(
|
||||||
|
sourceMap,
|
||||||
|
`${keyPrefix ? `${keyPrefix}.` : ''}${propertyKey}`
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{nested && renderOpening(propertyValue)}
|
||||||
|
<div className="ml-3">
|
||||||
|
{Object.entries(propertyValue)
|
||||||
|
.filter(
|
||||||
|
([, value]) =>
|
||||||
|
value && (Array.isArray(value) ? value.length : true)
|
||||||
|
)
|
||||||
|
.map(([key, value]) =>
|
||||||
|
PropertyRenderer({
|
||||||
|
propertyKey: key,
|
||||||
|
propertyValue: value,
|
||||||
|
keyPrefix: `${keyPrefix ? `${keyPrefix}.` : ''}${propertyKey}`,
|
||||||
|
sourceMap,
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{nested && renderClosing(propertyValue)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<code>{`${propertyValue}`}</code>,
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderOpening(value: any): string {
|
||||||
|
return Array.isArray(value) && value.length
|
||||||
|
? '['
|
||||||
|
: value && typeof value === 'object'
|
||||||
|
? '{'
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderClosing(value: any): string {
|
||||||
|
return Array.isArray(value) && value.length
|
||||||
|
? '],'
|
||||||
|
: value && typeof value === 'object'
|
||||||
|
? '},'
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PropertyRenderer;
|
||||||
10
graph/project-details/src/lib/target.spec.tsx
Normal file
10
graph/project-details/src/lib/target.spec.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import Target from './target';
|
||||||
|
|
||||||
|
describe('Target', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<Target />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
32
graph/project-details/src/lib/target.tsx
Normal file
32
graph/project-details/src/lib/target.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable @nx/enforce-module-boundaries */
|
||||||
|
// nx-ignore-next-line
|
||||||
|
import { TargetConfiguration } from '@nx/devkit';
|
||||||
|
import PropertyRenderer from './property-renderer';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface TargetProps {
|
||||||
|
targetName: string;
|
||||||
|
targetConfiguration: TargetConfiguration;
|
||||||
|
sourceMap: Record<string, string[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Target(props: TargetProps) {
|
||||||
|
return (
|
||||||
|
<div className="ml-3 mb-3">
|
||||||
|
<h3 className="text-lg font-bold">{props.targetName}</h3>
|
||||||
|
<div className="ml-3">
|
||||||
|
{Object.entries(props.targetConfiguration).map(([key, value]) =>
|
||||||
|
PropertyRenderer({
|
||||||
|
propertyKey: key,
|
||||||
|
propertyValue: value,
|
||||||
|
keyPrefix: `targets.${props.targetName}`,
|
||||||
|
sourceMap: props.sourceMap,
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Target;
|
||||||
17
graph/project-details/tsconfig.json
Normal file
17
graph/project-details/tsconfig.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowJs": false,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"files": [],
|
||||||
|
"include": [],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.lib.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extends": "../../tsconfig.base.json"
|
||||||
|
}
|
||||||
24
graph/project-details/tsconfig.lib.json
Normal file
24
graph/project-details/tsconfig.lib.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../dist/out-tsc",
|
||||||
|
"types": [
|
||||||
|
"node",
|
||||||
|
|
||||||
|
"@nx/react/typings/cssmodule.d.ts",
|
||||||
|
"@nx/react/typings/image.d.ts"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"jest.config.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.tsx",
|
||||||
|
"src/**/*.test.tsx",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.test.js",
|
||||||
|
"src/**/*.spec.jsx",
|
||||||
|
"src/**/*.test.jsx"
|
||||||
|
],
|
||||||
|
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { buildProjectGraphWithoutDaemon } from '../src/project-graph/project-graph';
|
import { buildProjectGraphAndSourceMapsWithoutDaemon } from '../src/project-graph/project-graph';
|
||||||
import { workspaceRoot } from '../src/utils/workspace-root';
|
import { workspaceRoot } from '../src/utils/workspace-root';
|
||||||
import { fileExists } from '../src/utils/fileutils';
|
import { fileExists } from '../src/utils/fileutils';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -20,7 +20,9 @@ import { setupWorkspaceContext } from '../src/utils/workspace-context';
|
|||||||
try {
|
try {
|
||||||
await daemonClient.stop();
|
await daemonClient.stop();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
const tasks: Array<Promise<any>> = [buildProjectGraphWithoutDaemon()];
|
const tasks: Array<Promise<any>> = [
|
||||||
|
buildProjectGraphAndSourceMapsWithoutDaemon(),
|
||||||
|
];
|
||||||
if (isNxCloudUsed(readNxJson())) {
|
if (isNxCloudUsed(readNxJson())) {
|
||||||
tasks.push(verifyOrUpdateNxCloudClient(getCloudOptions()));
|
tasks.push(verifyOrUpdateNxCloudClient(getCloudOptions()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,10 @@ import { TaskGraph } from '../../config/task-graph';
|
|||||||
import { daemonClient } from '../../daemon/client/client';
|
import { daemonClient } from '../../daemon/client/client';
|
||||||
import { getRootTsConfigPath } from '../../plugins/js/utils/typescript';
|
import { getRootTsConfigPath } from '../../plugins/js/utils/typescript';
|
||||||
import { pruneExternalNodes } from '../../project-graph/operators';
|
import { pruneExternalNodes } from '../../project-graph/operators';
|
||||||
import { createProjectGraphAsync } from '../../project-graph/project-graph';
|
import {
|
||||||
|
createProjectGraphAndSourceMapsAsync,
|
||||||
|
createProjectGraphAsync,
|
||||||
|
} from '../../project-graph/project-graph';
|
||||||
import {
|
import {
|
||||||
createTaskGraph,
|
createTaskGraph,
|
||||||
mapTargetDefaultsToDependencies,
|
mapTargetDefaultsToDependencies,
|
||||||
@ -45,6 +48,7 @@ import { HashPlanner, transferProjectGraph } from '../../native';
|
|||||||
import { transformProjectGraphForRust } from '../../native/transform-objects';
|
import { transformProjectGraphForRust } from '../../native/transform-objects';
|
||||||
import { getAffectedGraphNodes } from '../affected/affected';
|
import { getAffectedGraphNodes } from '../affected/affected';
|
||||||
import { readFileMapCache } from '../../project-graph/nx-deps-cache';
|
import { readFileMapCache } from '../../project-graph/nx-deps-cache';
|
||||||
|
import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils';
|
||||||
|
|
||||||
import { filterUsingGlobPatterns } from '../../hasher/task-hasher';
|
import { filterUsingGlobPatterns } from '../../hasher/task-hasher';
|
||||||
|
|
||||||
@ -94,7 +98,8 @@ function buildEnvironmentJs(
|
|||||||
localMode: 'build' | 'serve',
|
localMode: 'build' | 'serve',
|
||||||
depGraphClientResponse?: ProjectGraphClientResponse,
|
depGraphClientResponse?: ProjectGraphClientResponse,
|
||||||
taskGraphClientResponse?: TaskGraphClientResponse,
|
taskGraphClientResponse?: TaskGraphClientResponse,
|
||||||
expandedTaskInputsReponse?: ExpandedTaskInputsReponse
|
expandedTaskInputsReponse?: ExpandedTaskInputsReponse,
|
||||||
|
sourceMapsResponse?: ConfigurationSourceMaps
|
||||||
) {
|
) {
|
||||||
let environmentJs = `window.exclude = ${JSON.stringify(exclude)};
|
let environmentJs = `window.exclude = ${JSON.stringify(exclude)};
|
||||||
window.watch = ${!!watchMode};
|
window.watch = ${!!watchMode};
|
||||||
@ -111,6 +116,7 @@ function buildEnvironmentJs(
|
|||||||
projectGraphUrl: 'project-graph.json',
|
projectGraphUrl: 'project-graph.json',
|
||||||
taskGraphUrl: 'task-graph.json',
|
taskGraphUrl: 'task-graph.json',
|
||||||
taskInputsUrl: 'task-inputs.json',
|
taskInputsUrl: 'task-inputs.json',
|
||||||
|
sourceMapsUrl: 'source-maps.json'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
defaultWorkspaceId: 'local',
|
defaultWorkspaceId: 'local',
|
||||||
@ -130,10 +136,15 @@ function buildEnvironmentJs(
|
|||||||
environmentJs += `window.expandedTaskInputsResponse = ${JSON.stringify(
|
environmentJs += `window.expandedTaskInputsResponse = ${JSON.stringify(
|
||||||
expandedTaskInputsReponse
|
expandedTaskInputsReponse
|
||||||
)};`;
|
)};`;
|
||||||
|
|
||||||
|
environmentJs += `window.sourceMapsResponse = ${JSON.stringify(
|
||||||
|
sourceMapsResponse
|
||||||
|
)};`;
|
||||||
} else {
|
} else {
|
||||||
environmentJs += `window.projectGraphResponse = null;`;
|
environmentJs += `window.projectGraphResponse = null;`;
|
||||||
environmentJs += `window.taskGraphResponse = null;`;
|
environmentJs += `window.taskGraphResponse = null;`;
|
||||||
environmentJs += `window.expandedTaskInputsResponse = null;`;
|
environmentJs += `window.expandedTaskInputsResponse = null;`;
|
||||||
|
environmentJs += `window.sourceMapsResponse = null;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return environmentJs;
|
return environmentJs;
|
||||||
@ -214,7 +225,7 @@ export async function generateGraph(
|
|||||||
groupByFolder?: boolean;
|
groupByFolder?: boolean;
|
||||||
watch?: boolean;
|
watch?: boolean;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
view: 'projects' | 'tasks';
|
view: 'projects' | 'tasks' | 'project-details';
|
||||||
projects?: string[];
|
projects?: string[];
|
||||||
all?: boolean;
|
all?: boolean;
|
||||||
targets?: string[];
|
targets?: string[];
|
||||||
@ -238,12 +249,33 @@ export async function generateGraph(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.view === 'project-details' && !args.focus) {
|
||||||
|
output.error({
|
||||||
|
title: `The project details view requires the --focus option.`,
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
if (args.view === 'project-details' && (args.targets || args.affected)) {
|
||||||
|
output.error({
|
||||||
|
title: `The project details view can only be used with the --focus option.`,
|
||||||
|
bodyLines: [
|
||||||
|
`You passed ${args.targets ? '--targets ' : ''}${
|
||||||
|
args.affected ? '--affected ' : ''
|
||||||
|
}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Graph Client should support multiple targets
|
// TODO: Graph Client should support multiple targets
|
||||||
const target = Array.isArray(args.targets && args.targets.length >= 1)
|
const target = Array.isArray(args.targets && args.targets.length >= 1)
|
||||||
? args.targets[0]
|
? args.targets[0]
|
||||||
: args.targets;
|
: args.targets;
|
||||||
|
|
||||||
const rawGraph = await createProjectGraphAsync({ exitOnError: true });
|
const { projectGraph: rawGraph, sourceMaps } =
|
||||||
|
await createProjectGraphAndSourceMapsAsync({
|
||||||
|
exitOnError: true,
|
||||||
|
});
|
||||||
let prunedGraph = pruneExternalNodes(rawGraph);
|
let prunedGraph = pruneExternalNodes(rawGraph);
|
||||||
|
|
||||||
const projects = Object.values(
|
const projects = Object.values(
|
||||||
@ -339,23 +371,23 @@ export async function generateGraph(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const depGraphClientResponse = await createDepGraphClientResponse(
|
const { projectGraphClientResponse } =
|
||||||
affectedProjects
|
await createProjectGraphAndSourceMapClientResponse(affectedProjects);
|
||||||
);
|
|
||||||
|
|
||||||
const taskGraphClientResponse = await createTaskGraphClientResponse();
|
const taskGraphClientResponse = await createTaskGraphClientResponse();
|
||||||
const taskInputsReponse = await createExpandedTaskInputResponse(
|
const taskInputsReponse = await createExpandedTaskInputResponse(
|
||||||
taskGraphClientResponse,
|
taskGraphClientResponse,
|
||||||
depGraphClientResponse
|
projectGraphClientResponse
|
||||||
);
|
);
|
||||||
|
|
||||||
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,
|
projectGraphClientResponse,
|
||||||
taskGraphClientResponse,
|
taskGraphClientResponse,
|
||||||
taskInputsReponse
|
taskInputsReponse,
|
||||||
|
sourceMaps
|
||||||
);
|
);
|
||||||
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');
|
||||||
@ -472,10 +504,13 @@ async function startServer(
|
|||||||
unregisterFileWatcher = await createFileWatcher();
|
unregisterFileWatcher = await createFileWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDepGraphClientResponse = await createDepGraphClientResponse(affected);
|
const { projectGraphClientResponse, sourceMapResponse } =
|
||||||
currentDepGraphClientResponse.focus = focus;
|
await createProjectGraphAndSourceMapClientResponse(affected);
|
||||||
currentDepGraphClientResponse.groupByFolder = groupByFolder;
|
|
||||||
currentDepGraphClientResponse.exclude = exclude;
|
currentProjectGraphClientResponse = projectGraphClientResponse;
|
||||||
|
currentProjectGraphClientResponse.focus = focus;
|
||||||
|
currentProjectGraphClientResponse.groupByFolder = groupByFolder;
|
||||||
|
currentProjectGraphClientResponse.exclude = exclude;
|
||||||
|
|
||||||
const app = http.createServer(async (req, res) => {
|
const app = http.createServer(async (req, res) => {
|
||||||
// parse URL
|
// parse URL
|
||||||
@ -488,7 +523,7 @@ async function startServer(
|
|||||||
const sanitizePath = basename(parsedUrl.pathname);
|
const sanitizePath = basename(parsedUrl.pathname);
|
||||||
if (sanitizePath === 'project-graph.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(currentProjectGraphClientResponse));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,9 +550,15 @@ async function startServer(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sanitizePath === 'source-maps.json') {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
|
res.end(JSON.stringify(currentSourceMapsClientResponse));
|
||||||
|
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: currentProjectGraphClientResponse.hash }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +604,7 @@ async function startServer(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentDepGraphClientResponse: ProjectGraphClientResponse = {
|
let currentProjectGraphClientResponse: ProjectGraphClientResponse = {
|
||||||
hash: null,
|
hash: null,
|
||||||
projects: [],
|
projects: [],
|
||||||
dependencies: {},
|
dependencies: {},
|
||||||
@ -577,6 +618,7 @@ let currentDepGraphClientResponse: ProjectGraphClientResponse = {
|
|||||||
groupByFolder: false,
|
groupByFolder: false,
|
||||||
exclude: [],
|
exclude: [],
|
||||||
};
|
};
|
||||||
|
let currentSourceMapsClientResponse: ConfigurationSourceMaps = {};
|
||||||
|
|
||||||
function debounce(fn: (...args) => void, time: number) {
|
function debounce(fn: (...args) => void, time: number) {
|
||||||
let timeout: NodeJS.Timeout;
|
let timeout: NodeJS.Timeout;
|
||||||
@ -602,14 +644,17 @@ function createFileWatcher() {
|
|||||||
} else if (changes !== null && changes.changedFiles.length > 0) {
|
} else if (changes !== null && changes.changedFiles.length > 0) {
|
||||||
output.note({ title: 'Recalculating project graph...' });
|
output.note({ title: 'Recalculating project graph...' });
|
||||||
|
|
||||||
const newGraphClientResponse = await createDepGraphClientResponse();
|
const { projectGraphClientResponse, sourceMapResponse } =
|
||||||
|
await createProjectGraphAndSourceMapClientResponse();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
newGraphClientResponse.hash !== currentDepGraphClientResponse.hash
|
projectGraphClientResponse.hash !==
|
||||||
|
currentProjectGraphClientResponse.hash
|
||||||
) {
|
) {
|
||||||
output.note({ title: 'Graph changes updated.' });
|
output.note({ title: 'Graph changes updated.' });
|
||||||
|
|
||||||
currentDepGraphClientResponse = newGraphClientResponse;
|
currentProjectGraphClientResponse = projectGraphClientResponse;
|
||||||
|
currentSourceMapsClientResponse = sourceMapResponse;
|
||||||
} else {
|
} else {
|
||||||
output.note({ title: 'No graph changes found.' });
|
output.note({ title: 'No graph changes found.' });
|
||||||
}
|
}
|
||||||
@ -618,14 +663,18 @@ function createFileWatcher() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createDepGraphClientResponse(
|
async function createProjectGraphAndSourceMapClientResponse(
|
||||||
affected: string[] = []
|
affected: string[] = []
|
||||||
): Promise<ProjectGraphClientResponse> {
|
): Promise<{
|
||||||
|
projectGraphClientResponse: ProjectGraphClientResponse;
|
||||||
|
sourceMapResponse: ConfigurationSourceMaps;
|
||||||
|
}> {
|
||||||
performance.mark('project graph watch calculation:start');
|
performance.mark('project graph watch calculation:start');
|
||||||
|
|
||||||
let graph = pruneExternalNodes(
|
const { projectGraph, sourceMaps } =
|
||||||
await createProjectGraphAsync({ exitOnError: true })
|
await createProjectGraphAndSourceMapsAsync({ exitOnError: true });
|
||||||
);
|
|
||||||
|
let graph = pruneExternalNodes(projectGraph);
|
||||||
let fileMap = readFileMapCache().fileMap.projectFileMap;
|
let fileMap = readFileMapCache().fileMap.projectFileMap;
|
||||||
performance.mark('project graph watch calculation:end');
|
performance.mark('project graph watch calculation:end');
|
||||||
performance.mark('project graph response generation:start');
|
performance.mark('project graph response generation:start');
|
||||||
@ -654,13 +703,16 @@ async function createDepGraphClientResponse(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...currentDepGraphClientResponse,
|
projectGraphClientResponse: {
|
||||||
|
...currentProjectGraphClientResponse,
|
||||||
hash,
|
hash,
|
||||||
layout,
|
layout,
|
||||||
projects,
|
projects,
|
||||||
dependencies,
|
dependencies,
|
||||||
affected,
|
affected,
|
||||||
fileMap,
|
fileMap,
|
||||||
|
},
|
||||||
|
sourceMapResponse: sourceMaps,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,9 +898,11 @@ async function getExpandedTaskInputs(
|
|||||||
if (inputs) {
|
if (inputs) {
|
||||||
return expandInputs(
|
return expandInputs(
|
||||||
inputs,
|
inputs,
|
||||||
currentDepGraphClientResponse.projects.find((p) => p.name === project),
|
currentProjectGraphClientResponse.projects.find(
|
||||||
|
(p) => p.name === project
|
||||||
|
),
|
||||||
allWorkspaceFiles,
|
allWorkspaceFiles,
|
||||||
currentDepGraphClientResponse
|
currentProjectGraphClientResponse
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@ -21,6 +21,7 @@ export type ShowProjectsOptions = NxShowArgs & {
|
|||||||
|
|
||||||
export type ShowProjectOptions = NxShowArgs & {
|
export type ShowProjectOptions = NxShowArgs & {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
|
web?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const yargsShowCommand: CommandModule<
|
export const yargsShowCommand: CommandModule<
|
||||||
@ -121,6 +122,17 @@ const showProjectCommand: CommandModule<NxShowArgs, ShowProjectOptions> = {
|
|||||||
description: 'Which project should be viewed?',
|
description: 'Which project should be viewed?',
|
||||||
})
|
})
|
||||||
.default('json', true)
|
.default('json', true)
|
||||||
|
.option('web', {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Show project details in the browser',
|
||||||
|
hidden: true,
|
||||||
|
})
|
||||||
|
.check((argv) => {
|
||||||
|
if (argv.web) {
|
||||||
|
argv.json = false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
.example(
|
.example(
|
||||||
'$0 show project my-app',
|
'$0 show project my-app',
|
||||||
'View project information for my-app in JSON format'
|
'View project information for my-app in JSON format'
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import {
|
|||||||
} from '../../utils/command-line-utils';
|
} from '../../utils/command-line-utils';
|
||||||
import { findMatchingProjects } from '../../utils/find-matching-projects';
|
import { findMatchingProjects } from '../../utils/find-matching-projects';
|
||||||
import { ShowProjectOptions, ShowProjectsOptions } from './command-object';
|
import { ShowProjectOptions, ShowProjectsOptions } from './command-object';
|
||||||
|
import { generateGraph } from '../graph/graph';
|
||||||
|
|
||||||
export async function showProjectsHandler(
|
export async function showProjectsHandler(
|
||||||
args: ShowProjectsOptions
|
args: ShowProjectsOptions
|
||||||
@ -94,6 +95,16 @@ export async function showProjectHandler(
|
|||||||
}
|
}
|
||||||
if (args.json) {
|
if (args.json) {
|
||||||
console.log(JSON.stringify(node.data));
|
console.log(JSON.stringify(node.data));
|
||||||
|
} else if (args.web) {
|
||||||
|
await generateGraph(
|
||||||
|
{
|
||||||
|
view: 'project-details',
|
||||||
|
focus: node.name,
|
||||||
|
watch: false,
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const chalk = require('chalk') as typeof import('chalk');
|
const chalk = require('chalk') as typeof import('chalk');
|
||||||
const logIfExists = (label, key: keyof typeof node['data']) => {
|
const logIfExists = (label, key: keyof typeof node['data']) => {
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import { Message, SocketMessenger } from './socket-messenger';
|
|||||||
import { safelyCleanUpExistingProcess } from '../cache';
|
import { safelyCleanUpExistingProcess } from '../cache';
|
||||||
import { Hash } from '../../hasher/task-hasher';
|
import { Hash } from '../../hasher/task-hasher';
|
||||||
import { Task, TaskGraph } from '../../config/task-graph';
|
import { Task, TaskGraph } from '../../config/task-graph';
|
||||||
|
import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils';
|
||||||
|
|
||||||
const DAEMON_ENV_SETTINGS = {
|
const DAEMON_ENV_SETTINGS = {
|
||||||
...process.env,
|
...process.env,
|
||||||
@ -124,9 +125,17 @@ export class DaemonClient {
|
|||||||
return this.sendToDaemonViaQueue({ type: 'REQUEST_SHUTDOWN' });
|
return this.sendToDaemonViaQueue({ type: 'REQUEST_SHUTDOWN' });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectGraph(): Promise<ProjectGraph> {
|
async getProjectGraphAndSourceMaps(): Promise<{
|
||||||
return (await this.sendToDaemonViaQueue({ type: 'REQUEST_PROJECT_GRAPH' }))
|
projectGraph: ProjectGraph;
|
||||||
.projectGraph;
|
sourceMaps: ConfigurationSourceMaps;
|
||||||
|
}> {
|
||||||
|
const response = await this.sendToDaemonViaQueue({
|
||||||
|
type: 'REQUEST_PROJECT_GRAPH',
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
projectGraph: response.projectGraph,
|
||||||
|
sourceMaps: response.sourceMaps,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllFileData(): Promise<FileData[]> {
|
async getAllFileData(): Promise<FileData[]> {
|
||||||
@ -162,7 +171,7 @@ export class DaemonClient {
|
|||||||
} | null
|
} | null
|
||||||
) => void
|
) => void
|
||||||
): Promise<UnregisterCallback> {
|
): Promise<UnregisterCallback> {
|
||||||
await this.getProjectGraph();
|
await this.getProjectGraphAndSourceMaps();
|
||||||
let messenger: SocketMessenger | undefined;
|
let messenger: SocketMessenger | undefined;
|
||||||
|
|
||||||
await this.queue.sendToQueue(() => {
|
await this.queue.sendToQueue(() => {
|
||||||
|
|||||||
@ -19,7 +19,8 @@ export async function handleRequestProjectGraph(): Promise<HandlerResult> {
|
|||||||
|
|
||||||
const serializedResult = serializeResult(
|
const serializedResult = serializeResult(
|
||||||
result.error,
|
result.error,
|
||||||
result.serializedProjectGraph
|
result.serializedProjectGraph,
|
||||||
|
result.serializedSourceMaps
|
||||||
);
|
);
|
||||||
if (!serializedResult) {
|
if (!serializedResult) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import { readNxJson, NxJsonConfiguration } from '../../config/nx-json';
|
import { readNxJson } from '../../config/nx-json';
|
||||||
import {
|
import {
|
||||||
FileData,
|
FileData,
|
||||||
FileMap,
|
FileMap,
|
||||||
@ -21,7 +21,6 @@ import {
|
|||||||
retrieveWorkspaceFiles,
|
retrieveWorkspaceFiles,
|
||||||
} from '../../project-graph/utils/retrieve-workspace-files';
|
} from '../../project-graph/utils/retrieve-workspace-files';
|
||||||
import { fileExists } from '../../utils/fileutils';
|
import { fileExists } from '../../utils/fileutils';
|
||||||
import { writeSourceMaps } from '../../utils/source-maps';
|
|
||||||
import {
|
import {
|
||||||
resetWorkspaceContext,
|
resetWorkspaceContext,
|
||||||
updateFilesInContext,
|
updateFilesInContext,
|
||||||
@ -31,14 +30,17 @@ import { notifyFileWatcherSockets } from './file-watching/file-watcher-sockets';
|
|||||||
import { serverLogger } from './logger';
|
import { serverLogger } from './logger';
|
||||||
import { NxWorkspaceFilesExternals } from '../../native';
|
import { NxWorkspaceFilesExternals } from '../../native';
|
||||||
|
|
||||||
let cachedSerializedProjectGraphPromise: Promise<{
|
interface SerializedProjectGraph {
|
||||||
error: Error | null;
|
error: Error | null;
|
||||||
projectGraph: ProjectGraph | null;
|
projectGraph: ProjectGraph | null;
|
||||||
fileMap: FileMap | null;
|
fileMap: FileMap | null;
|
||||||
allWorkspaceFiles: FileData[] | null;
|
allWorkspaceFiles: FileData[] | null;
|
||||||
serializedProjectGraph: string | null;
|
serializedProjectGraph: string | null;
|
||||||
|
serializedSourceMaps: string | null;
|
||||||
rustReferences: NxWorkspaceFilesExternals | null;
|
rustReferences: NxWorkspaceFilesExternals | null;
|
||||||
}>;
|
}
|
||||||
|
|
||||||
|
let cachedSerializedProjectGraphPromise: Promise<SerializedProjectGraph>;
|
||||||
export let fileMapWithFiles:
|
export let fileMapWithFiles:
|
||||||
| {
|
| {
|
||||||
fileMap: FileMap;
|
fileMap: FileMap;
|
||||||
@ -56,7 +58,7 @@ let waitPeriod = 100;
|
|||||||
let scheduledTimeoutId;
|
let scheduledTimeoutId;
|
||||||
let knownExternalNodes: Record<string, ProjectGraphExternalNode> = {};
|
let knownExternalNodes: Record<string, ProjectGraphExternalNode> = {};
|
||||||
|
|
||||||
export async function getCachedSerializedProjectGraphPromise() {
|
export async function getCachedSerializedProjectGraphPromise(): Promise<SerializedProjectGraph> {
|
||||||
try {
|
try {
|
||||||
// recomputing it now on demand. we can ignore the scheduled timeout
|
// recomputing it now on demand. we can ignore the scheduled timeout
|
||||||
if (scheduledTimeoutId) {
|
if (scheduledTimeoutId) {
|
||||||
@ -81,6 +83,7 @@ export async function getCachedSerializedProjectGraphPromise() {
|
|||||||
return {
|
return {
|
||||||
error: e,
|
error: e,
|
||||||
serializedProjectGraph: null,
|
serializedProjectGraph: null,
|
||||||
|
serializedSourceMaps: null,
|
||||||
projectGraph: null,
|
projectGraph: null,
|
||||||
fileMap: null,
|
fileMap: null,
|
||||||
allWorkspaceFiles: null,
|
allWorkspaceFiles: null,
|
||||||
@ -196,7 +199,7 @@ async function processCollectedUpdatedAndDeletedFiles(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processFilesAndCreateAndSerializeProjectGraph() {
|
async function processFilesAndCreateAndSerializeProjectGraph(): Promise<SerializedProjectGraph> {
|
||||||
try {
|
try {
|
||||||
performance.mark('hash-watched-changes-start');
|
performance.mark('hash-watched-changes-start');
|
||||||
const updatedFiles = [...collectedUpdatedFiles.values()];
|
const updatedFiles = [...collectedUpdatedFiles.values()];
|
||||||
@ -214,17 +217,16 @@ async function processFilesAndCreateAndSerializeProjectGraph() {
|
|||||||
serverLogger.requestLog([...updatedFiles.values()]);
|
serverLogger.requestLog([...updatedFiles.values()]);
|
||||||
serverLogger.requestLog([...deletedFiles]);
|
serverLogger.requestLog([...deletedFiles]);
|
||||||
const nxJson = readNxJson(workspaceRoot);
|
const nxJson = readNxJson(workspaceRoot);
|
||||||
const configResult = await retrieveProjectConfigurations(
|
const graphNodes = await retrieveProjectConfigurations(
|
||||||
workspaceRoot,
|
workspaceRoot,
|
||||||
nxJson
|
nxJson
|
||||||
);
|
);
|
||||||
await processCollectedUpdatedAndDeletedFiles(
|
await processCollectedUpdatedAndDeletedFiles(
|
||||||
configResult,
|
graphNodes,
|
||||||
updatedFileHashes,
|
updatedFileHashes,
|
||||||
deletedFiles
|
deletedFiles
|
||||||
);
|
);
|
||||||
writeSourceMaps(configResult.sourceMaps);
|
return createAndSerializeProjectGraph(graphNodes);
|
||||||
return createAndSerializeProjectGraph(configResult);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
error: err,
|
error: err,
|
||||||
@ -233,6 +235,7 @@ async function processFilesAndCreateAndSerializeProjectGraph() {
|
|||||||
rustReferences: null,
|
rustReferences: null,
|
||||||
allWorkspaceFiles: null,
|
allWorkspaceFiles: null,
|
||||||
serializedProjectGraph: null,
|
serializedProjectGraph: null,
|
||||||
|
serializedSourceMaps: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,14 +257,8 @@ function copyFileMap(m: FileMap) {
|
|||||||
|
|
||||||
async function createAndSerializeProjectGraph({
|
async function createAndSerializeProjectGraph({
|
||||||
projects,
|
projects,
|
||||||
}: RetrievedGraphNodes): Promise<{
|
sourceMaps,
|
||||||
error: string | null;
|
}: RetrievedGraphNodes): Promise<SerializedProjectGraph> {
|
||||||
projectGraph: ProjectGraph | null;
|
|
||||||
fileMap: FileMap | null;
|
|
||||||
allWorkspaceFiles: FileData[] | null;
|
|
||||||
rustReferences: NxWorkspaceFilesExternals | null;
|
|
||||||
serializedProjectGraph: string | null;
|
|
||||||
}> {
|
|
||||||
try {
|
try {
|
||||||
performance.mark('create-project-graph-start');
|
performance.mark('create-project-graph-start');
|
||||||
const fileMap = copyFileMap(fileMapWithFiles.fileMap);
|
const fileMap = copyFileMap(fileMapWithFiles.fileMap);
|
||||||
@ -289,6 +286,7 @@ async function createAndSerializeProjectGraph({
|
|||||||
|
|
||||||
performance.mark('json-stringify-start');
|
performance.mark('json-stringify-start');
|
||||||
const serializedProjectGraph = JSON.stringify(projectGraph);
|
const serializedProjectGraph = JSON.stringify(projectGraph);
|
||||||
|
const serializedSourceMaps = JSON.stringify(sourceMaps);
|
||||||
performance.mark('json-stringify-end');
|
performance.mark('json-stringify-end');
|
||||||
performance.measure(
|
performance.measure(
|
||||||
'serialize graph',
|
'serialize graph',
|
||||||
@ -302,6 +300,7 @@ async function createAndSerializeProjectGraph({
|
|||||||
fileMap,
|
fileMap,
|
||||||
allWorkspaceFiles,
|
allWorkspaceFiles,
|
||||||
serializedProjectGraph,
|
serializedProjectGraph,
|
||||||
|
serializedSourceMaps,
|
||||||
rustReferences,
|
rustReferences,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -314,6 +313,7 @@ async function createAndSerializeProjectGraph({
|
|||||||
fileMap: null,
|
fileMap: null,
|
||||||
allWorkspaceFiles: null,
|
allWorkspaceFiles: null,
|
||||||
serializedProjectGraph: null,
|
serializedProjectGraph: null,
|
||||||
|
serializedSourceMaps: null,
|
||||||
rustReferences: null,
|
rustReferences: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,6 +99,6 @@ export async function respondWithErrorAndExit(
|
|||||||
|
|
||||||
error.message = `${error.message}\n\nBecause of the error the Nx daemon process has exited. The next Nx command is going to restart the daemon process.\nIf the error persists, please run "nx reset".`;
|
error.message = `${error.message}\n\nBecause of the error the Nx daemon process has exited. The next Nx command is going to restart the daemon process.\nIf the error persists, please run "nx reset".`;
|
||||||
|
|
||||||
await respondToClient(socket, serializeResult(error, null), null);
|
await respondToClient(socket, serializeResult(error, null, null), null);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,11 @@ function serializeError(error: Error | null): string | null {
|
|||||||
// Prepare a serialized project graph result for sending over IPC from the server to the client
|
// Prepare a serialized project graph result for sending over IPC from the server to the client
|
||||||
export function serializeResult(
|
export function serializeResult(
|
||||||
error: Error | null,
|
error: Error | null,
|
||||||
serializedProjectGraph: string | null
|
serializedProjectGraph: string | null,
|
||||||
|
serializedSourceMaps: string | null
|
||||||
): string | null {
|
): string | null {
|
||||||
// We do not want to repeat work `JSON.stringify`ing an object containing the potentially large project graph so merge as strings
|
// We do not want to repeat work `JSON.stringify`ing an object containing the potentially large project graph so merge as strings
|
||||||
return `{ "error": ${serializeError(
|
return `{ "error": ${serializeError(
|
||||||
error
|
error
|
||||||
)}, "projectGraph": ${serializedProjectGraph} }`;
|
)}, "projectGraph": ${serializedProjectGraph}, "sourceMaps": ${serializedSourceMaps} }`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import {
|
|||||||
} from './utils/retrieve-workspace-files';
|
} from './utils/retrieve-workspace-files';
|
||||||
import { readNxJson } from '../config/nx-json';
|
import { readNxJson } from '../config/nx-json';
|
||||||
import { unregisterPluginTSTranspiler } from '../utils/nx-plugin';
|
import { unregisterPluginTSTranspiler } from '../utils/nx-plugin';
|
||||||
import { writeSourceMaps } from '../utils/source-maps';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronously reads the latest cached copy of the workspace's ProjectGraph.
|
* Synchronously reads the latest cached copy of the workspace's ProjectGraph.
|
||||||
@ -78,7 +77,7 @@ export function readProjectsConfigurationFromProjectGraph(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildProjectGraphWithoutDaemon() {
|
export async function buildProjectGraphAndSourceMapsWithoutDaemon() {
|
||||||
const nxJson = readNxJson();
|
const nxJson = readNxJson();
|
||||||
|
|
||||||
performance.mark('retrieve-project-configurations:start');
|
performance.mark('retrieve-project-configurations:start');
|
||||||
@ -106,11 +105,9 @@ export async function buildProjectGraphWithoutDaemon() {
|
|||||||
).projectGraph;
|
).projectGraph;
|
||||||
performance.mark('build-project-graph-using-project-file-map:end');
|
performance.mark('build-project-graph-using-project-file-map:end');
|
||||||
|
|
||||||
writeSourceMaps(sourceMaps);
|
|
||||||
|
|
||||||
unregisterPluginTSTranspiler();
|
unregisterPluginTSTranspiler();
|
||||||
|
|
||||||
return projectGraph;
|
return { projectGraph, sourceMaps };
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleProjectGraphError(opts: { exitOnError: boolean }, e) {
|
function handleProjectGraphError(opts: { exitOnError: boolean }, e) {
|
||||||
@ -156,11 +153,23 @@ export async function createProjectGraphAsync(
|
|||||||
resetDaemonClient: false,
|
resetDaemonClient: false,
|
||||||
}
|
}
|
||||||
): Promise<ProjectGraph> {
|
): Promise<ProjectGraph> {
|
||||||
|
const projectGraphAndSourceMaps = await createProjectGraphAndSourceMapsAsync(
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
return projectGraphAndSourceMaps.projectGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createProjectGraphAndSourceMapsAsync(
|
||||||
|
opts: { exitOnError: boolean; resetDaemonClient?: boolean } = {
|
||||||
|
exitOnError: false,
|
||||||
|
resetDaemonClient: false,
|
||||||
|
}
|
||||||
|
) {
|
||||||
performance.mark('create-project-graph-async:start');
|
performance.mark('create-project-graph-async:start');
|
||||||
|
|
||||||
if (!daemonClient.enabled()) {
|
if (!daemonClient.enabled()) {
|
||||||
try {
|
try {
|
||||||
const res = await buildProjectGraphWithoutDaemon();
|
const res = await buildProjectGraphAndSourceMapsWithoutDaemon();
|
||||||
performance.measure(
|
performance.measure(
|
||||||
'create-project-graph-async >> retrieve-project-configurations',
|
'create-project-graph-async >> retrieve-project-configurations',
|
||||||
'retrieve-project-configurations:start',
|
'retrieve-project-configurations:start',
|
||||||
@ -188,7 +197,8 @@ export async function createProjectGraphAsync(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const projectGraph = await daemonClient.getProjectGraph();
|
const projectGraphAndSourceMaps =
|
||||||
|
await daemonClient.getProjectGraphAndSourceMaps();
|
||||||
if (opts.resetDaemonClient) {
|
if (opts.resetDaemonClient) {
|
||||||
daemonClient.reset();
|
daemonClient.reset();
|
||||||
}
|
}
|
||||||
@ -198,7 +208,7 @@ export async function createProjectGraphAsync(
|
|||||||
'create-project-graph-async:start',
|
'create-project-graph-async:start',
|
||||||
'create-project-graph-async:end'
|
'create-project-graph-async:end'
|
||||||
);
|
);
|
||||||
return projectGraph;
|
return projectGraphAndSourceMaps;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message.indexOf('inotify_add_watch') > -1) {
|
if (e.message.indexOf('inotify_add_watch') > -1) {
|
||||||
// common errors with the daemon due to OS settings (cannot watch all the files available)
|
// common errors with the daemon due to OS settings (cannot watch all the files available)
|
||||||
@ -210,7 +220,7 @@ export async function createProjectGraphAsync(
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
markDaemonAsDisabled();
|
markDaemonAsDisabled();
|
||||||
return buildProjectGraphWithoutDaemon();
|
return buildProjectGraphAndSourceMapsWithoutDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.internalDaemonError) {
|
if (e.internalDaemonError) {
|
||||||
@ -224,7 +234,7 @@ export async function createProjectGraphAsync(
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
markDaemonAsDisabled();
|
markDaemonAsDisabled();
|
||||||
return buildProjectGraphWithoutDaemon();
|
return buildProjectGraphAndSourceMapsWithoutDaemon();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleProjectGraphError(opts, e);
|
handleProjectGraphError(opts, e);
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import { getNxRequirePaths } from '../../utils/installation-directory';
|
import { getNxRequirePaths } from '../../utils/installation-directory';
|
||||||
import {
|
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||||
ProjectConfiguration,
|
|
||||||
ProjectsConfigurations,
|
|
||||||
} from '../../config/workspace-json-project-json';
|
|
||||||
import {
|
import {
|
||||||
NX_ANGULAR_JSON_PLUGIN_NAME,
|
NX_ANGULAR_JSON_PLUGIN_NAME,
|
||||||
NxAngularJsonPlugin,
|
NxAngularJsonPlugin,
|
||||||
@ -11,11 +8,10 @@ import {
|
|||||||
} from '../../adapter/angular-json';
|
} from '../../adapter/angular-json';
|
||||||
import { NxJsonConfiguration, readNxJson } from '../../config/nx-json';
|
import { NxJsonConfiguration, readNxJson } from '../../config/nx-json';
|
||||||
import { ProjectGraphExternalNode } from '../../config/project-graph';
|
import { ProjectGraphExternalNode } from '../../config/project-graph';
|
||||||
import type { NxWorkspaceFiles } from '../../native';
|
|
||||||
import { getNxPackageJsonWorkspacesPlugin } from '../../../plugins/package-json-workspaces';
|
import { getNxPackageJsonWorkspacesPlugin } from '../../../plugins/package-json-workspaces';
|
||||||
import {
|
import {
|
||||||
ConfigurationSourceMaps,
|
|
||||||
buildProjectsConfigurationsFromProjectPathsAndPlugins,
|
buildProjectsConfigurationsFromProjectPathsAndPlugins,
|
||||||
|
ConfigurationSourceMaps,
|
||||||
} from './project-configuration-utils';
|
} from './project-configuration-utils';
|
||||||
import {
|
import {
|
||||||
getDefaultPlugins,
|
getDefaultPlugins,
|
||||||
@ -24,8 +20,8 @@ import {
|
|||||||
} from '../../utils/nx-plugin';
|
} from '../../utils/nx-plugin';
|
||||||
import { CreateProjectJsonProjectsPlugin } from '../../plugins/project-json/build-nodes/project-json';
|
import { CreateProjectJsonProjectsPlugin } from '../../plugins/project-json/build-nodes/project-json';
|
||||||
import {
|
import {
|
||||||
globWithWorkspaceContext,
|
|
||||||
getNxWorkspaceFilesFromContext,
|
getNxWorkspaceFilesFromContext,
|
||||||
|
globWithWorkspaceContext,
|
||||||
} from '../../utils/workspace-context';
|
} from '../../utils/workspace-context';
|
||||||
import { buildAllWorkspaceFiles } from './build-all-workspace-files';
|
import { buildAllWorkspaceFiles } from './build-all-workspace-files';
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import { join } from 'path';
|
|
||||||
import { projectGraphCacheDirectory } from './cache-directory';
|
|
||||||
import { writeJsonFile } from './fileutils';
|
|
||||||
|
|
||||||
export function writeSourceMaps(
|
|
||||||
sourceMaps: Record<string, Record<string, string[]>>
|
|
||||||
) {
|
|
||||||
writeJsonFile(
|
|
||||||
join(projectGraphCacheDirectory, 'configuration-source-maps.json'),
|
|
||||||
sourceMaps
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -34,6 +34,7 @@ function writeFile() {
|
|||||||
projectGraphUrl: join('assets/generated-project-graphs/', filename),
|
projectGraphUrl: join('assets/generated-project-graphs/', filename),
|
||||||
taskGraphUrl: join('assets/generated-task-graphs/', filename),
|
taskGraphUrl: join('assets/generated-task-graphs/', filename),
|
||||||
taskInputsUrl: join('assets/generated-task-inputs/', filename),
|
taskInputsUrl: join('assets/generated-task-inputs/', filename),
|
||||||
|
sourceMapsUrl: join('assets/generated-source-maps/', filename),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
@ -52,6 +53,7 @@ function writeFile() {
|
|||||||
projectGraphUrl: join('assets/project-graphs/', filename),
|
projectGraphUrl: join('assets/project-graphs/', filename),
|
||||||
taskGraphUrl: join('assets/task-graphs/', filename),
|
taskGraphUrl: join('assets/task-graphs/', filename),
|
||||||
taskInputsUrl: join('assets/task-inputs/', filename),
|
taskInputsUrl: join('assets/task-inputs/', filename),
|
||||||
|
sourceMapsUrl: join('assets/source-maps/', filename),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@ -36,6 +36,10 @@ async function generateGraph(directory: string, name: string) {
|
|||||||
/window.expandedTaskInputsResponse = (.*?);/
|
/window.expandedTaskInputsResponse = (.*?);/
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sourceMapsResponse = environmentJs.match(
|
||||||
|
/window.sourceMapsResponse = (.*?);/
|
||||||
|
);
|
||||||
|
|
||||||
ensureDirSync(
|
ensureDirSync(
|
||||||
join(__dirname, '../graph/client/src/assets/generated-project-graphs/')
|
join(__dirname, '../graph/client/src/assets/generated-project-graphs/')
|
||||||
);
|
);
|
||||||
@ -45,6 +49,9 @@ async function generateGraph(directory: string, name: string) {
|
|||||||
ensureDirSync(
|
ensureDirSync(
|
||||||
join(__dirname, '../graph/client/src/assets/generated-task-inputs/')
|
join(__dirname, '../graph/client/src/assets/generated-task-inputs/')
|
||||||
);
|
);
|
||||||
|
ensureDirSync(
|
||||||
|
join(__dirname, '../graph/client/src/assets/generated-source-maps/')
|
||||||
|
);
|
||||||
|
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
join(
|
join(
|
||||||
@ -72,6 +79,15 @@ async function generateGraph(directory: string, name: string) {
|
|||||||
),
|
),
|
||||||
expandedTaskInputsReponse[1]
|
expandedTaskInputsReponse[1]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
writeFileSync(
|
||||||
|
join(
|
||||||
|
__dirname,
|
||||||
|
'../graph/client/src/assets/generated-source-maps/',
|
||||||
|
`${name}.json`
|
||||||
|
),
|
||||||
|
sourceMapsResponse[1]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
"@nx/expo": ["packages/expo"],
|
"@nx/expo": ["packages/expo"],
|
||||||
"@nx/expo/*": ["packages/expo/*"],
|
"@nx/expo/*": ["packages/expo/*"],
|
||||||
"@nx/express": ["packages/express"],
|
"@nx/express": ["packages/express"],
|
||||||
|
"@nx/graph/project-details": ["graph/project-details/src/index.ts"],
|
||||||
"@nx/graph/ui-components": ["graph/ui-components/src/index.ts"],
|
"@nx/graph/ui-components": ["graph/ui-components/src/index.ts"],
|
||||||
"@nx/graph/ui-graph": ["graph/ui-graph/src/index.ts"],
|
"@nx/graph/ui-graph": ["graph/ui-graph/src/index.ts"],
|
||||||
"@nx/graph/ui-tooltips": ["graph/ui-tooltips/src/index.ts"],
|
"@nx/graph/ui-tooltips": ["graph/ui-tooltips/src/index.ts"],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user