@rushstack/lockfile-explorer 1.7.41 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CHANGELOG.json +55 -0
  2. package/CHANGELOG.md +21 -1
  3. package/build/lfx-shared/IAppContext.d.ts +32 -0
  4. package/build/lfx-shared/IAppContext.js +5 -0
  5. package/build/lfx-shared/IAppContext.js.map +1 -0
  6. package/build/lfx-shared/IJsonLfxGraph.d.ts +51 -0
  7. package/build/lfx-shared/IJsonLfxGraph.js +19 -0
  8. package/build/lfx-shared/IJsonLfxGraph.js.map +1 -0
  9. package/build/lfx-shared/IJsonLfxWorkspace.d.ts +59 -0
  10. package/build/lfx-shared/IJsonLfxWorkspace.js +5 -0
  11. package/build/lfx-shared/IJsonLfxWorkspace.js.map +1 -0
  12. package/build/lfx-shared/LfxGraph.d.ts +96 -0
  13. package/build/lfx-shared/LfxGraph.js +67 -0
  14. package/build/lfx-shared/LfxGraph.js.map +1 -0
  15. package/build/lfx-shared/index.d.ts +6 -0
  16. package/build/lfx-shared/index.js +12 -0
  17. package/build/lfx-shared/index.js.map +1 -0
  18. package/build/lfx-shared/lfxGraphSerializer.d.ts +5 -0
  19. package/build/lfx-shared/lfxGraphSerializer.js +121 -0
  20. package/build/lfx-shared/lfxGraphSerializer.js.map +1 -0
  21. package/dist/531.0e5a24ca1399529aa975.js +2 -0
  22. package/dist/{964.4bbaf68a6f1467df6770.js.LICENSE.txt → 531.0e5a24ca1399529aa975.js.LICENSE.txt} +13 -0
  23. package/dist/app.22259b754540a899e03d.js +1 -0
  24. package/dist/index.html +1 -1
  25. package/lib/cli/explorer/ExplorerCommandLineParser.d.ts.map +1 -1
  26. package/lib/cli/explorer/ExplorerCommandLineParser.js +61 -22
  27. package/lib/cli/explorer/ExplorerCommandLineParser.js.map +1 -1
  28. package/lib/cli/lint/actions/CheckAction.d.ts.map +1 -1
  29. package/lib/cli/lint/actions/CheckAction.js.map +1 -1
  30. package/lib/graph/IPnpmfileModule.d.ts +15 -0
  31. package/lib/graph/IPnpmfileModule.d.ts.map +1 -0
  32. package/lib/graph/IPnpmfileModule.js +5 -0
  33. package/lib/graph/IPnpmfileModule.js.map +1 -0
  34. package/lib/graph/PnpmfileRunner.d.ts +19 -0
  35. package/lib/graph/PnpmfileRunner.d.ts.map +1 -0
  36. package/lib/graph/PnpmfileRunner.js +123 -0
  37. package/lib/graph/PnpmfileRunner.js.map +1 -0
  38. package/lib/graph/lfxGraphLoader.d.ts +9 -0
  39. package/lib/graph/lfxGraphLoader.d.ts.map +1 -0
  40. package/lib/graph/lfxGraphLoader.js +408 -0
  41. package/lib/graph/lfxGraphLoader.js.map +1 -0
  42. package/lib/graph/lockfilePath.d.ts +37 -0
  43. package/lib/graph/lockfilePath.d.ts.map +1 -0
  44. package/lib/graph/lockfilePath.js +123 -0
  45. package/lib/graph/lockfilePath.js.map +1 -0
  46. package/lib/graph/pnpmfileRunnerWorkerThread.d.ts +23 -0
  47. package/lib/graph/pnpmfileRunnerWorkerThread.d.ts.map +1 -0
  48. package/lib/graph/pnpmfileRunnerWorkerThread.js +94 -0
  49. package/lib/graph/pnpmfileRunnerWorkerThread.js.map +1 -0
  50. package/lib/state/index.d.ts +4 -22
  51. package/lib/state/index.d.ts.map +1 -1
  52. package/lib/state/index.js +0 -6
  53. package/lib/state/index.js.map +1 -1
  54. package/lib/utils/init.d.ts +2 -2
  55. package/lib/utils/init.d.ts.map +1 -1
  56. package/lib/utils/init.js +73 -29
  57. package/lib/utils/init.js.map +1 -1
  58. package/lib/utils/shrinkwrap.d.ts.map +1 -1
  59. package/lib/utils/shrinkwrap.js.map +1 -1
  60. package/package.json +14 -12
  61. package/dist/964.4bbaf68a6f1467df6770.js +0 -2
  62. package/dist/app.acf2b912c3f02793012c.js +0 -1
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.PnpmfileRunner = void 0;
39
+ const node_worker_threads_1 = require("node:worker_threads");
40
+ const path = __importStar(require("node:path"));
41
+ /**
42
+ * Evals `.pnpmfile.cjs` in an isolated thread, so `transformPackageAsync()` can be used to rewrite
43
+ * package.json files. Calling `disposeAsync()` will free the loaded modules.
44
+ */
45
+ class PnpmfileRunner {
46
+ constructor(pnpmfilePath) {
47
+ this._nextId = 1000;
48
+ this._promisesById = new Map();
49
+ this._disposed = false;
50
+ this.logger = undefined;
51
+ this._worker = new node_worker_threads_1.Worker(path.join(`${__dirname}/pnpmfileRunnerWorkerThread.js`), {
52
+ workerData: { pnpmfilePath }
53
+ });
54
+ this._worker.on('message', (message) => {
55
+ const id = message.id;
56
+ const promise = this._promisesById.get(id);
57
+ if (!promise) {
58
+ return;
59
+ }
60
+ if (message.kind === 'return') {
61
+ this._promisesById.delete(id);
62
+ // TODO: Validate the user's readPackage() return value
63
+ const result = message.result;
64
+ promise.resolve(result);
65
+ }
66
+ else if (message.kind === 'log') {
67
+ // No this._promisesById.delete(id) for this case
68
+ if (this.logger) {
69
+ this.logger(message.log);
70
+ }
71
+ else {
72
+ console.log('.pnpmfile.cjs: ' + message.log);
73
+ }
74
+ }
75
+ else {
76
+ this._promisesById.delete(id);
77
+ promise.reject(new Error(message.error || 'An unknown error occurred'));
78
+ }
79
+ });
80
+ this._worker.on('error', (err) => {
81
+ for (const promise of this._promisesById.values()) {
82
+ promise.reject(err);
83
+ }
84
+ this._promisesById.clear();
85
+ });
86
+ this._worker.on('exit', (code) => {
87
+ if (!this._disposed) {
88
+ const error = new Error(`PnpmfileRunner worker thread terminated unexpectedly with exit code ${code}`);
89
+ console.error(error);
90
+ for (const promise of this._promisesById.values()) {
91
+ promise.reject(error);
92
+ }
93
+ this._promisesById.clear();
94
+ }
95
+ });
96
+ }
97
+ /**
98
+ * Invokes the readPackage() hook from .pnpmfile.cjs
99
+ */
100
+ transformPackageAsync(packageJson, packageJsonFullPath) {
101
+ if (this._disposed) {
102
+ return Promise.reject(new Error('The operation failed because PnpmfileRunner has been disposed'));
103
+ }
104
+ const id = this._nextId++;
105
+ return new Promise((resolve, reject) => {
106
+ this._promisesById.set(id, { resolve, reject });
107
+ this._worker.postMessage({ id, packageJson, packageJsonFullPath });
108
+ });
109
+ }
110
+ async disposeAsync() {
111
+ if (this._disposed) {
112
+ return;
113
+ }
114
+ for (const pending of this._promisesById.values()) {
115
+ pending.reject(new Error('Aborted because PnpmfileRunner was disposed'));
116
+ }
117
+ this._promisesById.clear();
118
+ this._disposed = true;
119
+ await this._worker.terminate();
120
+ }
121
+ }
122
+ exports.PnpmfileRunner = PnpmfileRunner;
123
+ //# sourceMappingURL=PnpmfileRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PnpmfileRunner.js","sourceRoot":"","sources":["../../src/graph/PnpmfileRunner.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { Worker } from 'node:worker_threads';\nimport * as path from 'node:path';\nimport type { IPackageJson } from '@rushstack/node-core-library';\n\nimport type { IRequestMessage, ResponseMessage } from './pnpmfileRunnerWorkerThread';\n\ninterface IPromise {\n resolve: (r: IPackageJson) => void;\n reject: (e: Error) => void;\n}\n\n/**\n * Evals `.pnpmfile.cjs` in an isolated thread, so `transformPackageAsync()` can be used to rewrite\n * package.json files. Calling `disposeAsync()` will free the loaded modules.\n */\nexport class PnpmfileRunner {\n private _worker: Worker;\n private _nextId: number = 1000;\n private _promisesById: Map<number, IPromise> = new Map();\n private _disposed: boolean = false;\n\n public logger: ((message: string) => void) | undefined = undefined;\n\n public constructor(pnpmfilePath: string) {\n this._worker = new Worker(path.join(`${__dirname}/pnpmfileRunnerWorkerThread.js`), {\n workerData: { pnpmfilePath }\n });\n\n this._worker.on('message', (message: ResponseMessage) => {\n const id: number = message.id;\n const promise: IPromise | undefined = this._promisesById.get(id);\n if (!promise) {\n return;\n }\n\n if (message.kind === 'return') {\n this._promisesById.delete(id);\n // TODO: Validate the user's readPackage() return value\n const result: IPackageJson = message.result as IPackageJson;\n promise.resolve(result);\n } else if (message.kind === 'log') {\n // No this._promisesById.delete(id) for this case\n if (this.logger) {\n this.logger(message.log);\n } else {\n console.log('.pnpmfile.cjs: ' + message.log);\n }\n } else {\n this._promisesById.delete(id);\n promise.reject(new Error(message.error || 'An unknown error occurred'));\n }\n });\n\n this._worker.on('error', (err) => {\n for (const promise of this._promisesById.values()) {\n promise.reject(err);\n }\n this._promisesById.clear();\n });\n\n this._worker.on('exit', (code) => {\n if (!this._disposed) {\n const error: Error = new Error(\n `PnpmfileRunner worker thread terminated unexpectedly with exit code ${code}`\n );\n console.error(error);\n for (const promise of this._promisesById.values()) {\n promise.reject(error);\n }\n this._promisesById.clear();\n }\n });\n }\n\n /**\n * Invokes the readPackage() hook from .pnpmfile.cjs\n */\n public transformPackageAsync(\n packageJson: IPackageJson,\n packageJsonFullPath: string\n ): Promise<IPackageJson> {\n if (this._disposed) {\n return Promise.reject(new Error('The operation failed because PnpmfileRunner has been disposed'));\n }\n\n const id: number = this._nextId++;\n return new Promise((resolve, reject) => {\n this._promisesById.set(id, { resolve, reject });\n this._worker.postMessage({ id, packageJson, packageJsonFullPath } satisfies IRequestMessage);\n });\n }\n\n public async disposeAsync(): Promise<void> {\n if (this._disposed) {\n return;\n }\n for (const pending of this._promisesById.values()) {\n pending.reject(new Error('Aborted because PnpmfileRunner was disposed'));\n }\n this._promisesById.clear();\n this._disposed = true;\n await this._worker.terminate();\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { LfxGraph, type IJsonLfxWorkspace } from '../../build/lfx-shared';
2
+ /**
3
+ * Parse through the lockfile and create all the corresponding LockfileEntries and LockfileDependencies
4
+ * to construct the lockfile graph.
5
+ *
6
+ * @returns A list of all the LockfileEntries in the lockfile.
7
+ */
8
+ export declare function generateLockfileGraph(lockfileJson: unknown, workspace: IJsonLfxWorkspace): LfxGraph;
9
+ //# sourceMappingURL=lfxGraphLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lfxGraphLoader.d.ts","sourceRoot":"","sources":["../../src/graph/lfxGraphLoader.ts"],"names":[],"mappings":"AAOA,OAAO,EAGL,QAAQ,EAKR,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAC;AA2VhC;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,GAAG,QAAQ,CAkInG"}
@@ -0,0 +1,408 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.generateLockfileGraph = generateLockfileGraph;
39
+ const node_core_library_1 = require("@rushstack/node-core-library");
40
+ const lfx_shared_1 = require("../../build/lfx-shared");
41
+ const lockfilePath = __importStar(require("./lockfilePath"));
42
+ function createPackageLockfileDependency(options) {
43
+ const { name, version, kind: dependencyType, containingEntry, peerDependenciesMeta, pnpmLockfileVersion } = options;
44
+ const result = {
45
+ name,
46
+ version,
47
+ dependencyType,
48
+ containingEntry,
49
+ entryId: '',
50
+ peerDependencyMeta: {}
51
+ };
52
+ if (version.startsWith('link:')) {
53
+ const relativePath = version.substring('link:'.length);
54
+ if (containingEntry.kind === lfx_shared_1.LfxGraphEntryKind.Project) {
55
+ // TODO: Here we assume it's a "workspace:" link and try to resolve it to another workspace project,
56
+ // but it could also be a link to an arbitrary folder (in which case this entryId will fail to resolve).
57
+ // In the future, we should distinguish these cases.
58
+ const selfRelativePath = lockfilePath.getAbsolute(containingEntry.packageJsonFolderPath, relativePath);
59
+ result.entryId = 'project:' + selfRelativePath.toString();
60
+ }
61
+ else {
62
+ // This could be a link to anywhere on the local computer, so we don't expect it to have a lockfile entry
63
+ result.entryId = '';
64
+ }
65
+ }
66
+ else if (result.version.startsWith('/')) {
67
+ result.entryId = version;
68
+ }
69
+ else if (result.dependencyType === lfx_shared_1.LfxDependencyKind.Peer) {
70
+ result.peerDependencyMeta = {
71
+ name: result.name,
72
+ version: version,
73
+ optional: (peerDependenciesMeta === null || peerDependenciesMeta === void 0 ? void 0 : peerDependenciesMeta[result.name]) ? peerDependenciesMeta[result.name].optional : false
74
+ };
75
+ result.entryId = 'Peer: ' + result.name;
76
+ }
77
+ else {
78
+ // Version 5.4: /@rushstack/m/1.0.0:
79
+ // Version 6.0: /@rushstack/m@1.0.0:
80
+ //
81
+ // Version 5.4: /@rushstack/j/1.0.0_@rushstack+n@2.0.0
82
+ // Version 6.0: /@rushstack/j@1.0.0(@rushstack/n@2.0.0)
83
+ const versionDelimiter = pnpmLockfileVersion === 54 ? '/' : '@';
84
+ result.entryId = '/' + result.name + versionDelimiter + result.version;
85
+ }
86
+ return new lfx_shared_1.LfxGraphDependency(result);
87
+ }
88
+ // v5.4 used this to parse projects ("importers") also
89
+ function parsePackageDependencies(dependencies, lockfileEntry, either, pnpmLockfileVersion, workspace) {
90
+ const node = either;
91
+ if (node.dependencies) {
92
+ for (const [packageName, version] of Object.entries(node.dependencies)) {
93
+ dependencies.push(createPackageLockfileDependency({
94
+ kind: lfx_shared_1.LfxDependencyKind.Regular,
95
+ name: packageName,
96
+ version: version,
97
+ containingEntry: lockfileEntry,
98
+ pnpmLockfileVersion,
99
+ workspace
100
+ }));
101
+ }
102
+ }
103
+ if (node.devDependencies) {
104
+ for (const [packageName, version] of Object.entries(node.devDependencies)) {
105
+ dependencies.push(createPackageLockfileDependency({
106
+ kind: lfx_shared_1.LfxDependencyKind.Dev,
107
+ name: packageName,
108
+ version: version,
109
+ containingEntry: lockfileEntry,
110
+ pnpmLockfileVersion,
111
+ workspace
112
+ }));
113
+ }
114
+ }
115
+ if (node.peerDependencies) {
116
+ for (const [packageName, version] of Object.entries(node.peerDependencies)) {
117
+ dependencies.push(createPackageLockfileDependency({
118
+ kind: lfx_shared_1.LfxDependencyKind.Peer,
119
+ name: packageName,
120
+ version: version,
121
+ containingEntry: lockfileEntry,
122
+ peerDependenciesMeta: node.peerDependenciesMeta,
123
+ pnpmLockfileVersion,
124
+ workspace
125
+ }));
126
+ }
127
+ }
128
+ if (node.transitivePeerDependencies) {
129
+ for (const dep of node.transitivePeerDependencies) {
130
+ lockfileEntry.transitivePeerDependencies.add(dep);
131
+ }
132
+ }
133
+ }
134
+ function parseProjectDependencies60(dependencies, lockfileEntry, snapshot, pnpmLockfileVersion, workspace) {
135
+ if (snapshot.dependencies) {
136
+ for (const [packageName, specifierAndResolution] of Object.entries(snapshot.dependencies)) {
137
+ dependencies.push(createPackageLockfileDependency({
138
+ kind: lfx_shared_1.LfxDependencyKind.Regular,
139
+ name: packageName,
140
+ version: specifierAndResolution.version,
141
+ containingEntry: lockfileEntry,
142
+ pnpmLockfileVersion,
143
+ workspace
144
+ }));
145
+ }
146
+ }
147
+ if (snapshot.devDependencies) {
148
+ for (const [packageName, specifierAndResolution] of Object.entries(snapshot.devDependencies)) {
149
+ dependencies.push(createPackageLockfileDependency({
150
+ kind: lfx_shared_1.LfxDependencyKind.Dev,
151
+ name: packageName,
152
+ version: specifierAndResolution.version,
153
+ containingEntry: lockfileEntry,
154
+ pnpmLockfileVersion,
155
+ workspace
156
+ }));
157
+ }
158
+ }
159
+ }
160
+ function createProjectLockfileEntry(options) {
161
+ const { rawEntryId, duplicates, workspace } = options;
162
+ const result = {
163
+ kind: lfx_shared_1.LfxGraphEntryKind.Project,
164
+ entryId: '',
165
+ rawEntryId: '',
166
+ packageJsonFolderPath: '',
167
+ entryPackageName: '',
168
+ displayText: '',
169
+ entryPackageVersion: '',
170
+ entrySuffix: ''
171
+ };
172
+ result.rawEntryId = rawEntryId;
173
+ // Example: pnpmLockfilePath = 'common/temp/my-subspace/pnpm-lock.yaml'
174
+ // Example: pnpmLockfileFolder = 'common/temp/my-subspace'
175
+ const pnpmLockfileFolder = workspace.pnpmLockfileFolder;
176
+ // Example: rawEntryId = '../../../projects/a'
177
+ // Example: packageJsonFolderPath = 'projects/a'
178
+ result.packageJsonFolderPath = lockfilePath.getAbsolute(pnpmLockfileFolder, rawEntryId);
179
+ result.entryId = 'project:' + result.packageJsonFolderPath;
180
+ const projectFolderName = lockfilePath.getBaseNameOf(rawEntryId);
181
+ if (!(duplicates === null || duplicates === void 0 ? void 0 : duplicates.has(projectFolderName))) {
182
+ // TODO: The actual package.json name might not match its directory name,
183
+ // but we have to load package.json to determine it.
184
+ result.entryPackageName = projectFolderName;
185
+ }
186
+ else {
187
+ result.entryPackageName = `${projectFolderName} (${result.packageJsonFolderPath})`;
188
+ }
189
+ result.displayText = `Project: ${result.entryPackageName}`;
190
+ const lockfileEntry = new lfx_shared_1.LfxGraphEntry(result);
191
+ return lockfileEntry;
192
+ }
193
+ function createPackageLockfileEntry(options) {
194
+ const { rawEntryId, rawYamlData, pnpmLockfileVersion, workspace } = options;
195
+ const result = {
196
+ kind: lfx_shared_1.LfxGraphEntryKind.Package,
197
+ entryId: '',
198
+ rawEntryId: '',
199
+ packageJsonFolderPath: '',
200
+ entryPackageName: '',
201
+ displayText: '',
202
+ entryPackageVersion: '',
203
+ entrySuffix: ''
204
+ };
205
+ result.rawEntryId = rawEntryId;
206
+ // Example: pnpmLockfilePath = 'common/temp/my-subspace/pnpm-lock.yaml'
207
+ // Example: pnpmLockfileFolder = 'common/temp/my-subspace'
208
+ const pnpmLockfileFolder = workspace.pnpmLockfileFolder;
209
+ result.displayText = rawEntryId;
210
+ if (!rawEntryId.startsWith('/')) {
211
+ throw new Error('Expecting leading "/" in path: ' + JSON.stringify(rawEntryId));
212
+ }
213
+ let dotPnpmSubfolder;
214
+ if (pnpmLockfileVersion === 54) {
215
+ const lastSlashIndex = rawEntryId.lastIndexOf('/');
216
+ if (lastSlashIndex < 0) {
217
+ throw new Error('Expecting "/" in path: ' + JSON.stringify(rawEntryId));
218
+ }
219
+ const packageName = rawEntryId.substring(1, lastSlashIndex);
220
+ result.entryPackageName = packageName;
221
+ // /@rushstack/eslint-config/3.0.1_eslint@8.21.0+typescript@4.7.4
222
+ // --> @rushstack/eslint-config 3.0.1 (eslint@8.21.0+typescript@4.7.4)
223
+ const underscoreIndex = rawEntryId.indexOf('_', lastSlashIndex);
224
+ if (underscoreIndex > 0) {
225
+ const version = rawEntryId.substring(lastSlashIndex + 1, underscoreIndex);
226
+ const suffix = rawEntryId.substring(underscoreIndex + 1);
227
+ result.displayText = packageName + ' ' + version + ' (' + suffix + ')';
228
+ result.entryPackageVersion = version;
229
+ result.entrySuffix = suffix;
230
+ }
231
+ else {
232
+ // /@rushstack/eslint-config/3.0.1
233
+ // --> @rushstack/eslint-config 3.0.1
234
+ const version = rawEntryId.substring(lastSlashIndex + 1);
235
+ result.displayText = packageName + ' ' + version;
236
+ result.entryPackageVersion = version;
237
+ }
238
+ // Example: @babel+register@7.17.7_@babel+core@7.17.12
239
+ dotPnpmSubfolder =
240
+ result.entryPackageName.replace('/', '+') +
241
+ '@' +
242
+ result.entryPackageVersion +
243
+ (result.entrySuffix ? `_${result.entrySuffix}` : '');
244
+ }
245
+ else {
246
+ // Example inputs:
247
+ // /@rushstack/eslint-config@3.0.1
248
+ // /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
249
+ let versionAtSignIndex;
250
+ if (rawEntryId.startsWith('/@')) {
251
+ versionAtSignIndex = rawEntryId.indexOf('@', 2);
252
+ }
253
+ else {
254
+ versionAtSignIndex = rawEntryId.indexOf('@', 1);
255
+ }
256
+ const packageName = rawEntryId.substring(1, versionAtSignIndex);
257
+ result.entryPackageName = packageName;
258
+ const leftParenIndex = rawEntryId.indexOf('(', versionAtSignIndex);
259
+ if (leftParenIndex < 0) {
260
+ const version = rawEntryId.substring(versionAtSignIndex + 1);
261
+ result.entryPackageVersion = version;
262
+ // /@rushstack/eslint-config@3.0.1
263
+ // --> @rushstack/eslint-config 3.0.1
264
+ result.displayText = packageName + ' ' + version;
265
+ }
266
+ else {
267
+ const version = rawEntryId.substring(versionAtSignIndex + 1, leftParenIndex);
268
+ result.entryPackageVersion = version;
269
+ // "(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)"
270
+ let suffix = rawEntryId.substring(leftParenIndex);
271
+ // Rewrite to:
272
+ // "@rushstack/m@1.0.0; @rushstack/n@2.0.0"
273
+ suffix = node_core_library_1.Text.replaceAll(suffix, ')(', '; ');
274
+ suffix = node_core_library_1.Text.replaceAll(suffix, '(', '');
275
+ suffix = node_core_library_1.Text.replaceAll(suffix, ')', '');
276
+ result.entrySuffix = suffix;
277
+ // /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
278
+ // --> @rushstack/l 1.0.0 [@rushstack/m@1.0.0; @rushstack/n@2.0.0]
279
+ result.displayText = packageName + ' ' + version + ' [' + suffix + ']';
280
+ }
281
+ // Example: /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
282
+ // --> @rushstack+l@1.0.0_@rushstack+m@1.0.0_@rushstack+n@2.0.0
283
+ // @rushstack/l 1.0.0 (@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
284
+ dotPnpmSubfolder = rawEntryId.substring(1);
285
+ dotPnpmSubfolder = node_core_library_1.Text.replaceAll(dotPnpmSubfolder, '/', '+');
286
+ dotPnpmSubfolder = node_core_library_1.Text.replaceAll(dotPnpmSubfolder, ')(', '_');
287
+ dotPnpmSubfolder = node_core_library_1.Text.replaceAll(dotPnpmSubfolder, '(', '_');
288
+ dotPnpmSubfolder = node_core_library_1.Text.replaceAll(dotPnpmSubfolder, ')', '');
289
+ }
290
+ // Example:
291
+ // common/temp/default/node_modules/.pnpm
292
+ // /@babel+register@7.17.7_@babel+core@7.17.12
293
+ // /node_modules/@babel/register
294
+ result.packageJsonFolderPath = lockfilePath.join(pnpmLockfileFolder, `node_modules/.pnpm/` + dotPnpmSubfolder + '/node_modules/' + result.entryPackageName);
295
+ const lockfileEntry = new lfx_shared_1.LfxGraphEntry(result);
296
+ parsePackageDependencies(lockfileEntry.dependencies, lockfileEntry, rawYamlData, pnpmLockfileVersion, workspace);
297
+ return lockfileEntry;
298
+ }
299
+ /**
300
+ * Parse through the lockfile and create all the corresponding LockfileEntries and LockfileDependencies
301
+ * to construct the lockfile graph.
302
+ *
303
+ * @returns A list of all the LockfileEntries in the lockfile.
304
+ */
305
+ function generateLockfileGraph(lockfileJson, workspace) {
306
+ var _a;
307
+ const lockfile = lockfileJson;
308
+ let pnpmLockfileVersion;
309
+ switch (lockfile.lockfileVersion.toString()) {
310
+ case '5.4':
311
+ pnpmLockfileVersion = 54;
312
+ break;
313
+ case '6':
314
+ case '6.0':
315
+ pnpmLockfileVersion = 60;
316
+ break;
317
+ //case '9':
318
+ //case '9.0':
319
+ // pnpmLockfileVersion = 90;
320
+ // break;
321
+ default:
322
+ throw new Error('Unsupported PNPM lockfile version ' + JSON.stringify(lockfile.lockfileVersion));
323
+ }
324
+ const lfxGraph = new lfx_shared_1.LfxGraph(workspace);
325
+ const allEntries = lfxGraph.entries;
326
+ const allEntriesById = new Map();
327
+ const allImporters = [];
328
+ // "Importers" are the local workspace projects
329
+ if (lockfile.importers) {
330
+ // Normally the UX shows the concise project folder name. However in the case of duplicates
331
+ // (where two projects use the same folder name), then we will need to disambiguate.
332
+ const baseNames = new Set();
333
+ const duplicates = new Set();
334
+ for (const importerKey of Object.keys(lockfile.importers)) {
335
+ const baseName = lockfilePath.getBaseNameOf(importerKey);
336
+ if (baseNames.has(baseName)) {
337
+ duplicates.add(baseName);
338
+ }
339
+ baseNames.add(baseName);
340
+ }
341
+ const isRushWorkspace = workspace.rushConfig !== undefined;
342
+ for (const importerKey of Object.keys(lockfile.importers)) {
343
+ if (isRushWorkspace && importerKey === '.') {
344
+ // Discard the synthetic package.json file created by Rush under common/temp
345
+ continue;
346
+ }
347
+ const importer = createProjectLockfileEntry({
348
+ rawEntryId: importerKey,
349
+ duplicates,
350
+ workspace,
351
+ pnpmLockfileVersion
352
+ });
353
+ if (pnpmLockfileVersion === 54) {
354
+ const lockfile54 = lockfileJson;
355
+ const importerValue = lockfile54.importers[importerKey];
356
+ parsePackageDependencies(importer.dependencies, importer, importerValue, pnpmLockfileVersion, workspace);
357
+ }
358
+ else {
359
+ const lockfile60 = lockfileJson;
360
+ if (lockfile60.importers) {
361
+ const importerValue = lockfile60.importers[importerKey];
362
+ parseProjectDependencies60(importer.dependencies, importer, importerValue, pnpmLockfileVersion, workspace);
363
+ }
364
+ }
365
+ allImporters.push(importer);
366
+ allEntries.push(importer);
367
+ allEntriesById.set(importer.entryId, importer);
368
+ }
369
+ }
370
+ const allPackages = [];
371
+ if (lockfile.packages) {
372
+ for (const [dependencyKey, dependencyValue] of Object.entries((_a = lockfile.packages) !== null && _a !== void 0 ? _a : {})) {
373
+ // const normalizedPath = new Path(dependencyKey).makeAbsolute('/').toString();
374
+ const currEntry = createPackageLockfileEntry({
375
+ rawEntryId: dependencyKey,
376
+ rawYamlData: dependencyValue,
377
+ workspace,
378
+ pnpmLockfileVersion
379
+ });
380
+ allPackages.push(currEntry);
381
+ allEntries.push(currEntry);
382
+ allEntriesById.set(dependencyKey, currEntry);
383
+ }
384
+ }
385
+ // Construct the graph
386
+ for (const entry of allEntries) {
387
+ for (const dependency of entry.dependencies) {
388
+ // Peer dependencies do not have a matching entry
389
+ if (dependency.dependencyType === lfx_shared_1.LfxDependencyKind.Peer) {
390
+ continue;
391
+ }
392
+ const matchedEntry = allEntriesById.get(dependency.entryId);
393
+ if (matchedEntry) {
394
+ // Create a two-way link between the dependency and the entry
395
+ dependency.resolvedEntry = matchedEntry;
396
+ matchedEntry.referrers.push(entry);
397
+ }
398
+ else {
399
+ if (dependency.entryId.startsWith('/')) {
400
+ // Local package
401
+ console.error('Could not resolve dependency entryId: ', dependency.entryId, dependency);
402
+ }
403
+ }
404
+ }
405
+ }
406
+ return lfxGraph;
407
+ }
408
+ //# sourceMappingURL=lfxGraphLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lfxGraphLoader.js","sourceRoot":"","sources":["../../src/graph/lfxGraphLoader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type * as lockfileTypes from '@pnpm/lockfile.types';\nimport type * as pnpmTypes from '@pnpm/types';\nimport { Text } from '@rushstack/node-core-library';\n\nimport {\n type ILfxGraphDependencyOptions,\n type ILfxGraphEntryOptions,\n LfxGraph,\n LfxGraphEntry,\n LfxGraphEntryKind,\n LfxDependencyKind,\n LfxGraphDependency,\n type IJsonLfxWorkspace\n} from '../../build/lfx-shared';\nimport * as lockfilePath from './lockfilePath';\n\ntype PnpmLockfileVersion = 54 | 60 | 90;\ntype PeerDependenciesMeta = lockfileTypes.LockfilePackageInfo['peerDependenciesMeta'];\n\nfunction createPackageLockfileDependency(options: {\n name: string;\n version: string;\n kind: LfxDependencyKind;\n containingEntry: LfxGraphEntry;\n peerDependenciesMeta?: PeerDependenciesMeta;\n pnpmLockfileVersion: PnpmLockfileVersion;\n workspace: IJsonLfxWorkspace;\n}): LfxGraphDependency {\n const {\n name,\n version,\n kind: dependencyType,\n containingEntry,\n peerDependenciesMeta,\n pnpmLockfileVersion\n } = options;\n\n const result: ILfxGraphDependencyOptions = {\n name,\n version,\n dependencyType,\n containingEntry,\n entryId: '',\n peerDependencyMeta: {}\n };\n\n if (version.startsWith('link:')) {\n const relativePath: string = version.substring('link:'.length);\n\n if (containingEntry.kind === LfxGraphEntryKind.Project) {\n // TODO: Here we assume it's a \"workspace:\" link and try to resolve it to another workspace project,\n // but it could also be a link to an arbitrary folder (in which case this entryId will fail to resolve).\n // In the future, we should distinguish these cases.\n const selfRelativePath: string = lockfilePath.getAbsolute(\n containingEntry.packageJsonFolderPath,\n relativePath\n );\n result.entryId = 'project:' + selfRelativePath.toString();\n } else {\n // This could be a link to anywhere on the local computer, so we don't expect it to have a lockfile entry\n result.entryId = '';\n }\n } else if (result.version.startsWith('/')) {\n result.entryId = version;\n } else if (result.dependencyType === LfxDependencyKind.Peer) {\n result.peerDependencyMeta = {\n name: result.name,\n version: version,\n optional: peerDependenciesMeta?.[result.name] ? peerDependenciesMeta[result.name].optional : false\n };\n result.entryId = 'Peer: ' + result.name;\n } else {\n // Version 5.4: /@rushstack/m/1.0.0:\n // Version 6.0: /@rushstack/m@1.0.0:\n //\n // Version 5.4: /@rushstack/j/1.0.0_@rushstack+n@2.0.0\n // Version 6.0: /@rushstack/j@1.0.0(@rushstack/n@2.0.0)\n const versionDelimiter: string = pnpmLockfileVersion === 54 ? '/' : '@';\n result.entryId = '/' + result.name + versionDelimiter + result.version;\n }\n return new LfxGraphDependency(result);\n}\n\n// v5.4 used this to parse projects (\"importers\") also\nfunction parsePackageDependencies(\n dependencies: LfxGraphDependency[],\n lockfileEntry: LfxGraphEntry,\n either: lockfileTypes.ProjectSnapshot | lockfileTypes.PackageSnapshot,\n pnpmLockfileVersion: PnpmLockfileVersion,\n workspace: IJsonLfxWorkspace\n): void {\n const node: Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot> =\n either as unknown as Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot>;\n if (node.dependencies) {\n for (const [packageName, version] of Object.entries(node.dependencies)) {\n dependencies.push(\n createPackageLockfileDependency({\n kind: LfxDependencyKind.Regular,\n name: packageName,\n version: version,\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n }\n if (node.devDependencies) {\n for (const [packageName, version] of Object.entries(node.devDependencies)) {\n dependencies.push(\n createPackageLockfileDependency({\n kind: LfxDependencyKind.Dev,\n name: packageName,\n version: version,\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n }\n if (node.peerDependencies) {\n for (const [packageName, version] of Object.entries(node.peerDependencies)) {\n dependencies.push(\n createPackageLockfileDependency({\n kind: LfxDependencyKind.Peer,\n name: packageName,\n version: version,\n containingEntry: lockfileEntry,\n peerDependenciesMeta: node.peerDependenciesMeta,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n }\n if (node.transitivePeerDependencies) {\n for (const dep of node.transitivePeerDependencies) {\n lockfileEntry.transitivePeerDependencies.add(dep);\n }\n }\n}\n\nfunction parseProjectDependencies60(\n dependencies: LfxGraphDependency[],\n lockfileEntry: LfxGraphEntry,\n snapshot: lockfileTypes.LockfileFileProjectSnapshot,\n pnpmLockfileVersion: PnpmLockfileVersion,\n workspace: IJsonLfxWorkspace\n): void {\n if (snapshot.dependencies) {\n for (const [packageName, specifierAndResolution] of Object.entries(snapshot.dependencies)) {\n dependencies.push(\n createPackageLockfileDependency({\n kind: LfxDependencyKind.Regular,\n name: packageName,\n version: specifierAndResolution.version,\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n }\n if (snapshot.devDependencies) {\n for (const [packageName, specifierAndResolution] of Object.entries(snapshot.devDependencies)) {\n dependencies.push(\n createPackageLockfileDependency({\n kind: LfxDependencyKind.Dev,\n name: packageName,\n version: specifierAndResolution.version,\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n }\n}\n\nfunction createProjectLockfileEntry(options: {\n rawEntryId: string;\n duplicates?: Set<string>;\n workspace: IJsonLfxWorkspace;\n pnpmLockfileVersion: PnpmLockfileVersion;\n}): LfxGraphEntry {\n const { rawEntryId, duplicates, workspace } = options;\n\n const result: ILfxGraphEntryOptions = {\n kind: LfxGraphEntryKind.Project,\n entryId: '',\n rawEntryId: '',\n packageJsonFolderPath: '',\n entryPackageName: '',\n displayText: '',\n entryPackageVersion: '',\n entrySuffix: ''\n };\n\n result.rawEntryId = rawEntryId;\n\n // Example: pnpmLockfilePath = 'common/temp/my-subspace/pnpm-lock.yaml'\n // Example: pnpmLockfileFolder = 'common/temp/my-subspace'\n const pnpmLockfileFolder: string = workspace.pnpmLockfileFolder;\n\n // Example: rawEntryId = '../../../projects/a'\n // Example: packageJsonFolderPath = 'projects/a'\n result.packageJsonFolderPath = lockfilePath.getAbsolute(pnpmLockfileFolder, rawEntryId);\n result.entryId = 'project:' + result.packageJsonFolderPath;\n\n const projectFolderName: string = lockfilePath.getBaseNameOf(rawEntryId);\n\n if (!duplicates?.has(projectFolderName)) {\n // TODO: The actual package.json name might not match its directory name,\n // but we have to load package.json to determine it.\n result.entryPackageName = projectFolderName;\n } else {\n result.entryPackageName = `${projectFolderName} (${result.packageJsonFolderPath})`;\n }\n result.displayText = `Project: ${result.entryPackageName}`;\n\n const lockfileEntry: LfxGraphEntry = new LfxGraphEntry(result);\n return lockfileEntry;\n}\n\nfunction createPackageLockfileEntry(options: {\n rawEntryId: string;\n rawYamlData: lockfileTypes.PackageSnapshot;\n workspace: IJsonLfxWorkspace;\n pnpmLockfileVersion: PnpmLockfileVersion;\n}): LfxGraphEntry {\n const { rawEntryId, rawYamlData, pnpmLockfileVersion, workspace } = options;\n\n const result: ILfxGraphEntryOptions = {\n kind: LfxGraphEntryKind.Package,\n entryId: '',\n rawEntryId: '',\n packageJsonFolderPath: '',\n entryPackageName: '',\n displayText: '',\n entryPackageVersion: '',\n entrySuffix: ''\n };\n\n result.rawEntryId = rawEntryId;\n\n // Example: pnpmLockfilePath = 'common/temp/my-subspace/pnpm-lock.yaml'\n // Example: pnpmLockfileFolder = 'common/temp/my-subspace'\n const pnpmLockfileFolder: string = workspace.pnpmLockfileFolder;\n\n result.displayText = rawEntryId;\n\n if (!rawEntryId.startsWith('/')) {\n throw new Error('Expecting leading \"/\" in path: ' + JSON.stringify(rawEntryId));\n }\n\n let dotPnpmSubfolder: string;\n\n if (pnpmLockfileVersion === 54) {\n const lastSlashIndex: number = rawEntryId.lastIndexOf('/');\n if (lastSlashIndex < 0) {\n throw new Error('Expecting \"/\" in path: ' + JSON.stringify(rawEntryId));\n }\n const packageName: string = rawEntryId.substring(1, lastSlashIndex);\n result.entryPackageName = packageName;\n\n // /@rushstack/eslint-config/3.0.1_eslint@8.21.0+typescript@4.7.4\n // --> @rushstack/eslint-config 3.0.1 (eslint@8.21.0+typescript@4.7.4)\n const underscoreIndex: number = rawEntryId.indexOf('_', lastSlashIndex);\n if (underscoreIndex > 0) {\n const version: string = rawEntryId.substring(lastSlashIndex + 1, underscoreIndex);\n const suffix: string = rawEntryId.substring(underscoreIndex + 1);\n result.displayText = packageName + ' ' + version + ' (' + suffix + ')';\n result.entryPackageVersion = version;\n result.entrySuffix = suffix;\n } else {\n // /@rushstack/eslint-config/3.0.1\n // --> @rushstack/eslint-config 3.0.1\n const version: string = rawEntryId.substring(lastSlashIndex + 1);\n result.displayText = packageName + ' ' + version;\n result.entryPackageVersion = version;\n }\n\n // Example: @babel+register@7.17.7_@babel+core@7.17.12\n dotPnpmSubfolder =\n result.entryPackageName.replace('/', '+') +\n '@' +\n result.entryPackageVersion +\n (result.entrySuffix ? `_${result.entrySuffix}` : '');\n } else {\n // Example inputs:\n // /@rushstack/eslint-config@3.0.1\n // /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\n let versionAtSignIndex: number;\n if (rawEntryId.startsWith('/@')) {\n versionAtSignIndex = rawEntryId.indexOf('@', 2);\n } else {\n versionAtSignIndex = rawEntryId.indexOf('@', 1);\n }\n const packageName: string = rawEntryId.substring(1, versionAtSignIndex);\n result.entryPackageName = packageName;\n\n const leftParenIndex: number = rawEntryId.indexOf('(', versionAtSignIndex);\n if (leftParenIndex < 0) {\n const version: string = rawEntryId.substring(versionAtSignIndex + 1);\n result.entryPackageVersion = version;\n\n // /@rushstack/eslint-config@3.0.1\n // --> @rushstack/eslint-config 3.0.1\n result.displayText = packageName + ' ' + version;\n } else {\n const version: string = rawEntryId.substring(versionAtSignIndex + 1, leftParenIndex);\n result.entryPackageVersion = version;\n\n // \"(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\"\n let suffix: string = rawEntryId.substring(leftParenIndex);\n\n // Rewrite to:\n // \"@rushstack/m@1.0.0; @rushstack/n@2.0.0\"\n suffix = Text.replaceAll(suffix, ')(', '; ');\n suffix = Text.replaceAll(suffix, '(', '');\n suffix = Text.replaceAll(suffix, ')', '');\n result.entrySuffix = suffix;\n\n // /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\n // --> @rushstack/l 1.0.0 [@rushstack/m@1.0.0; @rushstack/n@2.0.0]\n result.displayText = packageName + ' ' + version + ' [' + suffix + ']';\n }\n\n // Example: /@rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\n // --> @rushstack+l@1.0.0_@rushstack+m@1.0.0_@rushstack+n@2.0.0\n\n // @rushstack/l 1.0.0 (@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\n dotPnpmSubfolder = rawEntryId.substring(1);\n dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, '/', '+');\n dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, ')(', '_');\n dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, '(', '_');\n dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, ')', '');\n }\n\n // Example:\n // common/temp/default/node_modules/.pnpm\n // /@babel+register@7.17.7_@babel+core@7.17.12\n // /node_modules/@babel/register\n result.packageJsonFolderPath = lockfilePath.join(\n pnpmLockfileFolder,\n `node_modules/.pnpm/` + dotPnpmSubfolder + '/node_modules/' + result.entryPackageName\n );\n\n const lockfileEntry: LfxGraphEntry = new LfxGraphEntry(result);\n parsePackageDependencies(\n lockfileEntry.dependencies,\n lockfileEntry,\n rawYamlData,\n pnpmLockfileVersion,\n workspace\n );\n return lockfileEntry;\n}\n\n/**\n * Parse through the lockfile and create all the corresponding LockfileEntries and LockfileDependencies\n * to construct the lockfile graph.\n *\n * @returns A list of all the LockfileEntries in the lockfile.\n */\nexport function generateLockfileGraph(lockfileJson: unknown, workspace: IJsonLfxWorkspace): LfxGraph {\n const lockfile: lockfileTypes.LockfileObject | lockfileTypes.LockfileFile = lockfileJson as\n | lockfileTypes.LockfileObject\n | lockfileTypes.LockfileFile;\n\n let pnpmLockfileVersion: PnpmLockfileVersion;\n switch (lockfile.lockfileVersion.toString()) {\n case '5.4':\n pnpmLockfileVersion = 54;\n break;\n case '6':\n case '6.0':\n pnpmLockfileVersion = 60;\n break;\n //case '9':\n //case '9.0':\n // pnpmLockfileVersion = 90;\n // break;\n default:\n throw new Error('Unsupported PNPM lockfile version ' + JSON.stringify(lockfile.lockfileVersion));\n }\n\n const lfxGraph: LfxGraph = new LfxGraph(workspace);\n const allEntries: LfxGraphEntry[] = lfxGraph.entries;\n const allEntriesById: Map<string, LfxGraphEntry> = new Map();\n\n const allImporters: LfxGraphEntry[] = [];\n\n // \"Importers\" are the local workspace projects\n if (lockfile.importers) {\n // Normally the UX shows the concise project folder name. However in the case of duplicates\n // (where two projects use the same folder name), then we will need to disambiguate.\n const baseNames: Set<string> = new Set();\n const duplicates: Set<string> = new Set();\n for (const importerKey of Object.keys(lockfile.importers)) {\n const baseName: string = lockfilePath.getBaseNameOf(importerKey);\n if (baseNames.has(baseName)) {\n duplicates.add(baseName);\n }\n baseNames.add(baseName);\n }\n\n const isRushWorkspace: boolean = workspace.rushConfig !== undefined;\n\n for (const importerKey of Object.keys(lockfile.importers)) {\n if (isRushWorkspace && importerKey === '.') {\n // Discard the synthetic package.json file created by Rush under common/temp\n continue;\n }\n\n const importer: LfxGraphEntry = createProjectLockfileEntry({\n rawEntryId: importerKey,\n duplicates,\n workspace,\n pnpmLockfileVersion\n });\n\n if (pnpmLockfileVersion === 54) {\n const lockfile54: lockfileTypes.LockfileObject = lockfileJson as lockfileTypes.LockfileObject;\n const importerValue: lockfileTypes.ProjectSnapshot =\n lockfile54.importers[importerKey as pnpmTypes.ProjectId];\n parsePackageDependencies(\n importer.dependencies,\n importer,\n importerValue,\n pnpmLockfileVersion,\n workspace\n );\n } else {\n const lockfile60: lockfileTypes.LockfileFile = lockfileJson as lockfileTypes.LockfileFile;\n if (lockfile60.importers) {\n const importerValue: lockfileTypes.LockfileFileProjectSnapshot =\n lockfile60.importers[importerKey as pnpmTypes.ProjectId];\n parseProjectDependencies60(\n importer.dependencies,\n importer,\n importerValue,\n pnpmLockfileVersion,\n workspace\n );\n }\n }\n\n allImporters.push(importer);\n allEntries.push(importer);\n allEntriesById.set(importer.entryId, importer);\n }\n }\n\n const allPackages: LfxGraphEntry[] = [];\n if (lockfile.packages) {\n for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages ?? {})) {\n // const normalizedPath = new Path(dependencyKey).makeAbsolute('/').toString();\n\n const currEntry: LfxGraphEntry = createPackageLockfileEntry({\n rawEntryId: dependencyKey,\n rawYamlData: dependencyValue as lockfileTypes.PackageSnapshot,\n workspace,\n pnpmLockfileVersion\n });\n\n allPackages.push(currEntry);\n allEntries.push(currEntry);\n allEntriesById.set(dependencyKey, currEntry);\n }\n }\n\n // Construct the graph\n for (const entry of allEntries) {\n for (const dependency of entry.dependencies) {\n // Peer dependencies do not have a matching entry\n if (dependency.dependencyType === LfxDependencyKind.Peer) {\n continue;\n }\n\n const matchedEntry: LfxGraphEntry | undefined = allEntriesById.get(dependency.entryId);\n if (matchedEntry) {\n // Create a two-way link between the dependency and the entry\n dependency.resolvedEntry = matchedEntry;\n matchedEntry.referrers.push(entry);\n } else {\n if (dependency.entryId.startsWith('/')) {\n // Local package\n console.error('Could not resolve dependency entryId: ', dependency.entryId, dependency);\n }\n }\n }\n }\n\n return lfxGraph;\n}\n"]}