From a7cb477e9b44058ee67c0fc8b3a67fa6026b27bb Mon Sep 17 00:00:00 2001 From: "anup.aglawe" Date: Tue, 14 Oct 2025 23:26:24 +0530 Subject: [PATCH] feat(monorepo): add pnpmWorkspace support for package resolution Add support for pnpmWorkspace configuration in Eden monorepo, which takes precedence over existing workspaces and packages formats Include tests for pnpmWorkspace functionality and priority handling --- ts-parser/src/utils/monorepo.ts | 40 ++++++-- ts-parser/src/utils/test/monorepo.test.ts | 107 ++++++++++++++++++++++ 2 files changed, 138 insertions(+), 9 deletions(-) diff --git a/ts-parser/src/utils/monorepo.ts b/ts-parser/src/utils/monorepo.ts index 25daa086..4971312d 100644 --- a/ts-parser/src/utils/monorepo.ts +++ b/ts-parser/src/utils/monorepo.ts @@ -1,6 +1,15 @@ import * as fs from 'fs'; import * as path from 'path'; +/** + * Interface for Eden monorepo pnpmWorkspace configuration + * Available when emo version >= 3.6.0 + */ +export interface PnpmWorkspaceConfig { + // Workspace packages configuration (same as workspaces) + packages?: string[]; +} + /** * Interface for Eden monorepo configuration * Supports both legacy packages format and new workspaces format @@ -40,6 +49,8 @@ export interface EdenMonorepoConfig { }>; // New workspaces format (supports glob patterns) workspaces?: string[]; + // This has higher priority than packages and workspaces + pnpmWorkspace?: PnpmWorkspaceConfig; } /** @@ -117,11 +128,28 @@ export class MonorepoUtils { /** * Get packages from Eden monorepo configuration - * Supports both packages array and workspaces array formats + * Supports packages array, workspaces array, and pnpmWorkspace formats + * pnpmWorkspace has the highest priority (emo >= 3.6.0) */ static getEdenPackages(rootPath: string, config: EdenMonorepoConfig): MonorepoPackage[] { const packages: MonorepoPackage[] = []; + if (config.pnpmWorkspace && config.pnpmWorkspace.packages && config.pnpmWorkspace.packages.length > 0) { + for (const workspace of config.pnpmWorkspace.packages) { + const workspacePackages = this.expandWorkspacePattern(rootPath, workspace); + packages.push(...workspacePackages); + } + return packages; // Return early if pnpmWorkspace is configured + } + + // Handle new workspaces array format + if (config.workspaces && config.workspaces.length > 0) { + for (const workspace of config.workspaces) { + const workspacePackages = this.expandWorkspacePattern(rootPath, workspace); + packages.push(...workspacePackages); + } + } + // Handle legacy packages array format if (config.packages && config.packages.length > 0) { for (const pkg of config.packages) { @@ -154,14 +182,6 @@ export class MonorepoUtils { } } - // Handle new workspaces array format - if (config.workspaces && config.workspaces.length > 0) { - for (const workspace of config.workspaces) { - const workspacePackages = this.expandWorkspacePattern(rootPath, workspace); - packages.push(...workspacePackages); - } - } - return packages; } @@ -327,4 +347,6 @@ export class MonorepoUtils { return null; } + + } \ No newline at end of file diff --git a/ts-parser/src/utils/test/monorepo.test.ts b/ts-parser/src/utils/test/monorepo.test.ts index bbb1ad66..83205d06 100644 --- a/ts-parser/src/utils/test/monorepo.test.ts +++ b/ts-parser/src/utils/test/monorepo.test.ts @@ -710,6 +710,113 @@ describe('MonorepoUtils', () => { }); }); + describe('pnpmWorkspace support', () => { + describe('getEdenPackages with pnpmWorkspace', () => { + it('should parse pnpmWorkspace configuration and extract packages', () => { + const testProject = createPnpmWorkspaceProject([ + { + path: 'packages/core', + packageJson: { + name: '@test/core', + version: '1.0.0', + dependencies: { + 'react': '^18.0.0', + 'lodash': '^4.17.21' + } + } + }, + { + path: 'packages/utils', + packageJson: { + name: '@test/utils', + version: '1.0.0', + dependencies: { + 'typescript': '^5.0.0' + } + } + } + ], ['packages/*']); + + const config: EdenMonorepoConfig = { + pnpmWorkspace: { + packages: ['packages/*'] + } + }; + + const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config); + + expect(result).toHaveLength(2); + + const corePackage = result.find(pkg => pkg.name === '@test/core'); + expect(corePackage).toBeDefined(); + expect(corePackage?.path).toBe('packages/core'); + + const utilsPackage = result.find(pkg => pkg.name === '@test/utils'); + expect(utilsPackage).toBeDefined(); + expect(utilsPackage?.path).toBe('packages/utils'); + + testProject.cleanup(); + }); + + it('should prioritize pnpmWorkspace over workspaces and packages', () => { + const testProject = createPnpmWorkspaceProject([ + { + path: 'packages/core', + packageJson: { + name: '@test/core', + version: '1.0.0' + } + } + ], ['packages/*']); + + const config: EdenMonorepoConfig = { + pnpmWorkspace: { + packages: ['packages/*'] + }, + workspaces: ['apps/*'], + packages: [ + { path: 'legacy/*', shouldPublish: true } + ] + }; + + const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config); + + expect(result).toHaveLength(1); + expect(result[0].name).toBe('@test/core'); + expect(result[0].path).toBe('packages/core'); + + testProject.cleanup(); + }); + + it('should handle pnpmWorkspace without catalog configuration', () => { + const testProject = createPnpmWorkspaceProject([ + { + path: 'apps/web', + packageJson: { + name: '@test/web', + version: '1.0.0' + } + } + ], ['apps/*']); + + const config: EdenMonorepoConfig = { + pnpmWorkspace: { + packages: ['apps/*'] + } + }; + + const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config); + + expect(result).toHaveLength(1); + expect(result[0].name).toBe('@test/web'); + + testProject.cleanup(); + }); + }); + + + }); + describe('findPackageForPath', () => { const packages: MonorepoPackage[] = [ {