dependabot-bun 0.296.2 → 0.296.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/.eslintrc +11 -0
  3. data/helpers/README.md +29 -0
  4. data/helpers/build +26 -0
  5. data/helpers/jest.config.js +5 -0
  6. data/helpers/lib/npm/conflicting-dependency-parser.js +78 -0
  7. data/helpers/lib/npm/index.js +9 -0
  8. data/helpers/lib/npm/vulnerability-auditor.js +291 -0
  9. data/helpers/lib/npm6/helpers.js +25 -0
  10. data/helpers/lib/npm6/index.js +9 -0
  11. data/helpers/lib/npm6/peer-dependency-checker.js +111 -0
  12. data/helpers/lib/npm6/remove-dependencies-from-lockfile.js +22 -0
  13. data/helpers/lib/npm6/subdependency-updater.js +78 -0
  14. data/helpers/lib/npm6/updater.js +199 -0
  15. data/helpers/lib/pnpm/index.js +5 -0
  16. data/helpers/lib/pnpm/lockfile-parser.js +82 -0
  17. data/helpers/lib/yarn/conflicting-dependency-parser.js +176 -0
  18. data/helpers/lib/yarn/fix-duplicates.js +80 -0
  19. data/helpers/lib/yarn/helpers.js +54 -0
  20. data/helpers/lib/yarn/index.js +14 -0
  21. data/helpers/lib/yarn/lockfile-parser.js +21 -0
  22. data/helpers/lib/yarn/peer-dependency-checker.js +132 -0
  23. data/helpers/lib/yarn/replace-lockfile-declaration.js +57 -0
  24. data/helpers/lib/yarn/subdependency-updater.js +83 -0
  25. data/helpers/lib/yarn/updater.js +209 -0
  26. data/helpers/package-lock.json +28519 -0
  27. data/helpers/package.json +29 -0
  28. data/helpers/patches/npm++pacote+9.5.12.patch +14 -0
  29. data/helpers/run.js +30 -0
  30. data/helpers/test/npm6/conflicting-dependency-parser.test.js +66 -0
  31. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package-lock.json +591 -0
  32. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
  33. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package-lock.json +188 -0
  34. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
  35. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package-lock.json +27 -0
  36. data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
  37. data/helpers/test/npm6/fixtures/updater/original/package-lock.json +16 -0
  38. data/helpers/test/npm6/fixtures/updater/original/package.json +9 -0
  39. data/helpers/test/npm6/fixtures/updater/updated/package-lock.json +16 -0
  40. data/helpers/test/npm6/helpers.js +21 -0
  41. data/helpers/test/npm6/updater.test.js +30 -0
  42. data/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml +72 -0
  43. data/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml +2744 -0
  44. data/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml +16 -0
  45. data/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml +855 -0
  46. data/helpers/test/pnpm/lockfile-parser.test.js +62 -0
  47. data/helpers/test/yarn/conflicting-dependency-parser.test.js +83 -0
  48. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
  49. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/yarn.lock +496 -0
  50. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/package.json +14 -0
  51. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/yarn.lock +21 -0
  52. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
  53. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/yarn.lock +183 -0
  54. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
  55. data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/yarn.lock +21 -0
  56. data/helpers/test/yarn/fixtures/updater/illegal_character/package.json +8 -0
  57. data/helpers/test/yarn/fixtures/updater/illegal_character/yarn.lock +14 -0
  58. data/helpers/test/yarn/fixtures/updater/original/package.json +6 -0
  59. data/helpers/test/yarn/fixtures/updater/original/yarn.lock +11 -0
  60. data/helpers/test/yarn/fixtures/updater/updated/yarn.lock +12 -0
  61. data/helpers/test/yarn/fixtures/updater/with-version-comments/package.json +5 -0
  62. data/helpers/test/yarn/fixtures/updater/with-version-comments/yarn.lock +13 -0
  63. data/helpers/test/yarn/helpers.js +18 -0
  64. data/helpers/test/yarn/updater.test.js +117 -0
  65. data/lib/dependabot/bun/bun_package_manager.rb +47 -0
  66. data/lib/dependabot/bun/constraint_helper.rb +359 -0
  67. data/lib/dependabot/bun/dependency_files_filterer.rb +157 -0
  68. data/lib/dependabot/bun/file_fetcher/path_dependency_builder.rb +184 -0
  69. data/lib/dependabot/bun/file_fetcher.rb +402 -0
  70. data/lib/dependabot/bun/file_parser/bun_lock.rb +140 -0
  71. data/lib/dependabot/bun/file_parser/lockfile_parser.rb +105 -0
  72. data/lib/dependabot/bun/file_parser.rb +477 -0
  73. data/lib/dependabot/bun/file_updater/bun_lockfile_updater.rb +144 -0
  74. data/lib/dependabot/bun/file_updater/npmrc_builder.rb +256 -0
  75. data/lib/dependabot/bun/file_updater/package_json_preparer.rb +88 -0
  76. data/lib/dependabot/bun/file_updater/package_json_updater.rb +378 -0
  77. data/lib/dependabot/bun/file_updater.rb +203 -0
  78. data/lib/dependabot/bun/helpers.rb +93 -0
  79. data/lib/dependabot/bun/language.rb +45 -0
  80. data/lib/dependabot/bun/metadata_finder.rb +214 -0
  81. data/lib/dependabot/bun/native_helpers.rb +19 -0
  82. data/lib/dependabot/bun/package_manager.rb +280 -0
  83. data/lib/dependabot/bun/package_name.rb +118 -0
  84. data/lib/dependabot/bun/pnpm_package_manager.rb +55 -0
  85. data/lib/dependabot/bun/registry_helper.rb +188 -0
  86. data/lib/dependabot/bun/registry_parser.rb +93 -0
  87. data/lib/dependabot/bun/requirement.rb +146 -0
  88. data/lib/dependabot/bun/sub_dependency_files_filterer.rb +82 -0
  89. data/lib/dependabot/bun/update_checker/conflicting_dependency_resolver.rb +59 -0
  90. data/lib/dependabot/bun/update_checker/dependency_files_builder.rb +79 -0
  91. data/lib/dependabot/bun/update_checker/latest_version_finder.rb +448 -0
  92. data/lib/dependabot/bun/update_checker/library_detector.rb +76 -0
  93. data/lib/dependabot/bun/update_checker/registry_finder.rb +279 -0
  94. data/lib/dependabot/bun/update_checker/requirements_updater.rb +206 -0
  95. data/lib/dependabot/bun/update_checker/subdependency_version_resolver.rb +154 -0
  96. data/lib/dependabot/bun/update_checker/version_resolver.rb +583 -0
  97. data/lib/dependabot/bun/update_checker/vulnerability_auditor.rb +164 -0
  98. data/lib/dependabot/bun/update_checker.rb +455 -0
  99. data/lib/dependabot/bun/version.rb +138 -0
  100. data/lib/dependabot/bun/version_selector.rb +61 -0
  101. data/lib/dependabot/bun.rb +337 -35
  102. metadata +108 -65
  103. data/lib/dependabot/javascript/bun/file_fetcher.rb +0 -77
  104. data/lib/dependabot/javascript/bun/file_parser/bun_lock.rb +0 -156
  105. data/lib/dependabot/javascript/bun/file_parser/lockfile_parser.rb +0 -55
  106. data/lib/dependabot/javascript/bun/file_parser.rb +0 -74
  107. data/lib/dependabot/javascript/bun/file_updater/lockfile_updater.rb +0 -138
  108. data/lib/dependabot/javascript/bun/file_updater.rb +0 -75
  109. data/lib/dependabot/javascript/bun/helpers.rb +0 -72
  110. data/lib/dependabot/javascript/bun/package_manager.rb +0 -48
  111. data/lib/dependabot/javascript/bun/requirement.rb +0 -11
  112. data/lib/dependabot/javascript/bun/update_checker/conflicting_dependency_resolver.rb +0 -64
  113. data/lib/dependabot/javascript/bun/update_checker/dependency_files_builder.rb +0 -47
  114. data/lib/dependabot/javascript/bun/update_checker/latest_version_finder.rb +0 -450
  115. data/lib/dependabot/javascript/bun/update_checker/library_detector.rb +0 -76
  116. data/lib/dependabot/javascript/bun/update_checker/requirements_updater.rb +0 -203
  117. data/lib/dependabot/javascript/bun/update_checker/subdependency_version_resolver.rb +0 -144
  118. data/lib/dependabot/javascript/bun/update_checker/version_resolver.rb +0 -525
  119. data/lib/dependabot/javascript/bun/update_checker/vulnerability_auditor.rb +0 -165
  120. data/lib/dependabot/javascript/bun/update_checker.rb +0 -440
  121. data/lib/dependabot/javascript/bun/version.rb +0 -11
  122. data/lib/dependabot/javascript/shared/constraint_helper.rb +0 -359
  123. data/lib/dependabot/javascript/shared/dependency_files_filterer.rb +0 -164
  124. data/lib/dependabot/javascript/shared/file_fetcher.rb +0 -283
  125. data/lib/dependabot/javascript/shared/file_parser/lockfile_parser.rb +0 -106
  126. data/lib/dependabot/javascript/shared/file_parser.rb +0 -454
  127. data/lib/dependabot/javascript/shared/file_updater/npmrc_builder.rb +0 -394
  128. data/lib/dependabot/javascript/shared/file_updater/package_json_preparer.rb +0 -87
  129. data/lib/dependabot/javascript/shared/file_updater/package_json_updater.rb +0 -376
  130. data/lib/dependabot/javascript/shared/file_updater.rb +0 -179
  131. data/lib/dependabot/javascript/shared/language.rb +0 -45
  132. data/lib/dependabot/javascript/shared/metadata_finder.rb +0 -209
  133. data/lib/dependabot/javascript/shared/native_helpers.rb +0 -21
  134. data/lib/dependabot/javascript/shared/package_manager_detector.rb +0 -72
  135. data/lib/dependabot/javascript/shared/package_name.rb +0 -118
  136. data/lib/dependabot/javascript/shared/registry_helper.rb +0 -190
  137. data/lib/dependabot/javascript/shared/registry_parser.rb +0 -93
  138. data/lib/dependabot/javascript/shared/requirement.rb +0 -144
  139. data/lib/dependabot/javascript/shared/sub_dependency_files_filterer.rb +0 -79
  140. data/lib/dependabot/javascript/shared/update_checker/dependency_files_builder.rb +0 -87
  141. data/lib/dependabot/javascript/shared/update_checker/registry_finder.rb +0 -358
  142. data/lib/dependabot/javascript/shared/version.rb +0 -133
  143. data/lib/dependabot/javascript/shared/version_selector.rb +0 -60
  144. data/lib/dependabot/javascript.rb +0 -39
