Skip to content

Commit d4cf64d

Browse files
feat: add support for yarn berry lockfiles (#147)
* feat: add support for yarn berry lockfiles * Update packages/lockfile-lint-api/package.json * Update packages/lockfile-lint/package.json * Update packages/lockfile-lint-api/__tests__/parseYarnLockfile.test.js * Update packages/lockfile-lint/package.json * Update packages/lockfile-lint/package.json * Update packages/lockfile-lint-api/__tests__/parseYarnLockfile.test.js Co-authored-by: Liran Tal <[email protected]>
1 parent 144dc55 commit d4cf64d

File tree

5 files changed

+92
-15
lines changed

5 files changed

+92
-15
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This file is generated by running "yarn install" inside your project.
2+
# Manual changes might be lost - proceed with caution!
3+
4+
__metadata:
5+
version: 6
6+
cacheKey: 8
7+
8+
"debug@npm:4.1.1":
9+
version: 4.1.1
10+
resolution: "debug@npm:4.1.1"
11+
dependencies:
12+
ms: ^2.1.1
13+
checksum: 1e681f5cce94ba10f8dde74b20b42e4d8cf0d2a6700f4c165bb3bb6885565ef5ca5885bf07e704974a835f2415ff095a63164f539988a1f07e8a69fe8b1d65ad
14+
languageName: node
15+
linkType: hard
16+
17+
"ms@npm:2.1.2":
18+
version: 2.1.2
19+
resolution: "ms@npm:2.1.2"
20+
checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f
21+
languageName: node
22+
linkType: hard
23+
24+
"ms@npm:^2.1.1":
25+
version: 2.1.3
26+
resolution: "ms@npm:2.1.3"
27+
checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
28+
languageName: node
29+
linkType: hard
30+
31+
"test@workspace:.":
32+
version: 0.0.0-use.local
33+
resolution: "test@workspace:."
34+
dependencies:
35+
debug: 4.1.1
36+
ms: 2.1.2
37+
languageName: unknown
38+
linkType: soft

packages/lockfile-lint-api/__tests__/parseYarnLockfile.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ describe('ParseLockfile Yarn', () => {
2424
)
2525
})
2626

