Skip to content

Commit 43fe11a

Browse files
authored
feat(monorepo): add pnpmWorkspace support for package resolution (#104)
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 26a0956 commit 43fe11a

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)