@rushstack/lockfile-explorer 2.1.7 → 2.2.1

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 (106) hide show
  1. package/CHANGELOG.json +38 -0
  2. package/CHANGELOG.md +15 -1
  3. package/bin/lockfile-explorer +1 -1
  4. package/bin/lockfile-lint +1 -1
  5. package/dist/app.488eeffc8a0c899a054c.css +1 -0
  6. package/dist/app.55bea5774c40f4ed1bf2.js +1 -0
  7. package/dist/index.html +1 -1
  8. package/dist/rush-themed-ui.js +2 -2
  9. package/lib-esm/assets/lint-init/lockfile-lint-template.json +42 -0
  10. package/lib-esm/cli/explorer/ExplorerCommandLineParser.js +204 -0
  11. package/lib-esm/cli/explorer/ExplorerCommandLineParser.js.map +1 -0
  12. package/lib-esm/cli/lint/LintCommandLineParser.js +31 -0
  13. package/lib-esm/cli/lint/LintCommandLineParser.js.map +1 -0
  14. package/lib-esm/cli/lint/actions/CheckAction.js +138 -0
  15. package/lib-esm/cli/lint/actions/CheckAction.js.map +1 -0
  16. package/lib-esm/cli/lint/actions/InitAction.js +38 -0
  17. package/lib-esm/cli/lint/actions/InitAction.js.map +1 -0
  18. package/lib-esm/constants/common.js +5 -0
  19. package/lib-esm/constants/common.js.map +1 -0
  20. package/lib-esm/graph/IPnpmfileModule.js +4 -0
  21. package/lib-esm/graph/IPnpmfileModule.js.map +1 -0
  22. package/lib-esm/graph/PnpmfileRunner.js +86 -0
  23. package/lib-esm/graph/PnpmfileRunner.js.map +1 -0
  24. package/lib-esm/graph/lfxGraphLoader.js +459 -0
  25. package/lib-esm/graph/lfxGraphLoader.js.map +1 -0
  26. package/lib-esm/graph/lockfilePath.js +117 -0
  27. package/lib-esm/graph/lockfilePath.js.map +1 -0
  28. package/lib-esm/graph/pnpmfileRunnerWorkerThread.js +59 -0
  29. package/lib-esm/graph/pnpmfileRunnerWorkerThread.js.map +1 -0
  30. package/lib-esm/schemas/lockfile-lint.schema.json +45 -0
  31. package/lib-esm/start-explorer.js +6 -0
  32. package/lib-esm/start-explorer.js.map +1 -0
  33. package/lib-esm/start-lint.js +6 -0
  34. package/lib-esm/start-lint.js.map +1 -0
  35. package/lib-esm/state/index.js +4 -0
  36. package/lib-esm/state/index.js.map +1 -0
  37. package/lib-esm/utils/init.js +77 -0
  38. package/lib-esm/utils/init.js.map +1 -0
  39. package/lib-esm/utils/shrinkwrap.js +44 -0
  40. package/lib-esm/utils/shrinkwrap.js.map +1 -0
  41. package/package.json +30 -8
  42. package/dist/app.c67214284d4725ea5913.js +0 -1
  43. package/dist/app.e74e7004c99e392a3c70.css +0 -1
  44. package/dist/initappcontext.js +0 -14
  45. /package/{lib → lib-commonjs}/assets/lint-init/lockfile-lint-template.json +0 -0
  46. /package/{lib → lib-commonjs}/cli/explorer/ExplorerCommandLineParser.js +0 -0
  47. /package/{lib → lib-commonjs}/cli/explorer/ExplorerCommandLineParser.js.map +0 -0
  48. /package/{lib → lib-commonjs}/cli/lint/LintCommandLineParser.js +0 -0
  49. /package/{lib → lib-commonjs}/cli/lint/LintCommandLineParser.js.map +0 -0
  50. /package/{lib → lib-commonjs}/cli/lint/actions/CheckAction.js +0 -0
  51. /package/{lib → lib-commonjs}/cli/lint/actions/CheckAction.js.map +0 -0
  52. /package/{lib → lib-commonjs}/cli/lint/actions/InitAction.js +0 -0
  53. /package/{lib → lib-commonjs}/cli/lint/actions/InitAction.js.map +0 -0
  54. /package/{lib → lib-commonjs}/constants/common.js +0 -0
  55. /package/{lib → lib-commonjs}/constants/common.js.map +0 -0
  56. /package/{lib → lib-commonjs}/graph/IPnpmfileModule.js +0 -0
  57. /package/{lib → lib-commonjs}/graph/IPnpmfileModule.js.map +0 -0
  58. /package/{lib → lib-commonjs}/graph/PnpmfileRunner.js +0 -0
  59. /package/{lib → lib-commonjs}/graph/PnpmfileRunner.js.map +0 -0
  60. /package/{lib → lib-commonjs}/graph/lfxGraphLoader.js +0 -0
  61. /package/{lib → lib-commonjs}/graph/lfxGraphLoader.js.map +0 -0
  62. /package/{lib → lib-commonjs}/graph/lockfilePath.js +0 -0
  63. /package/{lib → lib-commonjs}/graph/lockfilePath.js.map +0 -0
  64. /package/{lib → lib-commonjs}/graph/pnpmfileRunnerWorkerThread.js +0 -0
  65. /package/{lib → lib-commonjs}/graph/pnpmfileRunnerWorkerThread.js.map +0 -0
  66. /package/{lib → lib-commonjs}/schemas/lockfile-lint.schema.json +0 -0
  67. /package/{lib → lib-commonjs}/start-explorer.js +0 -0
  68. /package/{lib → lib-commonjs}/start-explorer.js.map +0 -0
  69. /package/{lib → lib-commonjs}/start-lint.js +0 -0
  70. /package/{lib → lib-commonjs}/start-lint.js.map +0 -0
  71. /package/{lib → lib-commonjs}/state/index.js +0 -0
  72. /package/{lib → lib-commonjs}/state/index.js.map +0 -0
  73. /package/{lib → lib-commonjs}/utils/init.js +0 -0
  74. /package/{lib → lib-commonjs}/utils/init.js.map +0 -0
  75. /package/{lib → lib-commonjs}/utils/shrinkwrap.js +0 -0
  76. /package/{lib → lib-commonjs}/utils/shrinkwrap.js.map +0 -0
  77. /package/{lib → lib-dts}/cli/explorer/ExplorerCommandLineParser.d.ts +0 -0
  78. /package/{lib → lib-dts}/cli/explorer/ExplorerCommandLineParser.d.ts.map +0 -0
  79. /package/{lib → lib-dts}/cli/lint/LintCommandLineParser.d.ts +0 -0
  80. /package/{lib → lib-dts}/cli/lint/LintCommandLineParser.d.ts.map +0 -0
  81. /package/{lib → lib-dts}/cli/lint/actions/CheckAction.d.ts +0 -0
  82. /package/{lib → lib-dts}/cli/lint/actions/CheckAction.d.ts.map +0 -0
  83. /package/{lib → lib-dts}/cli/lint/actions/InitAction.d.ts +0 -0
  84. /package/{lib → lib-dts}/cli/lint/actions/InitAction.d.ts.map +0 -0
  85. /package/{lib → lib-dts}/constants/common.d.ts +0 -0
  86. /package/{lib → lib-dts}/constants/common.d.ts.map +0 -0
  87. /package/{lib → lib-dts}/graph/IPnpmfileModule.d.ts +0 -0
  88. /package/{lib → lib-dts}/graph/IPnpmfileModule.d.ts.map +0 -0
  89. /package/{lib → lib-dts}/graph/PnpmfileRunner.d.ts +0 -0
  90. /package/{lib → lib-dts}/graph/PnpmfileRunner.d.ts.map +0 -0
  91. /package/{lib → lib-dts}/graph/lfxGraphLoader.d.ts +0 -0
  92. /package/{lib → lib-dts}/graph/lfxGraphLoader.d.ts.map +0 -0
  93. /package/{lib → lib-dts}/graph/lockfilePath.d.ts +0 -0
  94. /package/{lib → lib-dts}/graph/lockfilePath.d.ts.map +0 -0
  95. /package/{lib → lib-dts}/graph/pnpmfileRunnerWorkerThread.d.ts +0 -0
  96. /package/{lib → lib-dts}/graph/pnpmfileRunnerWorkerThread.d.ts.map +0 -0
  97. /package/{lib → lib-dts}/start-explorer.d.ts +0 -0
  98. /package/{lib → lib-dts}/start-explorer.d.ts.map +0 -0
  99. /package/{lib → lib-dts}/start-lint.d.ts +0 -0
  100. /package/{lib → lib-dts}/start-lint.d.ts.map +0 -0
  101. /package/{lib → lib-dts}/state/index.d.ts +0 -0
  102. /package/{lib → lib-dts}/state/index.d.ts.map +0 -0
  103. /package/{lib → lib-dts}/utils/init.d.ts +0 -0
  104. /package/{lib → lib-dts}/utils/init.d.ts.map +0 -0
  105. /package/{lib → lib-dts}/utils/shrinkwrap.d.ts +0 -0
  106. /package/{lib → lib-dts}/utils/shrinkwrap.d.ts.map +0 -0
