Skip to content

Commit a7cb477

Browse files
committed
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
1 parent 7b4eb5b commit a7cb477

2 files changed

Lines changed: 138 additions & 9 deletions

File tree

ts-parser/src/utils/monorepo.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import * as fs from 'fs';
22
import * as path from 'path';
33

4+
/**
5+
* Interface for Eden monorepo pnpmWorkspace configuration
6+
* Available when emo version >= 3.6.0
7+
*/
8+
export interface PnpmWorkspaceConfig {
9+
// Workspace packages configuration (same as workspaces)
10+
packages?: string[];
11+
}
12+
413
/**
514
* Interface for Eden monorepo configuration
615
* Supports both legacy packages format and new workspaces format
@@ -40,6 +49,8 @@ export interface EdenMonorepoConfig {
4049
}>;
4150
// New workspaces format (supports glob patterns)
4251
workspaces?: string[];
52+
// This has higher priority than packages and workspaces
53+
pnpmWorkspace?: PnpmWorkspaceConfig;
4354
}
4455

4556
/**
@@ -117,11 +128,28 @@ export class MonorepoUtils {
117128

118129
/**
119130
* Get packages from Eden monorepo configuration
120-
* Supports both packages array and workspaces array formats
131+
* Supports packages array, workspaces array, and pnpmWorkspace formats
132+
* pnpmWorkspace has the highest priority (emo >= 3.6.0)
121133
*/
122134
static getEdenPackages(rootPath: string, config: EdenMonorepoConfig): MonorepoPackage[] {
123135
const packages: MonorepoPackage[] = [];
124136

137+
if (config.pnpmWorkspace && config.pnpmWorkspace.packages && config.pnpmWorkspace.packages.length > 0) {
138+
for (const workspace of config.pnpmWorkspace.packages) {
139+
const workspacePackages = this.expandWorkspacePattern(rootPath, workspace);
140+
packages.push(...workspacePackages);
141+
}
142+
return packages; // Return early if pnpmWorkspace is configured
143+
}
144+
145+
// Handle new workspaces array format
146+
if (config.workspaces && config.workspaces.length > 0) {
147+
for (const workspace of config.workspaces) {
148+
const workspacePackages = this.expandWorkspacePattern(rootPath, workspace);
149+
packages.push(...workspacePackages);
150+
}
151+
}
152+
125153
// Handle legacy packages array format
126154
if (config.packages && config.packages.length > 0) {
127155
for (const pkg of config.packages) {
@@ -154,14 +182,6 @@ export class MonorepoUtils {
154182
}
155183
}
156184

157-
// Handle new workspaces array format
158-
if (config.workspaces && config.workspaces.length > 0) {
159-
for (const workspace of config.workspaces) {
160-
const workspacePackages = this.expandWorkspacePattern(rootPath, workspace);
161-
packages.push(...workspacePackages);
162-
}
163-
}
164-
165185
return packages;
166186
}
167187

@@ -327,4 +347,6 @@ export class MonorepoUtils {
327347

328348
return null;
329349
}
350+
351+
330352
}

ts-parser/src/utils/test/monorepo.test.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,113 @@ describe('MonorepoUtils', () => {
710710
});
711711
});
712712

713+
describe('pnpmWorkspace support', () => {
714+
describe('getEdenPackages with pnpmWorkspace', () => {
715+
it('should parse pnpmWorkspace configuration and extract packages', () => {
716+
const testProject = createPnpmWorkspaceProject([
717+
{
718+
path: 'packages/core',
719+
packageJson: {
720+
name: '@test/core',
721+
version: '1.0.0',
722+
dependencies: {
723+
'react': '^18.0.0',
724+
'lodash': '^4.17.21'
725+
}
726+
}
727+
},
728+
{
729+
path: 'packages/utils',
730+
packageJson: {
731+
name: '@test/utils',
732+
version: '1.0.0',
733+
dependencies: {
734+
'typescript': '^5.0.0'
735+
}
736+
}
737+
}
738+
], ['packages/*']);
739+
740+
const config: EdenMonorepoConfig = {
741+
pnpmWorkspace: {
742+
packages: ['packages/*']
743+
}
744+
};
745+
746+
const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config);
747+
748+
expect(result).toHaveLength(2);
749+
750+
const corePackage = result.find(pkg => pkg.name === '@test/core');
751+
expect(corePackage).toBeDefined();
752+
expect(corePackage?.path).toBe('packages/core');
753+
754+
const utilsPackage = result.find(pkg => pkg.name === '@test/utils');
755+
expect(utilsPackage).toBeDefined();
756+
expect(utilsPackage?.path).toBe('packages/utils');
757+
758+
testProject.cleanup();
759+
});
760+
761+
it('should prioritize pnpmWorkspace over workspaces and packages', () => {
762+
const testProject = createPnpmWorkspaceProject([
763+
{
764+
path: 'packages/core',
765+
packageJson: {
766+
name: '@test/core',
767+
version: '1.0.0'
768+
}
769+
}
770+
], ['packages/*']);
771+
772+
const config: EdenMonorepoConfig = {
773+
pnpmWorkspace: {
774+
packages: ['packages/*']
775+
},
776+
workspaces: ['apps/*'],
777+
packages: [
778+
{ path: 'legacy/*', shouldPublish: true }
779+
]
780+
};
781+
782+
const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config);
783+
784+
expect(result).toHaveLength(1);
785+
expect(result[0].name).toBe('@test/core');
786+
expect(result[0].path).toBe('packages/core');
787+
788+
testProject.cleanup();
789+
});
790+
791+
it('should handle pnpmWorkspace without catalog configuration', () => {
792+
const testProject = createPnpmWorkspaceProject([
793+
{
794+
path: 'apps/web',
795+
packageJson: {
796+
name: '@test/web',
797+
version: '1.0.0'
798+
}
799+
}
800+
], ['apps/*']);
801+
802+
const config: EdenMonorepoConfig = {
803+
pnpmWorkspace: {
804+
packages: ['apps/*']
805+
}
806+
};
807+
808+
const result = MonorepoUtils.getEdenPackages(testProject.rootDir, config);
809+
810+
expect(result).toHaveLength(1);
811+
expect(result[0].name).toBe('@test/web');
812+
813+
testProject.cleanup();
814+
});
815+
});
816+
817+
818+
});
819+
713820
describe('findPackageForPath', () => {
714821
const packages: MonorepoPackage[] = [
715822
{

0 commit comments

Comments
 (0)