27+
it('parsing a yarn berry lockfile returns an object with packages', () => {
28+
const mockYarnLockfilePath = path.join(__dirname, './__fixtures__/yarnberry.lock')
29+
const options = {
30+
lockfilePath: mockYarnLockfilePath,
31+
lockfileType: 'yarn'
32+
}
33+
const parser = new ParseLockfile(options)
34+
const lockfile = parser.parseSync()
35+
36+
expect(lockfile.type).toEqual('success')
37+
expect(lockfile.object).toEqual(
38+
expect.objectContaining({
39+
'debug@npm:4.1.1': expect.any(Object),
40+
'ms@npm:2.1.2': expect.any(Object),
41+
'ms@npm:^2.1.1': expect.any(Object),
42+
'test@workspace:.': expect.any(Object)
43+
})
44+
)
45+
})
46+
2747
it('providing empty content for lockfileText throws an error', () => {
2848
const parser = new ParseLockfile({lockfileText: '\n\n', lockfileType: 'yarn'})
2949
expect(() => {

packages/lockfile-lint-api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
"directory": "packages/lockfile-lint-api"
5050
},
5151
"dependencies": {
52-
"@yarnpkg/parsers": "^3.0.0-rc.6",
52+
"@yarnpkg/parsers": "^3.0.0-rc.32",
5353
"object-hash": "^3.0.0"
5454
},
5555
"devDependencies": {

packages/lockfile-lint-api/src/ParseLockfile.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ const {
2020
* Checks if a sample object is a valid dependency structure
2121
* @return boolean
2222
*/
23-
function checkSampleContent (lockfile) {
24-
const [sampleKey, sampleValue] = Object.entries(lockfile)[0]
23+
function checkSampleContent (lockfile, isYarnBerry) {
24+
const [sampleKey, sampleValue] = Object.entries(lockfile)[isYarnBerry ? 1 : 0]
2525
return (
2626
sampleKey.match(/.*@.*/) &&
2727
(sampleValue &&
2828
typeof sampleValue === 'object' &&
2929
sampleValue.hasOwnProperty('version') &&
30-
sampleValue.hasOwnProperty('resolved'))
30+
(sampleValue.hasOwnProperty('resolved') || sampleValue.hasOwnProperty('resolution')))
3131
)
3232
}
3333
/**
@@ -36,11 +36,30 @@ function checkSampleContent (lockfile) {
3636
*/
3737
function yarnParseAndVerify (lockfileBuffer) {
3838
const lockfile = yarnParseSyml(lockfileBuffer.toString())
39+
const isYarnBerry = typeof lockfile.__metadata === 'object'
3940
const hasSensibleContent =
40-
lockfile && typeof lockfile === 'object' && checkSampleContent(lockfile)
41+
lockfile && typeof lockfile === 'object' && checkSampleContent(lockfile, isYarnBerry)
4142
if (!hasSensibleContent) {
4243
throw Error('Lockfile does not seem to contain a valid dependency list')
4344
}
45+
46+
if (isYarnBerry) {
47+
const normalizedLockFile = {}
48+
Object.entries(lockfile).forEach(([packageName, packageDetails]) => {
49+
const resolution = packageDetails.resolution
50+
if (resolution) {
51+
const splitByAt = resolution.split('@')
52+
let host
53+
if (splitByAt.length > 2 && resolution[0] === '@') {
54+
host = splitByAt[2]
55+
} else {
56+
host = splitByAt[1]
57+
}
58+
normalizedLockFile[packageName] = Object.assign({}, packageDetails, {resolved: host})
59+
}
60+
})
61+
return {type: 'success', object: normalizedLockFile}
62+
}
4463
return {type: 'success', object: lockfile}
4564
}
4665
class ParseLockfile {

yarn.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,13 +1347,13 @@
13471347
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916"
13481348
integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==
13491349

1350-
"@yarnpkg/parsers@^3.0.0-rc.6":
1351-
version "3.0.0-rc.6"
1352-
resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.6.tgz#3c93267fdae4470e4eaaf8c5f81d0d00ea177f76"
1353-
integrity sha512-YqtJ9VQqQixZsJJS4X83e6RMpgK1jmQJSIrCfd1wO3i/7vPk9QoLvvZS4bwZ2ha8QWqWlO/alAcXCGBezEI1Ig==
1350+
"@yarnpkg/parsers@^3.0.0-rc.32":
1351+
version "3.0.0-rc.32"
1352+
resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.32.tgz#0aef0bd1b9e9954173c01a7cbd35f98765e39e7d"
1353+
integrity sha512-Sz2g88b3iAu2jpMnhtps2bRX2GAAOvanOxGcVi+o7ybGjLetxK23o2cHskXKypvXxtZTsJegel5pUWSPpYphww==
13541354
dependencies:
13551355
js-yaml "^3.10.0"
1356-
tslib "^1.13.0"
1356+
tslib "^2.4.0"
13571357

13581358
JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5:
13591359
version "1.3.5"
@@ -9403,16 +9403,16 @@ trim-right@^1.0.1:
94039403
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
94049404
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
94059405

9406-
tslib@^1.13.0:
9407-
version "1.14.1"
9408-
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
9409-
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
9410-
94119406
tslib@^1.9.0:
94129407
version "1.9.3"
94139408
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
94149409
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
94159410

9411+
tslib@^2.4.0:
9412+
version "2.4.1"
9413+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
9414+
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
9415+
94169416
tunnel-agent@^0.6.0:
94179417
version "0.6.0"
94189418
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"

0 commit comments

Comments
 (0)