Skip to main content
Glama
nrwl

Nx MCP Server

Official
by nrwl
project-folder-tree.test.ts6.92 kB
import { join } from 'path'; import { NxlsWrapper } from '../nxls-wrapper'; import { defaultVersion, e2eCwd, newWorkspace, simpleReactWorkspaceOptions, uniq, waitFor, } from '@nx-console/shared-e2e-utils'; import { NxProjectFolderTreeRequest, NxWorkspaceRefreshNotification, } from '@nx-console/language-server-types'; import { TreeMap, TreeNode } from '@nx-console/shared-types'; import { mkdirSync, writeFileSync } from 'fs'; let nxlsWrapper: NxlsWrapper; const workspaceName = uniq('workspace'); describe('project folder tree', () => { beforeAll(async () => { newWorkspace({ name: workspaceName, options: simpleReactWorkspaceOptions, version: defaultVersion, }); nxlsWrapper = new NxlsWrapper(); await nxlsWrapper.startNxls(join(e2eCwd, workspaceName)); nxlsWrapper.setVerbose(true); }); it('should contain base projects with correct information', async () => { const projectFolderTree = await getProjectFolderTree(); expect([...projectFolderTree.treeMap.keys()]).toEqual(['e2e', '.']); expect(projectFolderTree.roots.length).toEqual(1); expect(projectFolderTree.roots[0].dir).toEqual('.'); expect(projectFolderTree.roots[0].projectName).toEqual(workspaceName); }); it('should contain projects & folder nodes for project in subfolder', async () => { await waitFor(11000); const projectFolder = join(e2eCwd, workspaceName, 'subfolder', 'project'); mkdirSync(projectFolder, { recursive: true }); writeFileSync(join(projectFolder, 'project.json'), '{ "name": "project" }'); await nxlsWrapper.waitForNotification( NxWorkspaceRefreshNotification.method, ); const projectFolderTree = await getProjectFolderTree(); expect(projectFolderTree.treeMap.size).toEqual(4); const subfolderNode = projectFolderTree.treeMap.get('subfolder'); expect(subfolderNode).toBeDefined(); expect(subfolderNode?.projectConfiguration).toBeUndefined(); expect(subfolderNode?.projectName).toBeUndefined(); expect(subfolderNode?.dir).toEqual('subfolder'); expect(subfolderNode?.children.length).toEqual(1); expect(subfolderNode?.children[0]).toEqual('subfolder/project'); const subfolderProjectNode = projectFolderTree.treeMap.get('subfolder/project'); expect(subfolderProjectNode).toBeDefined(); expect(subfolderProjectNode?.projectName).toEqual('project'); expect(subfolderProjectNode?.projectConfiguration).toBeDefined(); expect(subfolderProjectNode?.dir).toEqual('subfolder/project'); expect(subfolderProjectNode?.children.length).toEqual(0); // other properties unchanged expect(projectFolderTree.treeMap.get('e2e')).toBeDefined(); expect(projectFolderTree.treeMap.get('.')).toBeDefined(); expect(projectFolderTree.roots.length).toEqual(1); expect(projectFolderTree.roots[0].dir).toEqual('.'); }); it('should contain projects & folder info for nested projects', async () => { await waitFor(11000); const nestedProjectFolder = join( e2eCwd, workspaceName, 'subfolder', 'project', 'nested', ); mkdirSync(nestedProjectFolder, { recursive: true }); writeFileSync( join(nestedProjectFolder, 'project.json'), '{ "name": "nested" }', ); await nxlsWrapper.waitForNotification( NxWorkspaceRefreshNotification.method, ); const projectFolderTree = await getProjectFolderTree(); expect(projectFolderTree.treeMap.size).toEqual(5); const subfolderProjectNode = projectFolderTree.treeMap.get('subfolder/project'); expect(subfolderProjectNode).toBeDefined(); expect(subfolderProjectNode?.projectName).toEqual('project'); expect(subfolderProjectNode?.projectConfiguration).toBeDefined(); expect(subfolderProjectNode?.dir).toEqual('subfolder/project'); expect(subfolderProjectNode?.children.length).toEqual(1); expect(subfolderProjectNode?.children[0]).toEqual( 'subfolder/project/nested', ); const subfolderNestedProjectNode = projectFolderTree.treeMap.get( 'subfolder/project/nested', ); expect(subfolderNestedProjectNode).toBeDefined(); expect(subfolderNestedProjectNode?.projectName).toEqual('nested'); expect(subfolderNestedProjectNode?.projectConfiguration).toBeDefined(); expect(subfolderNestedProjectNode?.dir).toEqual('subfolder/project/nested'); expect(subfolderNestedProjectNode?.children.length).toEqual(0); // other properties unchanged expect(projectFolderTree.treeMap.get('e2e')).toBeDefined(); expect(projectFolderTree.treeMap.get('.')).toBeDefined(); expect(projectFolderTree.treeMap.get('subfolder')).toBeDefined(); }); it('should contain projects & folder info for deeply nested projects', async () => { await waitFor(11000); const deeplyNestedProjectFolder = join( e2eCwd, workspaceName, 'subfolder', 'project', 'subsubfolder', 'deeplynested', ); mkdirSync(deeplyNestedProjectFolder, { recursive: true }); writeFileSync( join(deeplyNestedProjectFolder, 'project.json'), '{ "name": "deeplynested" }', ); await nxlsWrapper.waitForNotification( NxWorkspaceRefreshNotification.method, ); const projectFolderTree = await getProjectFolderTree(); expect(projectFolderTree.treeMap.size).toEqual(7); expect( projectFolderTree.treeMap.get('subfolder/project')?.children, ).toEqual(['subfolder/project/subsubfolder', 'subfolder/project/nested']); const subsubfolderNode = projectFolderTree.treeMap.get( 'subfolder/project/subsubfolder', ); expect(subsubfolderNode?.children).toEqual([ 'subfolder/project/subsubfolder/deeplynested', ]); expect(subsubfolderNode?.projectName).toBeUndefined(); expect(subsubfolderNode?.projectConfiguration).toBeUndefined(); const deeplyNested = projectFolderTree.treeMap.get( 'subfolder/project/subsubfolder/deeplynested', ); expect(deeplyNested).toBeDefined(); expect(deeplyNested?.projectName).toEqual('deeplynested'); expect(deeplyNested?.projectConfiguration).toBeDefined(); expect(deeplyNested?.dir).toEqual( 'subfolder/project/subsubfolder/deeplynested', ); expect(deeplyNested?.children.length).toEqual(0); }); afterAll(async () => { return await nxlsWrapper.stopNxls(); }); }); // both vscode & intellij do this mapping to reconstruct a map from the array of nodes async function getProjectFolderTree(): Promise<{ treeMap: TreeMap; roots: TreeNode[]; }> { const res = ( await nxlsWrapper.sendRequest({ ...NxProjectFolderTreeRequest, params: {}, }) ).result as { serializedTreeMap: { dir: string; node: TreeNode }[]; roots: TreeNode[]; }; return { treeMap: new Map(res.serializedTreeMap.map((n) => [n.dir, n.node])), roots: res.roots, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nrwl/nx-console'

If you have feedback or need assistance with the MCP directory API, please join our Discord server