@@ -0,0 +1,21 @@
1
+ /* YARN.LOCK PARSER
2
+ *
3
+ * Inputs:
4
+ * - directory containing a yarn.lock
5
+ *
6
+ * Outputs:
7
+ * - JSON formatted yarn.lock
8
+ */
9
+ const fs = require("fs");
10
+ const path = require("path");
11
+ const parseLockfile = require("@dependabot/yarn-lib/lib/lockfile/parse")
12
+ .default;
13
+
14
+ async function parse(directory) {
15
+ const readFile = (fileName) =>
16
+ fs.readFileSync(path.join(directory, fileName)).toString();
17
+ const data = readFile("yarn.lock");
18
+ return parseLockfile(data).object;
19
+ }
20
+
21
+ module.exports = { parse };
@@ -0,0 +1,132 @@
1
+ /* PEER DEPENDENCY CHECKER
2
+ *
3
+ * Inputs:
4
+ * - directory containing a package.json and a yarn.lock
5
+ * - dependency name
6
+ * - new dependency version
7
+ * - requirements for this dependency
8
+ *
9
+ * Outputs:
10
+ * - successful completion, or an error if there are peer dependency warnings
11
+ */
12
+ const path = require("path");
13
+ const { Add } = require("@dependabot/yarn-lib/lib/cli/commands/add");
14
+ const Config = require("@dependabot/yarn-lib/lib/config").default;
15
+ const { BufferReporter } = require("@dependabot/yarn-lib/lib/reporters");
16
+ const Lockfile = require("@dependabot/yarn-lib/lib/lockfile").default;
17
+ const { isString } = require("./helpers");
18
+ const fetcher = require("@dependabot/yarn-lib/lib/package-fetcher.js");
19
+
20
+ // Check peer dependencies without downloading node_modules or updating
21
+ // package/lockfiles
22
+ //
23
+ // Logic copied from the import command
24
+ class LightweightAdd extends Add {
25
+ async bailout() {
26
+ const manifests = await fetcher.fetch(
27
+ this.resolver.getManifests(),
28
+ this.config
29
+ );
30
+ this.resolver.updateManifests(manifests);
31
+ await this.linker.resolvePeerModules();
32
+ return true;
33
+ }
34
+ }
35
+
36
+ function devRequirement(requirements) {
37
+ const groups = requirements.groups;
38
+ return (
39
+ groups.indexOf("devDependencies") > -1 &&
40
+ groups.indexOf("dependencies") == -1
41
+ );
42
+ }
43
+
44
+ function optionalRequirement(requirements) {
45
+ const groups = requirements.groups;
46
+ return (
47
+ groups.indexOf("optionalDependencies") > -1 &&
48
+ groups.indexOf("dependencies") == -1
49
+ );
50
+ }
51
+
52
+ function installArgsWithVersion(depName, desiredVersion, requirements) {
53
+ const source =
54
+ "source" in requirements
55
+ ? requirements.source
56
+ : (requirements.find((req) => req.source) || {}).source;
57
+ const req =
58
+ "requirement" in requirements
59
+ ? requirements.requirement
60
+ : (requirements.find((req) => req.requirement) || {}).requirement;
61
+
62
+ if (source && source.type === "git") {
63
+ if (desiredVersion) {
64
+ return [`${depName}@${source.url}#${desiredVersion}`];
65
+ } else {
66
+ return [`${depName}@${source.url}`];
67
+ }
68
+ } else {
69
+ return [`${depName}@${desiredVersion || req}`];
70
+ }
71
+ }
72
+
73
+ async function checkPeerDependencies(
74
+ directory,
75
+ depName,
76
+ desiredVersion,
77
+ requirements
78
+ ) {
79
+ for (let req of requirements) {
80
+ await checkPeerDepsForReq(directory, depName, desiredVersion, req);
81
+ }
82
+ }
83
+
84
+ async function checkPeerDepsForReq(
85
+ directory,
86
+ depName,
87
+ desiredVersion,
88
+ requirement
89
+ ) {
90
+ const flags = {
91
+ ignoreScripts: true,
92
+ ignoreWorkspaceRootCheck: true,
93
+ ignoreEngines: true,
94
+ ignorePlatform: true,
95
+ dev: devRequirement(requirement),
96
+ optional: optionalRequirement(requirement),
97
+ };
98
+ const reporter = new BufferReporter();
99
+ const config = new Config(reporter);
100
+
101
+ await config.init({
102
+ cwd: path.join(directory, path.dirname(requirement.file)),
103
+ nonInteractive: true,
104
+ enableDefaultRc: true,
105
+ extraneousYarnrcFiles: [".yarnrc"],
106
+ });
107
+
108
+ const lockfile = await Lockfile.fromDirectory(directory, reporter);
109
+
110
+ // Returns dep name and version for yarn add, example: ["react@16.6.0"]
111
+ let args = installArgsWithVersion(depName, desiredVersion, requirement);
112
+
113
+ // Just as if we'd run `yarn add package@version`, but using our lightweight
114
+ // implementation of Add that doesn't actually download and install packages
115
+ const add = new LightweightAdd(args, flags, config, reporter, lockfile);
116
+
117
+ await add.init();
118
+
119
+ const eventBuffer = reporter.getBuffer();
120
+ const peerDependencyWarnings = eventBuffer
121
+ .map(({ data }) => data)
122
+ .filter((data) => {
123
+ // Guard against event.data sometimes being an object
124
+ return isString(data) && data.match(/(unmet|incorrect) peer dependency/);
125
+ });
126
+
127
+ if (peerDependencyWarnings.length) {
128
+ throw new Error(peerDependencyWarnings.join("\n"));
129
+ }
130
+ }
131
+
132
+ module.exports = { checkPeerDependencies };
@@ -0,0 +1,57 @@
1
+ const parse = require("@dependabot/yarn-lib/lib/lockfile/parse").default;
2
+ const stringify = require("@dependabot/yarn-lib/lib/lockfile/stringify")
3
+ .default;
4
+
5
+ // Get an array of a dependency's requested version ranges from a lockfile
6
+ function getRequestedVersions(depName, lockfileJson) {
7
+ const requestedVersions = [];
8
+ // Matching dependency name and version requirements which could be a full url:
9
+ // dep@version, @private-dep@version, private-dep@https:://token@gh.com...#ref
10
+ const re = /^(.[^@]*)@(.*?)$/;
11
+
12
+ Object.entries(lockfileJson).forEach(([name, _]) => {
13
+ if (name.match(re)) {
14
+ const [_, packageName, requestedVersion] = name.match(re);
15
+ if (packageName === depName) {
16
+ requestedVersions.push(requestedVersion);
17
+ }
18
+ }
19
+ });
20
+
21
+ return requestedVersions;
22
+ }
23
+
24
+ module.exports = (
25
+ oldLockfileContent,
26
+ newLockfileContent,
27
+ depName,
28
+ newVersionRequirement,
29
+ existingVersionRequirement
30
+ ) => {
31
+ const oldJson = parse(oldLockfileContent).object;
32
+ const newJson = parse(newLockfileContent).object;
33
+
34
+ const enableLockfileVersions = Boolean(
35
+ oldLockfileContent.match(/^# yarn v/m)
36
+ );
37
+ const noHeader = !Boolean(oldLockfileContent.match(/^# THIS IS AN AU/m));
38
+
39
+ const oldPackageReqs = getRequestedVersions(depName, oldJson);
40
+ const newPackageReqs = getRequestedVersions(depName, newJson);
41
+
42
+ const reqToReplace = newPackageReqs.find((pattern) => {
43
+ return !oldPackageReqs.includes(pattern);
44
+ });
45
+
46
+ // If the new lockfile has entries that don't exist in the old lockfile,
47
+ // replace these version requirements with a range (will currently be an
48
+ // exact version because we tell yarn to install a specific version)
49
+ if (reqToReplace) {
50
+ newJson[
51
+ `${depName}@${newVersionRequirement || existingVersionRequirement}`
52
+ ] = newJson[`${depName}@${reqToReplace}`];
53
+ delete newJson[`${depName}@${reqToReplace}`];
54
+ }
55
+
56
+ return stringify(newJson, noHeader, enableLockfileVersions);
57
+ };
@@ -0,0 +1,83 @@
1
+ const fs = require("fs");
2
+ const os = require("os");
3
+ const path = require("path");
4
+ const Config = require("@dependabot/yarn-lib/lib/config").default;
5
+ const { EventReporter } = require("@dependabot/yarn-lib/lib/reporters");
6
+ const Lockfile = require("@dependabot/yarn-lib/lib/lockfile").default;
7
+ const fixDuplicates = require("./fix-duplicates");
8
+ const { LightweightInstall, LOCKFILE_ENTRY_REGEX } = require("./helpers");
9
+ const { parse } = require("./lockfile-parser");
10
+ const stringify =
11
+ require("@dependabot/yarn-lib/lib/lockfile/stringify").default;
12
+
13
+ // Replace the version comments in the new lockfile with the ones from the old
14
+ // lockfile. If they weren't present in the old lockfile, delete them.
15
+ function recoverVersionComments(oldLockfile, newLockfile) {
16
+ const yarnRegex = /^# yarn v(\S+)\n/gm;
17
+ const nodeRegex = /^# node v(\S+)\n/gm;
18
+ const oldMatch = (regex) => [].concat(oldLockfile.match(regex))[0];
19
+ return newLockfile
20
+ .replace(yarnRegex, () => oldMatch(yarnRegex) || "")
21
+ .replace(nodeRegex, () => oldMatch(nodeRegex) || "");
22
+ }
23
+
24
+ async function updateDependencyFile(
25
+ directory,
26
+ lockfileName,
27
+ dependencies
28
+ ) {
29
+ const readFile = (fileName) =>
30
+ fs.readFileSync(path.join(directory, fileName)).toString();
31
+ const originalYarnLock = readFile(lockfileName);
32
+
33
+ const flags = {
34
+ ignoreScripts: true,
35
+ ignoreWorkspaceRootCheck: true,
36
+ ignoreEngines: true,
37
+ };
38
+ const reporter = new EventReporter();
39
+ const config = new Config(reporter);
40
+ await config.init({
41
+ cwd: directory,
42
+ nonInteractive: true,
43
+ enableDefaultRc: true,
44
+ extraneousYarnrcFiles: [".yarnrc"],
45
+ });
46
+ const noHeader = !Boolean(originalYarnLock.match(/^# THIS IS AN AU/m));
47
+ config.enableLockfileVersions = Boolean(originalYarnLock.match(/^# yarn v/m));
48
+
49
+ // SubDependencyVersionResolver relies on the install finding the latest
50
+ // version of a sub-dependency that's been removed from the lockfile
51
+ // YarnLockFileUpdater passes a specific version to be updated
52
+ const lockfileObject = await parse(directory);
53
+ for (const [entry, pkg] of Object.entries(lockfileObject)) {
54
+ const [_, depName] = entry.match(
55
+ LOCKFILE_ENTRY_REGEX
56
+ );
57
+ if (dependencies.some(dependency => dependency.name === depName)) {
58
+ delete lockfileObject[entry];
59
+ }
60
+ }
61
+
62
+ let newLockFileContent = await stringify(lockfileObject, noHeader, config.enableLockfileVersions);
63
+ for (const dependency of dependencies) {
64
+ newLockFileContent = fixDuplicates(newLockFileContent, dependency.name);
65
+ }
66
+ fs.writeFileSync(path.join(directory, lockfileName), newLockFileContent);
67
+
68
+ const lockfile = await Lockfile.fromDirectory(directory, reporter);
69
+ const install = new LightweightInstall(flags, config, reporter, lockfile);
70
+ await install.init();
71
+
72
+ const updatedYarnLock = readFile(lockfileName);
73
+ const updatedYarnLockWithVersion = recoverVersionComments(
74
+ originalYarnLock,
75
+ updatedYarnLock
76
+ );
77
+
78
+ return {
79
+ [lockfileName]: updatedYarnLockWithVersion,
80
+ };
81
+ }
82
+
83
+ module.exports = { updateDependencyFile };
@@ -0,0 +1,209 @@
1
+ /* DEPENDENCY FILE UPDATER
2
+ *
3
+ * Inputs:
4
+ * - directory containing a package.json and a yarn.lock
5
+ * - dependency name
6
+ * - new dependency version
7
+ * - new requirements for this dependency
8
+ *
9
+ * Outputs:
10
+ * - updated package.json and yarn.lock files
11
+ *
12
+ * Update the dependency to the version specified and rewrite the package.json
13
+ * and yarn.lock files.
14
+ */
15
+ const fs = require("fs");
16
+ const path = require("path");
17
+ const { Add } = require("@dependabot/yarn-lib/lib/cli/commands/add");
18
+ const { Install } = require("@dependabot/yarn-lib/lib/cli/commands/install");
19
+ const {
20
+ cleanLockfile,
21
+ } = require("@dependabot/yarn-lib/lib/cli/commands/upgrade");
22
+ const Config = require("@dependabot/yarn-lib/lib/config").default;
23
+ const { EventReporter } = require("@dependabot/yarn-lib/lib/reporters");
24
+ const Lockfile = require("@dependabot/yarn-lib/lib/lockfile").default;
25
+ const parse = require("@dependabot/yarn-lib/lib/lockfile/parse").default;
26
+ const fixDuplicates = require("./fix-duplicates");
27
+ const replaceDeclaration = require("./replace-lockfile-declaration");
28
+ const { LightweightAdd, LightweightInstall } = require("./helpers");
29
+
30
+ function flattenAllDependencies(manifest) {
31
+ return Object.assign(
32
+ {},
33
+ manifest.optionalDependencies,
34
+ manifest.peerDependencies,
35
+ manifest.devDependencies,
36
+ manifest.dependencies
37
+ );
38
+ }
39
+
40
+ // Replace the version comments in the new lockfile with the ones from the old
41
+ // lockfile. If they weren't present in the old lockfile, delete them.
42
+ function recoverVersionComments(oldLockfile, newLockfile) {
43
+ const yarnRegex = /^# yarn v(\S+)\n/gm;
44
+ const nodeRegex = /^# node v(\S+)\n/gm;
45
+ const oldMatch = (regex) => [].concat(oldLockfile.match(regex))[0];
46
+ return newLockfile
47
+ .replace(yarnRegex, (match) => oldMatch(yarnRegex) || "")
48
+ .replace(nodeRegex, (match) => oldMatch(nodeRegex) || "");
49
+ }
50
+
51
+ function devRequirement(requirements) {
52
+ const groups = requirements.groups;
53
+ return (
54
+ groups.indexOf("devDependencies") > -1 &&
55
+ groups.indexOf("dependencies") == -1
56
+ );
57
+ }
58
+
59
+ function optionalRequirement(requirements) {
60
+ const groups = requirements.groups;
61
+ return (
62
+ groups.indexOf("optionalDependencies") > -1 &&
63
+ groups.indexOf("dependencies") == -1
64
+ );
65
+ }
66
+
67
+ function installArgsWithVersion(
68
+ depName,
69
+ desiredVersion,
70
+ requirements,
71
+ existingVersionRequirement
72
+ ) {
73
+ const source = requirements.source;
74
+
75
+ if (source && source.type === "git") {
76
+ if (!existingVersionRequirement) {
77
+ existingVersionRequirement = source.url;
78
+ }
79
+
80
+ // Git is configured to auth over https while updating
81
+ existingVersionRequirement = existingVersionRequirement.replace(
82
+ /git\+ssh:\/\/git@(.*?)[:/]/,
83
+ "git+https://$1/"
84
+ );
85
+
86
+ // Keep any semver range that has already been updated in the package
87
+ // requirement when installing the new version
88
+ if (existingVersionRequirement.match(desiredVersion)) {
89
+ return [`${depName}@${existingVersionRequirement}`];
90
+ } else {
91
+ return [
92
+ `${depName}@${existingVersionRequirement.replace(
93
+ /#.*/,
94
+ ""
95
+ )}#${desiredVersion}`,
96
+ ];
97
+ }
98
+ } else {
99
+ return [`${depName}@${desiredVersion}`];
100
+ }
101
+ }
102
+
103
+ async function updateDependencyFiles(directory, dependencies) {
104
+ const readFile = (fileName) =>
105
+ fs.readFileSync(path.join(directory, fileName)).toString();
106
+ let updateRunResults = { "yarn.lock": readFile("yarn.lock") };
107
+ let requiredVersions = [];
108
+ for (let dep of dependencies) {
109
+ for (let reqs of dep.requirements) {
110
+ if (requiredVersions.indexOf(reqs.requirement) > -1) {
111
+ continue;
112
+ }
113
+ updateRunResults = Object.assign(
114
+ updateRunResults,
115
+ await updateDependencyFile(directory, dep.name, dep.version, reqs)
116
+ );
117
+ requiredVersions.push(reqs.requirement);
118
+ }
119
+ }
120
+ return updateRunResults;
121
+ }
122
+
123
+ async function updateDependencyFile(
124
+ directory,
125
+ depName,
126
+ desiredVersion,
127
+ requirements
128
+ ) {
129
+ const readFile = (fileName) =>
130
+ fs.readFileSync(path.join(directory, fileName)).toString();
131
+ const originalYarnLock = readFile("yarn.lock");
132
+ const originalPackageJson = readFile(requirements.file);
133
+
134
+ const flags = {
135
+ ignoreScripts: true,
136
+ ignoreWorkspaceRootCheck: true,
137
+ ignoreEngines: true,
138
+ ignorePlatform: true,
139
+ dev: devRequirement(requirements),
140
+ optional: optionalRequirement(requirements),
141
+ };
142
+ const reporter = new EventReporter();
143
+ const config = new Config(reporter);
144
+ await config.init({
145
+ cwd: path.join(directory, path.dirname(requirements.file)),
146
+ nonInteractive: true,
147
+ enableDefaultRc: true,
148
+ extraneousYarnrcFiles: [".yarnrc"],
149
+ });
150
+ config.enableLockfileVersions = Boolean(originalYarnLock.match(/^# yarn v/m));
151
+
152
+ const lockfile = await Lockfile.fromDirectory(directory, reporter);
153
+
154
+ // Just as if we'd run `yarn add package@version`, but using our lightweight
155
+ // implementation of Add that doesn't actually download and install packages
156
+ const manifest = await config.readRootManifest();
157
+ const existingVersionRequirement = flattenAllDependencies(manifest)[depName];
158
+
159
+ const args = installArgsWithVersion(
160
+ depName,
161
+ desiredVersion,
162
+ requirements,
163
+ existingVersionRequirement
164
+ );
165
+
166
+ const add = new LightweightAdd(args, flags, config, reporter, lockfile);
167
+
168
+ // Despite the innocent-sounding name, this actually does all the hard work
169
+ await add.init();
170
+
171
+ const dedupedYarnLock = fixDuplicates(readFile("yarn.lock"), depName);
172
+
173
+ const newVersionRequirement = requirements.requirement;
174
+
175
+ // Replace the version requirement in the lockfile (which will currently be an
176
+ // exact version, not a requirement range)
177
+ // If we don't have new requirement (e.g. git source) use the existing version
178
+ // requirement from the package manifest
179
+ const replacedDeclarationYarnLock = replaceDeclaration(
180
+ originalYarnLock,
181
+ dedupedYarnLock,
182
+ depName,
183
+ newVersionRequirement,
184
+ existingVersionRequirement
185
+ );
186
+
187
+ // Do a normal install to ensure the lockfile doesn't change when we do
188
+ fs.writeFileSync(
189
+ path.join(directory, "yarn.lock"),
190
+ replacedDeclarationYarnLock
191
+ );
192
+ fs.writeFileSync(
193
+ path.join(directory, requirements.file),
194
+ originalPackageJson
195
+ );
196
+
197
+ const lockfile2 = await Lockfile.fromDirectory(directory, reporter);
198
+ const install2 = new LightweightInstall(flags, config, reporter, lockfile2);
199
+ await install2.init();
200
+
201
+ let updatedYarnLock = readFile("yarn.lock");
202
+ updatedYarnLock = recoverVersionComments(originalYarnLock, updatedYarnLock);
203
+
204
+ return {
205
+ "yarn.lock": updatedYarnLock,
206
+ };
207
+ }
208
+
209
+ module.exports = { updateDependencyFiles };