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.
- checksums.yaml +4 -4
- data/helpers/.eslintrc +11 -0
- data/helpers/README.md +29 -0
- data/helpers/build +26 -0
- data/helpers/jest.config.js +5 -0
- data/helpers/lib/npm/conflicting-dependency-parser.js +78 -0
- data/helpers/lib/npm/index.js +9 -0
- data/helpers/lib/npm/vulnerability-auditor.js +291 -0
- data/helpers/lib/npm6/helpers.js +25 -0
- data/helpers/lib/npm6/index.js +9 -0
- data/helpers/lib/npm6/peer-dependency-checker.js +111 -0
- data/helpers/lib/npm6/remove-dependencies-from-lockfile.js +22 -0
- data/helpers/lib/npm6/subdependency-updater.js +78 -0
- data/helpers/lib/npm6/updater.js +199 -0
- data/helpers/lib/pnpm/index.js +5 -0
- data/helpers/lib/pnpm/lockfile-parser.js +82 -0
- data/helpers/lib/yarn/conflicting-dependency-parser.js +176 -0
- data/helpers/lib/yarn/fix-duplicates.js +80 -0
- data/helpers/lib/yarn/helpers.js +54 -0
- data/helpers/lib/yarn/index.js +14 -0
- data/helpers/lib/yarn/lockfile-parser.js +21 -0
- data/helpers/lib/yarn/peer-dependency-checker.js +132 -0
- data/helpers/lib/yarn/replace-lockfile-declaration.js +57 -0
- data/helpers/lib/yarn/subdependency-updater.js +83 -0
- data/helpers/lib/yarn/updater.js +209 -0
- data/helpers/package-lock.json +28519 -0
- data/helpers/package.json +29 -0
- data/helpers/patches/npm++pacote+9.5.12.patch +14 -0
- data/helpers/run.js +30 -0
- data/helpers/test/npm6/conflicting-dependency-parser.test.js +66 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package-lock.json +591 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package-lock.json +188 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package-lock.json +27 -0
- data/helpers/test/npm6/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
- data/helpers/test/npm6/fixtures/updater/original/package-lock.json +16 -0
- data/helpers/test/npm6/fixtures/updater/original/package.json +9 -0
- data/helpers/test/npm6/fixtures/updater/updated/package-lock.json +16 -0
- data/helpers/test/npm6/helpers.js +21 -0
- data/helpers/test/npm6/updater.test.js +30 -0
- data/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml +72 -0
- data/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml +2744 -0
- data/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml +16 -0
- data/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml +855 -0
- data/helpers/test/pnpm/lockfile-parser.test.js +62 -0
- data/helpers/test/yarn/conflicting-dependency-parser.test.js +83 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/package.json +14 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/deeply-nested/yarn.lock +496 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/package.json +14 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/dev-dependencies/yarn.lock +21 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/package.json +14 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/nested/yarn.lock +183 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/package.json +14 -0
- data/helpers/test/yarn/fixtures/conflicting-dependency-parser/simple/yarn.lock +21 -0
- data/helpers/test/yarn/fixtures/updater/illegal_character/package.json +8 -0
- data/helpers/test/yarn/fixtures/updater/illegal_character/yarn.lock +14 -0
- data/helpers/test/yarn/fixtures/updater/original/package.json +6 -0
- data/helpers/test/yarn/fixtures/updater/original/yarn.lock +11 -0
- data/helpers/test/yarn/fixtures/updater/updated/yarn.lock +12 -0
- data/helpers/test/yarn/fixtures/updater/with-version-comments/package.json +5 -0
- data/helpers/test/yarn/fixtures/updater/with-version-comments/yarn.lock +13 -0
- data/helpers/test/yarn/helpers.js +18 -0
- data/helpers/test/yarn/updater.test.js +117 -0
- data/lib/dependabot/bun/bun_package_manager.rb +47 -0
- data/lib/dependabot/bun/constraint_helper.rb +359 -0
- data/lib/dependabot/bun/dependency_files_filterer.rb +157 -0
- data/lib/dependabot/bun/file_fetcher/path_dependency_builder.rb +184 -0
- data/lib/dependabot/bun/file_fetcher.rb +402 -0
- data/lib/dependabot/bun/file_parser/bun_lock.rb +140 -0
- data/lib/dependabot/bun/file_parser/lockfile_parser.rb +105 -0
- data/lib/dependabot/bun/file_parser.rb +477 -0
- data/lib/dependabot/bun/file_updater/bun_lockfile_updater.rb +144 -0
- data/lib/dependabot/bun/file_updater/npmrc_builder.rb +256 -0
- data/lib/dependabot/bun/file_updater/package_json_preparer.rb +88 -0
- data/lib/dependabot/bun/file_updater/package_json_updater.rb +378 -0
- data/lib/dependabot/bun/file_updater.rb +203 -0
- data/lib/dependabot/bun/helpers.rb +93 -0
- data/lib/dependabot/bun/language.rb +45 -0
- data/lib/dependabot/bun/metadata_finder.rb +214 -0
- data/lib/dependabot/bun/native_helpers.rb +19 -0
- data/lib/dependabot/bun/package_manager.rb +280 -0
- data/lib/dependabot/bun/package_name.rb +118 -0
- data/lib/dependabot/bun/pnpm_package_manager.rb +55 -0
- data/lib/dependabot/bun/registry_helper.rb +188 -0
- data/lib/dependabot/bun/registry_parser.rb +93 -0
- data/lib/dependabot/bun/requirement.rb +146 -0
- data/lib/dependabot/bun/sub_dependency_files_filterer.rb +82 -0
- data/lib/dependabot/bun/update_checker/conflicting_dependency_resolver.rb +59 -0
- data/lib/dependabot/bun/update_checker/dependency_files_builder.rb +79 -0
- data/lib/dependabot/bun/update_checker/latest_version_finder.rb +448 -0
- data/lib/dependabot/bun/update_checker/library_detector.rb +76 -0
- data/lib/dependabot/bun/update_checker/registry_finder.rb +279 -0
- data/lib/dependabot/bun/update_checker/requirements_updater.rb +206 -0
- data/lib/dependabot/bun/update_checker/subdependency_version_resolver.rb +154 -0
- data/lib/dependabot/bun/update_checker/version_resolver.rb +583 -0
- data/lib/dependabot/bun/update_checker/vulnerability_auditor.rb +164 -0
- data/lib/dependabot/bun/update_checker.rb +455 -0
- data/lib/dependabot/bun/version.rb +138 -0
- data/lib/dependabot/bun/version_selector.rb +61 -0
- data/lib/dependabot/bun.rb +337 -35
- metadata +108 -65
- data/lib/dependabot/javascript/bun/file_fetcher.rb +0 -77
- data/lib/dependabot/javascript/bun/file_parser/bun_lock.rb +0 -156
- data/lib/dependabot/javascript/bun/file_parser/lockfile_parser.rb +0 -55
- data/lib/dependabot/javascript/bun/file_parser.rb +0 -74
- data/lib/dependabot/javascript/bun/file_updater/lockfile_updater.rb +0 -138
- data/lib/dependabot/javascript/bun/file_updater.rb +0 -75
- data/lib/dependabot/javascript/bun/helpers.rb +0 -72
- data/lib/dependabot/javascript/bun/package_manager.rb +0 -48
- data/lib/dependabot/javascript/bun/requirement.rb +0 -11
- data/lib/dependabot/javascript/bun/update_checker/conflicting_dependency_resolver.rb +0 -64
- data/lib/dependabot/javascript/bun/update_checker/dependency_files_builder.rb +0 -47
- data/lib/dependabot/javascript/bun/update_checker/latest_version_finder.rb +0 -450
- data/lib/dependabot/javascript/bun/update_checker/library_detector.rb +0 -76
- data/lib/dependabot/javascript/bun/update_checker/requirements_updater.rb +0 -203
- data/lib/dependabot/javascript/bun/update_checker/subdependency_version_resolver.rb +0 -144
- data/lib/dependabot/javascript/bun/update_checker/version_resolver.rb +0 -525
- data/lib/dependabot/javascript/bun/update_checker/vulnerability_auditor.rb +0 -165
- data/lib/dependabot/javascript/bun/update_checker.rb +0 -440
- data/lib/dependabot/javascript/bun/version.rb +0 -11
- data/lib/dependabot/javascript/shared/constraint_helper.rb +0 -359
- data/lib/dependabot/javascript/shared/dependency_files_filterer.rb +0 -164
- data/lib/dependabot/javascript/shared/file_fetcher.rb +0 -283
- data/lib/dependabot/javascript/shared/file_parser/lockfile_parser.rb +0 -106
- data/lib/dependabot/javascript/shared/file_parser.rb +0 -454
- data/lib/dependabot/javascript/shared/file_updater/npmrc_builder.rb +0 -394
- data/lib/dependabot/javascript/shared/file_updater/package_json_preparer.rb +0 -87
- data/lib/dependabot/javascript/shared/file_updater/package_json_updater.rb +0 -376
- data/lib/dependabot/javascript/shared/file_updater.rb +0 -179
- data/lib/dependabot/javascript/shared/language.rb +0 -45
- data/lib/dependabot/javascript/shared/metadata_finder.rb +0 -209
- data/lib/dependabot/javascript/shared/native_helpers.rb +0 -21
- data/lib/dependabot/javascript/shared/package_manager_detector.rb +0 -72
- data/lib/dependabot/javascript/shared/package_name.rb +0 -118
- data/lib/dependabot/javascript/shared/registry_helper.rb +0 -190
- data/lib/dependabot/javascript/shared/registry_parser.rb +0 -93
- data/lib/dependabot/javascript/shared/requirement.rb +0 -144
- data/lib/dependabot/javascript/shared/sub_dependency_files_filterer.rb +0 -79
- data/lib/dependabot/javascript/shared/update_checker/dependency_files_builder.rb +0 -87
- data/lib/dependabot/javascript/shared/update_checker/registry_finder.rb +0 -358
- data/lib/dependabot/javascript/shared/version.rb +0 -133
- data/lib/dependabot/javascript/shared/version_selector.rb +0 -60
- 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 };
|