@@ -0,0 +1,459 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ import { Text } from '@rushstack/node-core-library';
4
+ import { LfxGraph, LfxGraphEntry, LfxGraphEntryKind, LfxDependencyKind, LfxGraphDependency } from '../../build/lfx-shared';
5
+ import * as lockfilePath from './lockfilePath';
6
+ function createPackageLockfileDependency(options) {
7
+ const { name, versionPath, originalSpecifier, kind: dependencyKind, containingEntry, peerDependenciesMeta, pnpmLockfileVersion } = options;
8
+ const result = {
9
+ name,
10
+ versionPath,
11
+ entryId: '',
12
+ originalSpecifier,
13
+ dependencyKind,
14
+ peerDependencyMeta: {},
15
+ containingEntry
16
+ };
17
+ if (versionPath.startsWith('link:')) {
18
+ const relativePath = versionPath.substring('link:'.length);
19
+ if (containingEntry.kind === LfxGraphEntryKind.Project) {
20
+ // TODO: Here we assume it's a "workspace:" link and try to resolve it to another workspace project,
21
+ // but it could also be a link to an arbitrary folder (in which case this entryId will fail to resolve).
22
+ // In the future, we should distinguish these cases.
23
+ const selfRelativePath = lockfilePath.getAbsolute(containingEntry.packageJsonFolderPath, relativePath);
24
+ result.entryId = 'project:' + selfRelativePath.toString();
25
+ }
26
+ else {
27
+ // This could be a link to anywhere on the local computer, so we don't expect it to have a lockfile entry
28
+ result.entryId = '';
29
+ }
30
+ }
31
+ else if (result.versionPath.startsWith('/')) {
32
+ result.entryId = versionPath;
33
+ }
34
+ else {
35
+ // Version 5.4: /@rushstack/m/1.0.0:
36
+ // Version 6.0: /@rushstack/m@1.0.0:
37
+ // Version 9.0: @rushstack/m@1.0.0:
38
+ //
39
+ // Version 5.4: /@rushstack/j/1.0.0_@rushstack+n@2.0.0
40
+ // Version 6.0: /@rushstack/j@1.0.0(@rushstack/n@2.0.0)
41
+ // Version 9.0: @rushstack/j@1.0.0(@rushstack/n@2.0.0)
42
+ const versionDelimiter = pnpmLockfileVersion < 60 ? '/' : '@';
43
+ result.entryId =
44
+ (pnpmLockfileVersion < 90 ? '/' : '') + result.name + versionDelimiter + result.versionPath;
45
+ }
46
+ if (result.dependencyKind === LfxDependencyKind.Peer) {
47
+ result.peerDependencyMeta = {
48
+ name: result.name,
49
+ version: versionPath,
50
+ optional: (peerDependenciesMeta === null || peerDependenciesMeta === void 0 ? void 0 : peerDependenciesMeta[result.name]) ? peerDependenciesMeta[result.name].optional : false
51
+ };
52
+ }
53
+ return new LfxGraphDependency(result);
54
+ }
55
+ function parsePackageDependencies(options) {
56
+ const { dependencies, lockfileEntry, mainEntry, specifierEntry, pnpmLockfileVersion, workspace } = options;
57
+ const node = mainEntry;
58
+ function createDependency(kind, packageName, versionPath) {
59
+ let originalSpecifier = undefined;
60
+ if (specifierEntry && specifierEntry.peerDependencies) {
61
+ originalSpecifier = specifierEntry.peerDependencies[packageName];
62
+ if (originalSpecifier) {
63
+ kind = LfxDependencyKind.Peer;
64
+ }
65
+ }
66
+ dependencies.push(createPackageLockfileDependency({
67
+ kind,
68
+ name: packageName,
69
+ versionPath,
70
+ originalSpecifier: originalSpecifier !== null && originalSpecifier !== void 0 ? originalSpecifier : '',
71
+ containingEntry: lockfileEntry,
72
+ peerDependenciesMeta: specifierEntry === null || specifierEntry === void 0 ? void 0 : specifierEntry.peerDependenciesMeta,
73
+ pnpmLockfileVersion,
74
+ workspace
75
+ }));
76
+ }
77
+ if (node.dependencies) {
78
+ for (const [packageName, versionPath] of Object.entries(node.dependencies)) {
79
+ createDependency(LfxDependencyKind.Regular, packageName, versionPath);
80
+ }
81
+ }
82
+ if (node.optionalDependencies) {
83
+ for (const [packageName, versionPath] of Object.entries(node.optionalDependencies)) {
84
+ createDependency(LfxDependencyKind.Regular, packageName, versionPath);
85
+ }
86
+ }
87
+ if (node.devDependencies) {
88
+ for (const [packageName, versionPath] of Object.entries(node.devDependencies)) {
89
+ createDependency(LfxDependencyKind.Dev, packageName, versionPath);
90
+ }
91
+ }
92
+ if (node.transitivePeerDependencies) {
93
+ for (const dep of node.transitivePeerDependencies) {
94
+ lockfileEntry.transitivePeerDependencies.add(dep);
95
+ }
96
+ }
97
+ }
98
+ function parseProjectDependencies54(options) {
99
+ const { dependencies, lockfileEntry, mainEntry, pnpmLockfileVersion, workspace } = options;
100
+ const node = mainEntry;
101
+ function createDependency(kind, packageName, versionPath) {
102
+ let originalSpecifier = undefined;
103
+ if (mainEntry.specifiers) {
104
+ originalSpecifier = mainEntry.specifiers[packageName];
105
+ }
106
+ dependencies.push(createPackageLockfileDependency({
107
+ kind,
108
+ name: packageName,
109
+ versionPath,
110
+ originalSpecifier: originalSpecifier !== null && originalSpecifier !== void 0 ? originalSpecifier : '',
111
+ containingEntry: lockfileEntry,
112
+ pnpmLockfileVersion,
113
+ workspace
114
+ }));
115
+ }
116
+ if (node.dependencies) {
117
+ for (const [packageName, versionPath] of Object.entries(node.dependencies)) {
118
+ createDependency(LfxDependencyKind.Regular, packageName, versionPath);
119
+ }
120
+ }
121
+ if (node.optionalDependencies) {
122
+ for (const [packageName, versionPath] of Object.entries(node.optionalDependencies)) {
123
+ createDependency(LfxDependencyKind.Regular, packageName, versionPath);
124
+ }
125
+ }
126
+ if (node.devDependencies) {
127
+ for (const [packageName, versionPath] of Object.entries(node.devDependencies)) {
128
+ createDependency(LfxDependencyKind.Dev, packageName, versionPath);
129
+ }
130
+ }
131
+ }
132
+ function parseProjectDependencies60(dependencies, lockfileEntry, snapshot, pnpmLockfileVersion, workspace) {
133
+ function createDependency(kind, packageName, specifierAndResolution) {
134
+ dependencies.push(createPackageLockfileDependency({
135
+ kind,
136
+ name: packageName,
137
+ versionPath: specifierAndResolution.version,
138
+ originalSpecifier: specifierAndResolution.specifier,
139
+ containingEntry: lockfileEntry,
140
+ pnpmLockfileVersion,
141
+ workspace
142
+ }));
143
+ }
144
+ if (snapshot.dependencies) {
145
+ for (const [packageName, specifierAndResolution] of Object.entries(snapshot.dependencies)) {
146
+ createDependency(LfxDependencyKind.Regular, packageName, specifierAndResolution);
147
+ }
148
+ }
149
+ if (snapshot.optionalDependencies) {
150
+ for (const [packageName, specifierAndResolution] of Object.entries(snapshot.optionalDependencies)) {
151
+ createDependency(LfxDependencyKind.Regular, packageName, specifierAndResolution);
152
+ }
153
+ }
154
+ if (snapshot.devDependencies) {
155
+ for (const [packageName, specifierAndResolution] of Object.entries(snapshot.devDependencies)) {
156
+ createDependency(LfxDependencyKind.Dev, packageName, specifierAndResolution);
157
+ }
158
+ }
159
+ }
160
+ function createProjectLockfileEntry(options) {
161
+ const { rawEntryId, duplicates, workspace } = options;
162
+ const result = {
163
+ kind: 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 LfxGraphEntry(result);
191
+ return lockfileEntry;
192
+ }
193
+ function createPackageLockfileEntry(options) {
194
+ const { rawEntryId, pnpmLockfileVersion, workspace } = options;
195
+ const result = {
196
+ kind: LfxGraphEntryKind.Package,
197
+ entryId: rawEntryId,
198
+ rawEntryId: rawEntryId,
199
+ packageJsonFolderPath: '',
200
+ entryPackageName: '',
201
+ displayText: rawEntryId,
202
+ entryPackageVersion: '',
203
+ entrySuffix: ''
204
+ };
205
+ // Example: pnpmLockfilePath = 'common/temp/my-subspace/pnpm-lock.yaml'
206
+ // Example: pnpmLockfileFolder = 'common/temp/my-subspace'
207
+ const pnpmLockfileFolder = workspace.pnpmLockfileFolder;
208
+ let slashlessRawEntryId;
209
+ if (pnpmLockfileVersion >= 90) {
210
+ // The leading slash is omitted starting in V9.0
211
+ if (rawEntryId.startsWith('/')) {
212
+ throw new Error('Not expecting leading "/" in path: ' + JSON.stringify(rawEntryId));
213
+ }
214
+ slashlessRawEntryId = rawEntryId;
215
+ }
216
+ else {
217
+ if (!rawEntryId.startsWith('/')) {
218
+ throw new Error('Expecting leading "/" in path: ' + JSON.stringify(rawEntryId));
219
+ }
220
+ slashlessRawEntryId = rawEntryId.substring(1);
221
+ }
222
+ let dotPnpmSubfolder;
223
+ if (pnpmLockfileVersion < 60) {
224
+ const lastSlashIndex = rawEntryId.lastIndexOf('/');
225
+ if (lastSlashIndex < 0) {
226
+ throw new Error('Expecting "/" in path: ' + JSON.stringify(rawEntryId));
227
+ }
228
+ const packageName = rawEntryId.substring(1, lastSlashIndex);
229
+ result.entryPackageName = packageName;
230
+ // /@rushstack/eslint-config/3.0.1_eslint@8.21.0+typescript@4.7.4
231
+ // --> @rushstack/eslint-config 3.0.1 (eslint@8.21.0+typescript@4.7.4)
232
+ const underscoreIndex = rawEntryId.indexOf('_', lastSlashIndex);
233
+ if (underscoreIndex > 0) {
234
+ const version = rawEntryId.substring(lastSlashIndex + 1, underscoreIndex);
235
+ const suffix = rawEntryId.substring(underscoreIndex + 1);
236
+ result.displayText = packageName + ' ' + version + ' (' + suffix + ')';
237
+ result.entryPackageVersion = version;
238
+ result.entrySuffix = suffix;
239
+ }
240
+ else {
241
+ // /@rushstack/eslint-config/3.0.1
242
+ // --> @rushstack/eslint-config 3.0.1
243
+ const version = rawEntryId.substring(lastSlashIndex + 1);
244
+ result.displayText = packageName + ' ' + version;
245
+ result.entryPackageVersion = version;
246
+ }
247
+ // Example: @babel+register@7.17.7_@babel+core@7.17.12
248
+ dotPnpmSubfolder =
249
+ result.entryPackageName.replace('/', '+') +
250
+ '@' +
251
+ result.entryPackageVersion +
252
+ (result.entrySuffix ? `_${result.entrySuffix}` : '');
253
+ }
254
+ else {
255
+ // Example inputs:
256
+ // @rushstack/eslint-config@3.0.1
257
+ // @rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
258
+ let versionAtSignIndex;
259
+ if (slashlessRawEntryId.startsWith('@')) {
260
+ versionAtSignIndex = slashlessRawEntryId.indexOf('@', 1);
261
+ }
262
+ else {
263
+ versionAtSignIndex = slashlessRawEntryId.indexOf('@');
264
+ }
265
+ const packageName = slashlessRawEntryId.substring(0, versionAtSignIndex);
266
+ result.entryPackageName = packageName;
267
+ const leftParenIndex = slashlessRawEntryId.indexOf('(', versionAtSignIndex);
268
+ if (leftParenIndex < 0) {
269
+ const version = slashlessRawEntryId.substring(versionAtSignIndex + 1);
270
+ result.entryPackageVersion = version;
271
+ // @rushstack/eslint-config@3.0.1
272
+ // --> @rushstack/eslint-config 3.0.1
273
+ result.displayText = packageName + ' ' + version;
274
+ }
275
+ else {
276
+ const version = slashlessRawEntryId.substring(versionAtSignIndex + 1, leftParenIndex);
277
+ result.entryPackageVersion = version;
278
+ // "(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)"
279
+ let suffix = slashlessRawEntryId.substring(leftParenIndex);
280
+ // Rewrite to:
281
+ // "@rushstack/m@1.0.0; @rushstack/n@2.0.0"
282
+ suffix = Text.replaceAll(suffix, ')(', '; ');
283
+ suffix = Text.replaceAll(suffix, '(', '');
284
+ suffix = Text.replaceAll(suffix, ')', '');
285
+ result.entrySuffix = suffix;
286
+ // @rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
287
+ // --> @rushstack/l 1.0.0 [@rushstack/m@1.0.0; @rushstack/n@2.0.0]
288
+ result.displayText = packageName + ' ' + version + ' [' + suffix + ']';
289
+ }
290
+ // Example: @rushstack/l@1.0.0(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
291
+ // --> @rushstack+l@1.0.0_@rushstack+m@1.0.0_@rushstack+n@2.0.0
292
+ // @rushstack/l 1.0.0 (@rushstack/m@1.0.0)(@rushstack/n@2.0.0)
293
+ dotPnpmSubfolder = Text.replaceAll(slashlessRawEntryId, '/', '+');
294
+ dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, ')(', '_');
295
+ dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, '(', '_');
296
+ dotPnpmSubfolder = Text.replaceAll(dotPnpmSubfolder, ')', '');
297
+ }
298
+ // Example:
299
+ // common/temp/default/node_modules/.pnpm
300
+ // /@babel+register@7.17.7_@babel+core@7.17.12
301
+ // /node_modules/@babel/register
302
+ result.packageJsonFolderPath = lockfilePath.join(pnpmLockfileFolder, `node_modules/.pnpm/` + dotPnpmSubfolder + '/node_modules/' + result.entryPackageName);
303
+ const lockfileEntry = new LfxGraphEntry(result);
304
+ return lockfileEntry;
305
+ }
306
+ /**
307
+ * Parse through the lockfile and create all the corresponding LockfileEntries and LockfileDependencies
308
+ * to construct the lockfile graph.
309
+ *
310
+ * @returns A list of all the LockfileEntries in the lockfile.
311
+ */
312
+ export function generateLockfileGraph(lockfileJson, workspace) {
313
+ const lockfile = lockfileJson;
314
+ let pnpmLockfileVersion;
315
+ switch (lockfile.lockfileVersion.toString()) {
316
+ case '5.4':
317
+ pnpmLockfileVersion = 54;
318
+ break;
319
+ case '6':
320
+ case '6.0':
321
+ pnpmLockfileVersion = 60;
322
+ break;
323
+ case '9':
324
+ case '9.0':
325
+ pnpmLockfileVersion = 90;
326
+ break;
327
+ default:
328
+ throw new Error('Unsupported PNPM lockfile version ' + JSON.stringify(lockfile.lockfileVersion));
329
+ }
330
+ const lfxGraph = new LfxGraph(workspace);
331
+ const allEntries = lfxGraph.entries;
332
+ const allEntriesById = new Map();
333
+ const allImporters = [];
334
+ // "Importers" are the local workspace projects
335
+ if (lockfile.importers) {
336
+ // Normally the UX shows the concise project folder name. However in the case of duplicates
337
+ // (where two projects use the same folder name), then we will need to disambiguate.
338
+ const baseNames = new Set();
339
+ const duplicates = new Set();
340
+ for (const importerKey of Object.keys(lockfile.importers)) {
341
+ const baseName = lockfilePath.getBaseNameOf(importerKey);
342
+ if (baseNames.has(baseName)) {
343
+ duplicates.add(baseName);
344
+ }
345
+ baseNames.add(baseName);
346
+ }
347
+ const isRushWorkspace = workspace.rushConfig !== undefined;
348
+ for (const importerKey of Object.keys(lockfile.importers)) {
349
+ if (isRushWorkspace && importerKey === '.') {
350
+ // Discard the synthetic package.json file created by Rush under common/temp
351
+ continue;
352
+ }
353
+ const importer = createProjectLockfileEntry({
354
+ rawEntryId: importerKey,
355
+ duplicates,
356
+ workspace,
357
+ pnpmLockfileVersion
358
+ });
359
+ if (pnpmLockfileVersion < 60) {
360
+ const lockfile54 = lockfileJson;
361
+ const importerValue = lockfile54.importers[importerKey];
362
+ parseProjectDependencies54({
363
+ dependencies: importer.dependencies,
364
+ lockfileEntry: importer,
365
+ mainEntry: importerValue,
366
+ pnpmLockfileVersion,
367
+ workspace
368
+ });
369
+ }
370
+ else {
371
+ const lockfile60 = lockfileJson;
372
+ if (lockfile60.importers) {
373
+ const importerValue = lockfile60.importers[importerKey];
374
+ parseProjectDependencies60(importer.dependencies, importer, importerValue, pnpmLockfileVersion, workspace);
375
+ }
376
+ }
377
+ allImporters.push(importer);
378
+ allEntries.push(importer);
379
+ allEntriesById.set(importer.entryId, importer);
380
+ }
381
+ }
382
+ if (pnpmLockfileVersion < 90) {
383
+ if (lockfile.packages) {
384
+ for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages)) {
385
+ const lockfileEntry = createPackageLockfileEntry({
386
+ rawEntryId: dependencyKey,
387
+ workspace,
388
+ pnpmLockfileVersion
389
+ });
390
+ parsePackageDependencies({
391
+ dependencies: lockfileEntry.dependencies,
392
+ lockfileEntry: lockfileEntry,
393
+ mainEntry: dependencyValue,
394
+ specifierEntry: dependencyValue,
395
+ pnpmLockfileVersion,
396
+ workspace
397
+ });
398
+ allEntries.push(lockfileEntry);
399
+ allEntriesById.set(dependencyKey, lockfileEntry);
400
+ }
401
+ }
402
+ }
403
+ else {
404
+ const packagesByKey = new Map();
405
+ if (lockfile.packages) {
406
+ for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages)) {
407
+ packagesByKey.set(dependencyKey, dependencyValue);
408
+ }
409
+ }
410
+ // In v9.0 format, the dependency graph for non-workspace packages is found under "snapshots" not "packages".
411
+ // (The "packages" section now stores other fields that are unrelated to the graph itself.)
412
+ const lockfile90 = lockfileJson;
413
+ if (lockfile90.snapshots) {
414
+ for (const [dependencyKey, dependencyValue] of Object.entries(lockfile90.snapshots)) {
415
+ const lockfileEntry = createPackageLockfileEntry({
416
+ rawEntryId: dependencyKey,
417
+ workspace,
418
+ pnpmLockfileVersion
419
+ });
420
+ // Example: "@scope/my-package@1.0.0"
421
+ const packageInfoKey = lockfileEntry.entryPackageName + '@' + lockfileEntry.entryPackageVersion;
422
+ const packageInfo = packagesByKey.get(packageInfoKey);
423
+ parsePackageDependencies({
424
+ dependencies: lockfileEntry.dependencies,
425
+ lockfileEntry,
426
+ mainEntry: dependencyValue,
427
+ specifierEntry: packageInfo,
428
+ pnpmLockfileVersion,
429
+ workspace
430
+ });
431
+ allEntries.push(lockfileEntry);
432
+ allEntriesById.set(lockfileEntry.entryId, lockfileEntry);
433
+ }
434
+ }
435
+ }
436
+ // Construct the graph
437
+ for (const entry of allEntries) {
438
+ for (const dependency of entry.dependencies) {
439
+ // Peer dependencies do not have a matching entry
440
+ if (dependency.dependencyKind === LfxDependencyKind.Peer) {
441
+ continue;
442
+ }
443
+ const matchedEntry = allEntriesById.get(dependency.entryId);
444
+ if (matchedEntry) {
445
+ // Create a two-way link between the dependency and the entry
446
+ dependency.resolvedEntry = matchedEntry;
447
+ matchedEntry.referrers.push(entry);
448
+ }
449
+ else {
450
+ if (dependency.entryId.startsWith('/')) {
451
+ // Local package
452
+ console.error('Could not resolve dependency entryId: ', dependency.entryId, dependency);
453
+ }
454
+ }
455
+ }
456
+ }
457
+ return lfxGraph;
458
+ }
459
+ //# sourceMappingURL=lfxGraphLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lfxGraphLoader.js","sourceRoot":"","sources":["../../src/graph/lfxGraphLoader.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,2DAA2D;AAK3D,OAAO,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAEpD,OAAO,EAGL,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAC;AAK/C,SAAS,+BAA+B,CAAC,OASxC;IACC,MAAM,EACJ,IAAI,EACJ,WAAW,EACX,iBAAiB,EACjB,IAAI,EAAE,cAAc,EACpB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACpB,GAAG,OAAO,CAAC;IAEZ,MAAM,MAAM,GAA+B;QACzC,IAAI;QACJ,WAAW;QACX,OAAO,EAAE,EAAE;QACX,iBAAiB;QACjB,cAAc;QACd,kBAAkB,EAAE,EAAE;QACtB,eAAe;KAChB,CAAC;IAEF,IAAI,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,YAAY,GAAW,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEnE,IAAI,eAAe,CAAC,IAAI,KAAK,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACvD,oGAAoG;YACpG,wGAAwG;YACxG,oDAAoD;YACpD,MAAM,gBAAgB,GAAW,YAAY,CAAC,WAAW,CACvD,eAAe,CAAC,qBAAqB,EACrC,YAAY,CACb,CAAC;YACF,MAAM,CAAC,OAAO,GAAG,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,yGAAyG;YACzG,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,oCAAoC;QACpC,oCAAoC;QACpC,oCAAoC;QACpC,EAAE;QACF,sDAAsD;QACtD,uDAAuD;QACvD,uDAAuD;QACvD,MAAM,gBAAgB,GAAW,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACtE,MAAM,CAAC,OAAO;YACZ,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,gBAAgB,GAAG,MAAM,CAAC,WAAW,CAAC;IAChG,CAAC;IAED,IAAI,MAAM,CAAC,cAAc,KAAK,iBAAiB,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,CAAC,kBAAkB,GAAG;YAC1B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,WAAW;YACpB,QAAQ,EAAE,CAAA,oBAAoB,aAApB,oBAAoB,uBAApB,oBAAoB,CAAG,MAAM,CAAC,IAAI,CAAC,EAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK;SACnG,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,wBAAwB,CAAC,OAajC;IACC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE3G,MAAM,IAAI,GACR,SAA8F,CAAC;IAEjG,SAAS,gBAAgB,CAAC,IAAuB,EAAE,WAAmB,EAAE,WAAmB;QACzF,IAAI,iBAAiB,GAAuB,SAAS,CAAC;QAEtD,IAAI,cAAc,IAAI,cAAc,CAAC,gBAAgB,EAAE,CAAC;YACtD,iBAAiB,GAAG,cAAc,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACjE,IAAI,iBAAiB,EAAE,CAAC;gBACtB,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC;YAChC,CAAC;QACH,CAAC;QAED,YAAY,CAAC,IAAI,CACf,+BAA+B,CAAC;YAC9B,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,WAAW;YACX,iBAAiB,EAAE,iBAAiB,aAAjB,iBAAiB,cAAjB,iBAAiB,GAAI,EAAE;YAC1C,eAAe,EAAE,aAAa;YAC9B,oBAAoB,EAAE,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAE,oBAAoB;YAC1D,mBAAmB;YACnB,SAAS;SACV,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3E,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACnF,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YAC9E,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,0BAA0B,EAAE,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,0BAA0B,EAAE,CAAC;YAClD,aAAa,CAAC,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,OASnC;IACC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE3F,MAAM,IAAI,GACR,SAA8F,CAAC;IAEjG,SAAS,gBAAgB,CAAC,IAAuB,EAAE,WAAmB,EAAE,WAAmB;QACzF,IAAI,iBAAiB,GAAuB,SAAS,CAAC;QAEtD,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACzB,iBAAiB,GAAG,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACxD,CAAC;QAED,YAAY,CAAC,IAAI,CACf,+BAA+B,CAAC;YAC9B,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,WAAW;YACX,iBAAiB,EAAE,iBAAiB,aAAjB,iBAAiB,cAAjB,iBAAiB,GAAI,EAAE;YAC1C,eAAe,EAAE,aAAa;YAC9B,mBAAmB;YACnB,SAAS;SACV,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC3E,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACnF,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YAC9E,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CACjC,YAAkC,EAClC,aAA4B,EAC5B,QAAmD,EACnD,mBAAwC,EACxC,SAA4B;IAE5B,SAAS,gBAAgB,CACvB,IAAuB,EACvB,WAAmB,EACnB,sBAA4D;QAE5D,YAAY,CAAC,IAAI,CACf,+BAA+B,CAAC;YAC9B,IAAI;YACJ,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,sBAAsB,CAAC,OAAO;YAC3C,iBAAiB,EAAE,sBAAsB,CAAC,SAAS;YACnD,eAAe,EAAE,aAAa;YAC9B,mBAAmB;YACnB,SAAS;SACV,CAAC,CACH,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC1B,KAAK,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1F,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,sBAAsB,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,oBAAoB,EAAE,CAAC;QAClC,KAAK,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAClG,gBAAgB,CAAC,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,sBAAsB,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YAC7F,gBAAgB,CAAC,iBAAiB,CAAC,GAAG,EAAE,WAAW,EAAE,sBAAsB,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,OAKnC;IACC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAEtD,MAAM,MAAM,GAA0B;QACpC,IAAI,EAAE,iBAAiB,CAAC,OAAO;QAC/B,OAAO,EAAE,EAAE;QACX,UAAU,EAAE,EAAE;QACd,qBAAqB,EAAE,EAAE;QACzB,gBAAgB,EAAE,EAAE;QACpB,WAAW,EAAE,EAAE;QACf,mBAAmB,EAAE,EAAE;QACvB,WAAW,EAAE,EAAE;KAChB,CAAC;IAEF,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;IAE/B,yEAAyE;IACzE,0DAA0D;IAC1D,MAAM,kBAAkB,GAAW,SAAS,CAAC,kBAAkB,CAAC;IAEhE,8CAA8C;IAC9C,gDAAgD;IAChD,MAAM,CAAC,qBAAqB,GAAG,YAAY,CAAC,WAAW,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;IACxF,MAAM,CAAC,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC,qBAAqB,CAAC;IAE3D,MAAM,iBAAiB,GAAW,YAAY,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAEzE,IAAI,CAAC,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,GAAG,CAAC,iBAAiB,CAAC,CAAA,EAAE,CAAC;QACxC,yEAAyE;QACzE,oDAAoD;QACpD,MAAM,CAAC,gBAAgB,GAAG,iBAAiB,CAAC;IAC9C,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,gBAAgB,GAAG,GAAG,iBAAiB,KAAK,MAAM,CAAC,qBAAqB,GAAG,CAAC;IACrF,CAAC;IACD,MAAM,CAAC,WAAW,GAAG,YAAY,MAAM,CAAC,gBAAgB,EAAE,CAAC;IAE3D,MAAM,aAAa,GAAkB,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,0BAA0B,CAAC,OAInC;IACC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAE/D,MAAM,MAAM,GAA0B;QACpC,IAAI,EAAE,iBAAiB,CAAC,OAAO;QAC/B,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,UAAU;QACtB,qBAAqB,EAAE,EAAE;QACzB,gBAAgB,EAAE,EAAE;QACpB,WAAW,EAAE,UAAU;QACvB,mBAAmB,EAAE,EAAE;QACvB,WAAW,EAAE,EAAE;KAChB,CAAC;IAEF,yEAAyE;IACzE,0DAA0D;IAC1D,MAAM,kBAAkB,GAAW,SAAS,CAAC,kBAAkB,CAAC;IAEhE,IAAI,mBAA2B,CAAC;IAEhC,IAAI,mBAAmB,IAAI,EAAE,EAAE,CAAC;QAC9B,gDAAgD;QAChD,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QACtF,CAAC;QACD,mBAAmB,GAAG,UAAU,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,iCAAiC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QAClF,CAAC;QACD,mBAAmB,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,gBAAwB,CAAC;IAE7B,IAAI,mBAAmB,GAAG,EAAE,EAAE,CAAC;QAC7B,MAAM,cAAc,GAAW,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,WAAW,GAAW,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACpE,MAAM,CAAC,gBAAgB,GAAG,WAAW,CAAC;QAEtC,uEAAuE;QACvE,wEAAwE;QACxE,MAAM,eAAe,GAAW,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACxE,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,OAAO,GAAW,UAAU,CAAC,SAAS,CAAC,cAAc,GAAG,CAAC,EAAE,eAAe,CAAC,CAAC;YAClF,MAAM,MAAM,GAAW,UAAU,CAAC,SAAS,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;YACjE,MAAM,CAAC,WAAW,GAAG,WAAW,GAAG,GAAG,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;YACvE,MAAM,CAAC,mBAAmB,GAAG,OAAO,CAAC;YACrC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,wCAAwC;YACxC,uCAAuC;YACvC,MAAM,OAAO,GAAW,UAAU,CAAC,SAAS,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;YACjE,MAAM,CAAC,WAAW,GAAG,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC;YACjD,MAAM,CAAC,mBAAmB,GAAG,OAAO,CAAC;QACvC,CAAC;QAED,sDAAsD;QACtD,gBAAgB;YACd,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;gBACzC,GAAG;gBACH,MAAM,CAAC,mBAAmB;gBAC1B,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;SAAM,CAAC;QACN,kBAAkB;QAClB,uCAAuC;QACvC,mEAAmE;QACnE,IAAI,kBAA0B,CAAC;QAC/B,IAAI,mBAAmB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxC,kBAAkB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;aAAM,CAAC;YACN,kBAAkB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,WAAW,GAAW,mBAAmB,CAAC,SAAS,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACjF,MAAM,CAAC,gBAAgB,GAAG,WAAW,CAAC;QAEtC,MAAM,cAAc,GAAW,mBAAmB,CAAC,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;QACpF,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,OAAO,GAAW,mBAAmB,CAAC,SAAS,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC;YAC9E,MAAM,CAAC,mBAAmB,GAAG,OAAO,CAAC;YAErC,uCAAuC;YACvC,uCAAuC;YACvC,MAAM,CAAC,WAAW,GAAG,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAW,mBAAmB,CAAC,SAAS,CAAC,kBAAkB,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;YAC9F,MAAM,CAAC,mBAAmB,GAAG,OAAO,CAAC;YAErC,6CAA6C;YAC7C,IAAI,MAAM,GAAW,mBAAmB,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;YAEnE,cAAc;YACd,2CAA2C;YAC3C,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC7C,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1C,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC;YAE5B,mEAAmE;YACnE,oEAAoE;YACpE,MAAM,CAAC,WAAW,GAAG,WAAW,GAAG,GAAG,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;QACzE,CAAC;QAED,uEAAuE;QACvE,qEAAqE;QAErE,8DAA8D;QAC9D,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAClE,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAChE,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC/D,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,WAAW;IACX,2CAA2C;IAC3C,kDAAkD;IAClD,oCAAoC;IACpC,MAAM,CAAC,qBAAqB,GAAG,YAAY,CAAC,IAAI,CAC9C,kBAAkB,EAClB,qBAAqB,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CACtF,CAAC;IAEF,MAAM,aAAa,GAAkB,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAqB,EAAE,SAA4B;IACvF,MAAM,QAAQ,GAA8D,YAE9C,CAAC;IAE/B,IAAI,mBAAwC,CAAC;IAC7C,QAAQ,QAAQ,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC5C,KAAK,KAAK;YACR,mBAAmB,GAAG,EAAE,CAAC;YACzB,MAAM;QACR,KAAK,GAAG,CAAC;QACT,KAAK,KAAK;YACR,mBAAmB,GAAG,EAAE,CAAC;YACzB,MAAM;QACR,KAAK,GAAG,CAAC;QACT,KAAK,KAAK;YACR,mBAAmB,GAAG,EAAE,CAAC;YACzB,MAAM;QACR;YACE,MAAM,IAAI,KAAK,CAAC,oCAAoC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,QAAQ,GAAa,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,UAAU,GAAoB,QAAQ,CAAC,OAAO,CAAC;IACrD,MAAM,cAAc,GAA+B,IAAI,GAAG,EAAE,CAAC;IAE7D,MAAM,YAAY,GAAoB,EAAE,CAAC;IAEzC,+CAA+C;IAC/C,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QACvB,4FAA4F;QAC5F,oFAAoF;QACpF,MAAM,SAAS,GAAgB,IAAI,GAAG,EAAE,CAAC;QACzC,MAAM,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;QAC1C,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1D,MAAM,QAAQ,GAAW,YAAY,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;YACjE,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC3B,CAAC;YACD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QAED,MAAM,eAAe,GAAY,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC;QAEpE,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1D,IAAI,eAAe,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;gBAC3C,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAkB,0BAA0B,CAAC;gBACzD,UAAU,EAAE,WAAW;gBACvB,UAAU;gBACV,SAAS;gBACT,mBAAmB;aACpB,CAAC,CAAC;YAEH,IAAI,mBAAmB,GAAG,EAAE,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAiC,YAA4C,CAAC;gBAC9F,MAAM,aAAa,GACjB,UAAU,CAAC,SAAS,CAAC,WAAkC,CAAC,CAAC;gBAE3D,0BAA0B,CAAC;oBACzB,YAAY,EAAE,QAAQ,CAAC,YAAY;oBACnC,aAAa,EAAE,QAAQ;oBACvB,SAAS,EAAE,aAAa;oBACxB,mBAAmB;oBACnB,SAAS;iBACV,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,UAAU,GAA+B,YAA0C,CAAC;gBAC1F,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;oBACzB,MAAM,aAAa,GACjB,UAAU,CAAC,SAAS,CAAC,WAAkC,CAAC,CAAC;oBAC3D,0BAA0B,CACxB,QAAQ,CAAC,YAAY,EACrB,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,SAAS,CACV,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5B,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC1B,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,IAAI,mBAAmB,GAAG,EAAE,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjF,MAAM,aAAa,GAAkB,0BAA0B,CAAC;oBAC9D,UAAU,EAAE,aAAa;oBACzB,SAAS;oBACT,mBAAmB;iBACpB,CAAC,CAAC;gBACH,wBAAwB,CAAC;oBACvB,YAAY,EAAE,aAAa,CAAC,YAAY;oBACxC,aAAa,EAAE,aAAa;oBAC5B,SAAS,EAAE,eAAe;oBAC1B,cAAc,EAAE,eAAe;oBAC/B,mBAAmB;oBACnB,SAAS;iBACV,CAAC,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC/B,cAAc,CAAC,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAmD,IAAI,GAAG,EAAE,CAAC;QAChF,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,KAAK,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACjF,aAAa,CAAC,GAAG,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,6GAA6G;QAC7G,2FAA2F;QAC3F,MAAM,UAAU,GAA+B,YAA0C,CAAC;QAC1F,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;YACzB,KAAK,MAAM,CAAC,aAAa,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACpF,MAAM,aAAa,GAAkB,0BAA0B,CAAC;oBAC9D,UAAU,EAAE,aAAa;oBACzB,SAAS;oBACT,mBAAmB;iBACpB,CAAC,CAAC;gBAEH,qCAAqC;gBACrC,MAAM,cAAc,GAClB,aAAa,CAAC,gBAAgB,GAAG,GAAG,GAAG,aAAa,CAAC,mBAAmB,CAAC;gBAC3E,MAAM,WAAW,GAAkD,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAErG,wBAAwB,CAAC;oBACvB,YAAY,EAAE,aAAa,CAAC,YAAY;oBACxC,aAAa;oBACb,SAAS,EAAE,eAAe;oBAC1B,cAAc,EAAE,WAAW;oBAC3B,mBAAmB;oBACnB,SAAS;iBACV,CAAC,CAAC;gBAEH,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAC/B,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC5C,iDAAiD;YACjD,IAAI,UAAU,CAAC,cAAc,KAAK,iBAAiB,CAAC,IAAI,EAAE,CAAC;gBACzD,SAAS;YACX,CAAC;YAED,MAAM,YAAY,GAA8B,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACvF,IAAI,YAAY,EAAE,CAAC;gBACjB,6DAA6D;gBAC7D,UAAU,CAAC,aAAa,GAAG,YAAY,CAAC;gBACxC,YAAY,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,IAAI,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvC,gBAAgB;oBAChB,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;gBAC1F,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","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';\n\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 versionPath: string;\n originalSpecifier: string;\n kind: LfxDependencyKind;\n containingEntry: LfxGraphEntry;\n peerDependenciesMeta?: PeerDependenciesMeta;\n pnpmLockfileVersion: PnpmLockfileVersion;\n workspace: IJsonLfxWorkspace;\n}): LfxGraphDependency {\n const {\n name,\n versionPath,\n originalSpecifier,\n kind: dependencyKind,\n containingEntry,\n peerDependenciesMeta,\n pnpmLockfileVersion\n } = options;\n\n const result: ILfxGraphDependencyOptions = {\n name,\n versionPath,\n entryId: '',\n originalSpecifier,\n dependencyKind,\n peerDependencyMeta: {},\n containingEntry\n };\n\n if (versionPath.startsWith('link:')) {\n const relativePath: string = versionPath.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.versionPath.startsWith('/')) {\n result.entryId = versionPath;\n } else {\n // Version 5.4: /@rushstack/m/1.0.0:\n // Version 6.0: /@rushstack/m@1.0.0:\n // Version 9.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 // Version 9.0: @rushstack/j@1.0.0(@rushstack/n@2.0.0)\n const versionDelimiter: string = pnpmLockfileVersion < 60 ? '/' : '@';\n result.entryId =\n (pnpmLockfileVersion < 90 ? '/' : '') + result.name + versionDelimiter + result.versionPath;\n }\n\n if (result.dependencyKind === LfxDependencyKind.Peer) {\n result.peerDependencyMeta = {\n name: result.name,\n version: versionPath,\n optional: peerDependenciesMeta?.[result.name] ? peerDependenciesMeta[result.name].optional : false\n };\n }\n return new LfxGraphDependency(result);\n}\n\nfunction parsePackageDependencies(options: {\n dependencies: LfxGraphDependency[];\n lockfileEntry: LfxGraphEntry;\n /**\n * Used to obtain versionPath exact references.\n */\n mainEntry: lockfileTypes.LockfilePackageSnapshot;\n /**\n * Used to obtain informational version ranges.\n */\n specifierEntry: lockfileTypes.LockfilePackageInfo | undefined;\n pnpmLockfileVersion: PnpmLockfileVersion;\n workspace: IJsonLfxWorkspace;\n}): void {\n const { dependencies, lockfileEntry, mainEntry, specifierEntry, pnpmLockfileVersion, workspace } = options;\n\n const node: Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot> =\n mainEntry as unknown as Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot>;\n\n function createDependency(kind: LfxDependencyKind, packageName: string, versionPath: string): void {\n let originalSpecifier: string | undefined = undefined;\n\n if (specifierEntry && specifierEntry.peerDependencies) {\n originalSpecifier = specifierEntry.peerDependencies[packageName];\n if (originalSpecifier) {\n kind = LfxDependencyKind.Peer;\n }\n }\n\n dependencies.push(\n createPackageLockfileDependency({\n kind,\n name: packageName,\n versionPath,\n originalSpecifier: originalSpecifier ?? '',\n containingEntry: lockfileEntry,\n peerDependenciesMeta: specifierEntry?.peerDependenciesMeta,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n\n if (node.dependencies) {\n for (const [packageName, versionPath] of Object.entries(node.dependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, versionPath);\n }\n }\n if (node.optionalDependencies) {\n for (const [packageName, versionPath] of Object.entries(node.optionalDependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, versionPath);\n }\n }\n if (node.devDependencies) {\n for (const [packageName, versionPath] of Object.entries(node.devDependencies)) {\n createDependency(LfxDependencyKind.Dev, packageName, versionPath);\n }\n }\n\n if (node.transitivePeerDependencies) {\n for (const dep of node.transitivePeerDependencies) {\n lockfileEntry.transitivePeerDependencies.add(dep);\n }\n }\n}\n\nfunction parseProjectDependencies54(options: {\n dependencies: LfxGraphDependency[];\n lockfileEntry: LfxGraphEntry;\n /**\n * Used to obtain versionPath exact references and informational version ranges\n */\n mainEntry: lockfileTypes.ProjectSnapshot;\n pnpmLockfileVersion: PnpmLockfileVersion;\n workspace: IJsonLfxWorkspace;\n}): void {\n const { dependencies, lockfileEntry, mainEntry, pnpmLockfileVersion, workspace } = options;\n\n const node: Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot> =\n mainEntry as unknown as Partial<lockfileTypes.ProjectSnapshot & lockfileTypes.PackageSnapshot>;\n\n function createDependency(kind: LfxDependencyKind, packageName: string, versionPath: string): void {\n let originalSpecifier: string | undefined = undefined;\n\n if (mainEntry.specifiers) {\n originalSpecifier = mainEntry.specifiers[packageName];\n }\n\n dependencies.push(\n createPackageLockfileDependency({\n kind,\n name: packageName,\n versionPath,\n originalSpecifier: originalSpecifier ?? '',\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n\n if (node.dependencies) {\n for (const [packageName, versionPath] of Object.entries(node.dependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, versionPath);\n }\n }\n if (node.optionalDependencies) {\n for (const [packageName, versionPath] of Object.entries(node.optionalDependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, versionPath);\n }\n }\n if (node.devDependencies) {\n for (const [packageName, versionPath] of Object.entries(node.devDependencies)) {\n createDependency(LfxDependencyKind.Dev, packageName, versionPath);\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 function createDependency(\n kind: LfxDependencyKind,\n packageName: string,\n specifierAndResolution: lockfileTypes.SpecifierAndResolution\n ): void {\n dependencies.push(\n createPackageLockfileDependency({\n kind,\n name: packageName,\n versionPath: specifierAndResolution.version,\n originalSpecifier: specifierAndResolution.specifier,\n containingEntry: lockfileEntry,\n pnpmLockfileVersion,\n workspace\n })\n );\n }\n\n if (snapshot.dependencies) {\n for (const [packageName, specifierAndResolution] of Object.entries(snapshot.dependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, specifierAndResolution);\n }\n }\n if (snapshot.optionalDependencies) {\n for (const [packageName, specifierAndResolution] of Object.entries(snapshot.optionalDependencies)) {\n createDependency(LfxDependencyKind.Regular, packageName, specifierAndResolution);\n }\n }\n if (snapshot.devDependencies) {\n for (const [packageName, specifierAndResolution] of Object.entries(snapshot.devDependencies)) {\n createDependency(LfxDependencyKind.Dev, packageName, specifierAndResolution);\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 workspace: IJsonLfxWorkspace;\n pnpmLockfileVersion: PnpmLockfileVersion;\n}): LfxGraphEntry {\n const { rawEntryId, pnpmLockfileVersion, workspace } = options;\n\n const result: ILfxGraphEntryOptions = {\n kind: LfxGraphEntryKind.Package,\n entryId: rawEntryId,\n rawEntryId: rawEntryId,\n packageJsonFolderPath: '',\n entryPackageName: '',\n displayText: rawEntryId,\n entryPackageVersion: '',\n entrySuffix: ''\n };\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 let slashlessRawEntryId: string;\n\n if (pnpmLockfileVersion >= 90) {\n // The leading slash is omitted starting in V9.0\n if (rawEntryId.startsWith('/')) {\n throw new Error('Not expecting leading \"/\" in path: ' + JSON.stringify(rawEntryId));\n }\n slashlessRawEntryId = rawEntryId;\n } else {\n if (!rawEntryId.startsWith('/')) {\n throw new Error('Expecting leading \"/\" in path: ' + JSON.stringify(rawEntryId));\n }\n slashlessRawEntryId = rawEntryId.substring(1);\n }\n\n let dotPnpmSubfolder: string;\n\n if (pnpmLockfileVersion < 60) {\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 (slashlessRawEntryId.startsWith('@')) {\n versionAtSignIndex = slashlessRawEntryId.indexOf('@', 1);\n } else {\n versionAtSignIndex = slashlessRawEntryId.indexOf('@');\n }\n\n const packageName: string = slashlessRawEntryId.substring(0, versionAtSignIndex);\n result.entryPackageName = packageName;\n\n const leftParenIndex: number = slashlessRawEntryId.indexOf('(', versionAtSignIndex);\n if (leftParenIndex < 0) {\n const version: string = slashlessRawEntryId.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 = slashlessRawEntryId.substring(versionAtSignIndex + 1, leftParenIndex);\n result.entryPackageVersion = version;\n\n // \"(@rushstack/m@1.0.0)(@rushstack/n@2.0.0)\"\n let suffix: string = slashlessRawEntryId.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 = Text.replaceAll(slashlessRawEntryId, '/', '+');\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 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 < 60) {\n const lockfile54: lockfileTypes.LockfileObject = lockfileJson as lockfileTypes.LockfileObject;\n const importerValue: lockfileTypes.ProjectSnapshot =\n lockfile54.importers[importerKey as pnpmTypes.ProjectId];\n\n parseProjectDependencies54({\n dependencies: importer.dependencies,\n lockfileEntry: importer,\n mainEntry: 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 if (pnpmLockfileVersion < 90) {\n if (lockfile.packages) {\n for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages)) {\n const lockfileEntry: LfxGraphEntry = createPackageLockfileEntry({\n rawEntryId: dependencyKey,\n workspace,\n pnpmLockfileVersion\n });\n parsePackageDependencies({\n dependencies: lockfileEntry.dependencies,\n lockfileEntry: lockfileEntry,\n mainEntry: dependencyValue,\n specifierEntry: dependencyValue,\n pnpmLockfileVersion,\n workspace\n });\n allEntries.push(lockfileEntry);\n allEntriesById.set(dependencyKey, lockfileEntry);\n }\n }\n } else {\n const packagesByKey: Map<string, lockfileTypes.LockfilePackageInfo> = new Map();\n if (lockfile.packages) {\n for (const [dependencyKey, dependencyValue] of Object.entries(lockfile.packages)) {\n packagesByKey.set(dependencyKey, dependencyValue);\n }\n }\n\n // In v9.0 format, the dependency graph for non-workspace packages is found under \"snapshots\" not \"packages\".\n // (The \"packages\" section now stores other fields that are unrelated to the graph itself.)\n const lockfile90: lockfileTypes.LockfileFile = lockfileJson as lockfileTypes.LockfileFile;\n if (lockfile90.snapshots) {\n for (const [dependencyKey, dependencyValue] of Object.entries(lockfile90.snapshots)) {\n const lockfileEntry: LfxGraphEntry = createPackageLockfileEntry({\n rawEntryId: dependencyKey,\n workspace,\n pnpmLockfileVersion\n });\n\n // Example: \"@scope/my-package@1.0.0\"\n const packageInfoKey: string =\n lockfileEntry.entryPackageName + '@' + lockfileEntry.entryPackageVersion;\n const packageInfo: lockfileTypes.LockfilePackageInfo | undefined = packagesByKey.get(packageInfoKey);\n\n parsePackageDependencies({\n dependencies: lockfileEntry.dependencies,\n lockfileEntry,\n mainEntry: dependencyValue,\n specifierEntry: packageInfo,\n pnpmLockfileVersion,\n workspace\n });\n\n allEntries.push(lockfileEntry);\n allEntriesById.set(lockfileEntry.entryId, lockfileEntry);\n }\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.dependencyKind === 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"]}
@@ -0,0 +1,117 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+ /**
4
+ * For example, retrieves `d` from `/a/b/c/d`.
5
+ */
6
+ export function getBaseNameOf(importerPath) {
7
+ if (importerPath.length === 0) {
8
+ return '';
9
+ }
10
+ const index = importerPath.lastIndexOf('/');
11
+ if (index === importerPath.length - 1) {
12
+ throw new Error('Error: Path has a trailing slash');
13
+ }
14
+ if (index >= 0) {
15
+ return importerPath.substring(index + 1);
16
+ }
17
+ return importerPath;
18
+ }
19
+ /**
20
+ * For example, retrieves `/a/b/c` from `/a/b/c/d`.
21
+ */
22
+ export function getParentOf(importerPath) {
23
+ if (importerPath === '' || importerPath === '.' || importerPath === '/') {
24
+ throw new Error('Error: Path has no parent');
25
+ }
26
+ const index = importerPath.lastIndexOf('/');
27
+ if (index === importerPath.length - 1) {
28
+ throw new Error('Error: Path has a trailing slash');
29
+ }
30
+ if (index === 0) {
31
+ return '/';
32
+ }
33
+ if (index < 0) {
34
+ return '.';
35
+ }
36
+ return importerPath.substring(0, index);
37
+ }
38
+ /**
39
+ * Cheaply resolves a relative path against a base path, assuming the paths are delimited by `/`,
40
+ * and assuming the basePath is already in normal form. An error occurs if the relative path
41
+ * goes above the root folder.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * getAbsolutePath(`a/b/c`, `d/e`) === `a/b/c/d/e`
46
+ * getAbsolutePath(`/a/b/c`, `d/e`) === `/a/b/c/d/e`
47
+ * getAbsolutePath(`/a/b/c`, `/d/e`) === `/d/e`
48
+ * getAbsolutePath(`a/b/c`, `../../f`) === `a/f`
49
+ * getAbsolutePath(`a/b/c`, `.././/f`) === `a/b/f`
50
+ * getAbsolutePath(`a/b/c`, `../../..`) === `.`
51
+ * getAbsolutePath(`C:/a/b`, `../d`) === `C:/a/d`
52
+ * getAbsolutePath(`a/b/c`, `../../../..`) === ERROR
53
+ *
54
+ * // Degenerate cases:
55
+ * getAbsolutePath(`a/b/c/`, `d/`) === `a/b/c/d` // trailing slashes are discarded
56
+ * getAbsolutePath(`./../c`, `d`) === `./../c/d` // basePath assumed to be normal form
57
+ * getAbsolutePath(`C:\\`, `\\a`) === `C:\\/\\a` // backslashes not supported
58
+ * ```
59
+ */
60
+ export function getAbsolute(basePath, relativePath) {
61
+ let leadingSlash;
62
+ let stack;
63
+ // Discard intermediary slashes
64
+ const relativeParts = relativePath.split('/').filter((part) => part.length > 0);
65
+ if (relativePath.startsWith('/')) {
66
+ stack = [];
67
+ leadingSlash = true;
68
+ }
69
+ else {
70
+ // Discard intermediary slashes
71
+ stack = basePath.split('/').filter((part) => part.length > 0);
72
+ leadingSlash = basePath.startsWith('/');
73
+ }
74
+ for (const part of relativeParts) {
75
+ if (part === '.') {
76
+ // current directory, do nothing
77
+ continue;
78
+ }
79
+ else if (part === '..') {
80
+ if (stack.length === 0) {
81
+ throw new Error('getAbsolutePath(): relativePath goes above the root folder');
82
+ }
83
+ stack.pop();
84
+ }
85
+ else {
86
+ stack.push(part);
87
+ }
88
+ }
89
+ if (leadingSlash) {
90
+ return '/' + stack.join('/');
91
+ }
92
+ else {
93
+ return stack.length === 0 ? '.' : stack.join('/');
94
+ }
95
+ }
96
+ /**
97
+ * Returns the two parts joined by exactly one `/`, assuming the parts are already
98
+ * in normalized form. The `/` is not added if either part is an empty string.
99
+ */
100
+ export function join(leftPart, rightPart) {
101
+ if (leftPart.length === 0) {
102
+ return rightPart;
103
+ }
104
+ if (rightPart.length === 0) {
105
+ return leftPart;
106
+ }
107
+ const leftEndsWithSlash = leftPart[leftPart.length - 1] === '/';
108
+ const rightStartsWithSlash = rightPart[0] === '/';
109
+ if (leftEndsWithSlash && rightStartsWithSlash) {
110
+ return leftPart + rightPart.substring(1);
111
+ }
112
+ if (leftEndsWithSlash || rightStartsWithSlash) {
113
+ return leftPart + rightPart;
114
+ }
115
+ return leftPart + '/' + rightPart;
116
+ }
117
+ //# sourceMappingURL=lockfilePath.js.map