Skip to content

Commit 3382106

Browse files
jaysooFrozenPandaz
authored andcommitted
fix(core): prevent undefined importer crash in pnpm lockfile parsing (#33223)
When stringifying a pnpm v9 lockfile with workspace packages, Nx crashes with: "Cannot destructure property 'specifiers' of 'projectSnapshot' as it is undefined." This occurs when: - The lockfile has a root importer with `link:` references to workspace packages - But the lockfile is missing the workspace package importer entries - The code tries to access `importers[importerPath]` which returns undefined - This undefined value gets added to the output lockfile - During serialization, it crashes when trying to destructure undefined Workspace packages with missing importers are now silently skipped during lockfile serialization. This prevents the crash and allows Nx to continue operating with out-of-sync lockfiles. The fix adds a null check before adding workspace dependency importers to the output lockfile. Closes NXC-3244 (cherry picked from commit 514005a)
1 parent 65fa9b1 commit 3382106

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

packages/nx/src/plugins/js/lock-file/pnpm-parser.spec.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,4 +1685,84 @@ describe('pnpm LockFile utility', () => {
16851685
expect(result).toEqual(expectedPrunedLockFile);
16861686
});
16871687
});
1688+
1689+
describe('missing workspace importer', () => {
1690+
beforeEach(() => {
1691+
const fileSys = {
1692+
'node_modules/.modules.yaml': `hoistedDependencies: {}`,
1693+
'node_modules/lodash/package.json': '{"version": "4.17.21"}',
1694+
};
1695+
vol.fromJSON(fileSys, '/root');
1696+
});
1697+
1698+
it('should throw clear error when workspace package importer is missing', () => {
1699+
// v9.0 lockfile
1700+
// Only has root importer (.)
1701+
// Root importer references a workspace package with link:
1702+
// But the workspace package's importer is MISSING
1703+
const lockFile = `lockfileVersion: '9.0'
1704+
1705+
importers:
1706+
1707+
.:
1708+
dependencies:
1709+
lodash:
1710+
specifier: ^4.17.21
1711+
version: 4.17.21
1712+
my-workspace-lib:
1713+
specifier: workspace:*
1714+
version: link:packages/my-workspace-lib
1715+
1716+
packages:
1717+
1718+
1719+
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
1720+
1721+
snapshots:
1722+
1723+
1724+
1725+
const packageJson = {
1726+
name: 'test-app',
1727+
version: '1.0.0',
1728+
dependencies: {
1729+
lodash: '^4.17.21',
1730+
'my-workspace-lib': 'workspace:*',
1731+
},
1732+
};
1733+
1734+
const graph: ProjectGraph = {
1735+
nodes: {
1736+
'my-workspace-lib': {
1737+
name: 'my-workspace-lib',
1738+
type: 'lib',
1739+
data: {
1740+
root: 'packages/my-workspace-lib',
1741+
metadata: {
1742+
js: {
1743+
packageName: 'my-workspace-lib',
1744+
},
1745+
},
1746+
},
1747+
},
1748+
},
1749+
dependencies: {},
1750+
externalNodes: {
1751+
'npm:lodash': {
1752+
type: 'npm',
1753+
name: 'npm:lodash',
1754+
data: {
1755+
version: '4.17.21',
1756+
packageName: 'lodash',
1757+
hash: 'sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==',
1758+
},
1759+
},
1760+
},
1761+
};
1762+
1763+
expect(() =>
1764+
stringifyPnpmLockfile(graph, lockFile, packageJson, '/virtual')
1765+
).not.toThrow();
1766+
});
1767+
});
16881768
});

packages/nx/src/plugins/js/lock-file/pnpm-parser.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,10 @@ export function stringifyPnpmLockfile(
428428
const workspaceDependencyImporters: Record<string, ProjectSnapshot> = {};
429429
for (const [packageName, importerPath] of Object.entries(requiredImporters)) {
430430
const baseImporter = importers[importerPath];
431-
workspaceDependencyImporters[`workspace_modules/${packageName}`] =
432-
baseImporter;
431+
if (baseImporter) {
432+
workspaceDependencyImporters[`workspace_modules/${packageName}`] =
433+
baseImporter;
434+
}
433435
}
434436

435437
const output: Lockfile = {

0 commit comments

Comments
 (0)