spdx-satisfies 5.0.1 → 6.0.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.
- package/README.md +9 -43
- package/index.js +31 -25
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,48 +1,14 @@
|
|
|
1
|
+
`satisfies(SPDX license expression, array of approved licenses)`
|
|
2
|
+
|
|
3
|
+
Approved licenses may be simple license identifiers like `MIT`, plus-ranges like `EPL-2.0+`, or licenses with exceptions like `Apache-2.0 WITH LLVM`. They may _not_ be compound expressions using `AND` or `OR`.
|
|
4
|
+
|
|
1
5
|
```javascript
|
|
2
6
|
var assert = require('assert')
|
|
3
7
|
var satisfies = require('spdx-satisfies')
|
|
4
8
|
|
|
5
|
-
assert(satisfies('MIT', 'MIT'))
|
|
6
|
-
|
|
7
|
-
assert(satisfies('MIT', '
|
|
8
|
-
assert(satisfies('
|
|
9
|
-
assert(!satisfies('GPL-
|
|
10
|
-
|
|
11
|
-
assert(satisfies('GPL-2.0', 'GPL-2.0+'))
|
|
12
|
-
assert(satisfies('GPL-3.0', 'GPL-2.0+'))
|
|
13
|
-
assert(satisfies('GPL-1.0+', 'GPL-2.0+'))
|
|
14
|
-
assert(!satisfies('GPL-1.0', 'GPL-2.0+'))
|
|
15
|
-
assert(satisfies('GPL-2.0-only', 'GPL-2.0-only'))
|
|
16
|
-
assert(satisfies('GPL-3.0-only', 'GPL-2.0+'))
|
|
17
|
-
assert(satisfies('LGPL-3.0-only', 'LGPL-3.0-or-later'))
|
|
18
|
-
assert(satisfies('GPL-2.0', 'GPL-2.0+'))
|
|
19
|
-
assert(satisfies('GPL-2.0-only', 'GPL-2.0+'))
|
|
20
|
-
assert(satisfies('GPL-2.0', 'GPL-2.0-or-later'))
|
|
21
|
-
|
|
22
|
-
assert(!satisfies(
|
|
23
|
-
'GPL-2.0',
|
|
24
|
-
'GPL-2.0+ WITH Bison-exception-2.2'
|
|
25
|
-
))
|
|
26
|
-
|
|
27
|
-
assert(satisfies(
|
|
28
|
-
'GPL-3.0 WITH Bison-exception-2.2',
|
|
29
|
-
'GPL-2.0+ WITH Bison-exception-2.2'
|
|
30
|
-
))
|
|
31
|
-
|
|
32
|
-
assert(satisfies('(MIT OR GPL-2.0)', '(ISC OR MIT)'))
|
|
33
|
-
assert(satisfies('(MIT AND GPL-2.0)', '(MIT AND GPL-2.0)'))
|
|
34
|
-
assert(satisfies('MIT AND GPL-2.0 AND ISC', 'MIT AND GPL-2.0 AND ISC'))
|
|
35
|
-
assert(satisfies('MIT AND GPL-2.0 AND ISC', 'ISC AND GPL-2.0 AND MIT'))
|
|
36
|
-
assert(satisfies('(MIT OR GPL-2.0) AND ISC', 'MIT AND ISC'))
|
|
37
|
-
assert(satisfies('MIT AND ISC', '(MIT OR GPL-2.0) AND ISC'))
|
|
38
|
-
assert(satisfies('MIT AND ISC', '(MIT AND GPL-2.0) OR ISC'))
|
|
39
|
-
assert(satisfies('(MIT OR Apache-2.0) AND (ISC OR GPL-2.0)', 'Apache-2.0 AND ISC'))
|
|
40
|
-
assert(satisfies('(MIT OR Apache-2.0) AND (ISC OR GPL-2.0)', 'Apache-2.0 OR ISC'))
|
|
41
|
-
assert(satisfies('(MIT AND GPL-2.0)', '(MIT OR GPL-2.0)'))
|
|
42
|
-
assert(satisfies('(MIT AND GPL-2.0)', '(GPL-2.0 AND MIT)'))
|
|
43
|
-
assert(satisfies('MIT', '(GPL-2.0 OR MIT) AND (MIT OR ISC)'))
|
|
44
|
-
assert(satisfies('MIT AND ICU', '(MIT AND GPL-2.0) OR (ISC AND (Apache-2.0 OR ICU))'))
|
|
45
|
-
assert(!satisfies('(MIT AND GPL-2.0)', '(ISC OR GPL-2.0)'))
|
|
46
|
-
assert(!satisfies('MIT AND (GPL-2.0 OR ISC)', 'MIT'))
|
|
47
|
-
assert(!satisfies('(MIT OR Apache-2.0) AND (ISC OR GPL-2.0)', 'MIT'))
|
|
9
|
+
assert(satisfies('MIT', ['MIT', 'ISC', 'BSD-2-Clause', 'Apache-2.0']))
|
|
10
|
+
assert(satisfies('GPL-2.0 OR MIT', ['MIT']))
|
|
11
|
+
assert(!satisfies('GPL-2.0 AND MIT', ['MIT']))
|
|
12
|
+
assert(satisfies('GPL-3.0', ['GPL-2.0+']))
|
|
13
|
+
assert(!satisfies('GPL-1.0', ['GPL-2.0+']))
|
|
48
14
|
```
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@ var compare = require('spdx-compare')
|
|
|
2
2
|
var parse = require('spdx-expression-parse')
|
|
3
3
|
var ranges = require('spdx-ranges')
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
function rangesAreCompatible (first, second) {
|
|
6
6
|
return (
|
|
7
7
|
first.license === second.license ||
|
|
8
8
|
ranges.some(function (range) {
|
|
@@ -26,7 +26,7 @@ function licenseInRange (license, range) {
|
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
function identifierInRange (identifier, range) {
|
|
30
30
|
return (
|
|
31
31
|
identifier.license === range.license ||
|
|
32
32
|
compare.gt(identifier.license, range.license) ||
|
|
@@ -34,7 +34,7 @@ var identifierInRange = function (identifier, range) {
|
|
|
34
34
|
)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
function licensesAreCompatible (first, second) {
|
|
38
38
|
if (first.exception !== second.exception) {
|
|
39
39
|
return false
|
|
40
40
|
} else if (second.hasOwnProperty('license')) {
|
|
@@ -58,30 +58,38 @@ var licensesAreCompatible = function (first, second) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function
|
|
61
|
+
function replaceGPLOnlyOrLaterWithRanges (argument) {
|
|
62
62
|
var license = argument.license
|
|
63
63
|
if (license) {
|
|
64
64
|
if (endsWith(license, '-or-later')) {
|
|
65
65
|
argument.license = license.replace('-or-later', '')
|
|
66
66
|
argument.plus = true
|
|
67
67
|
} else if (endsWith(license, '-only')) {
|
|
68
|
-
argument.license = license.replace('-
|
|
68
|
+
argument.license = license.replace('-only', '')
|
|
69
69
|
delete argument.plus
|
|
70
70
|
}
|
|
71
71
|
} else if (argument.left && argument.right) {
|
|
72
|
-
argument.left =
|
|
73
|
-
argument.right =
|
|
72
|
+
argument.left = replaceGPLOnlyOrLaterWithRanges(argument.left)
|
|
73
|
+
argument.right = replaceGPLOnlyOrLaterWithRanges(argument.right)
|
|
74
74
|
}
|
|
75
75
|
return argument
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function endsWith (string, substring) {
|
|
79
|
-
|
|
79
|
+
const index = string.indexOf(substring)
|
|
80
|
+
if (index === -1) return false
|
|
81
|
+
return index === string.length - substring.length
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
function licenseString (e) {
|
|
83
85
|
if (e.hasOwnProperty('noassertion')) return 'NOASSERTION'
|
|
84
|
-
if (e.license)
|
|
86
|
+
if (e.license) {
|
|
87
|
+
return (
|
|
88
|
+
e.license +
|
|
89
|
+
(e.plus ? '+' : '') +
|
|
90
|
+
(e.exception ? ('WITH ' + e.exception) : '')
|
|
91
|
+
)
|
|
92
|
+
}
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
// Expand the given expression into an equivalent array where each member is an array of licenses AND'd
|
|
@@ -92,15 +100,6 @@ function expand (expression) {
|
|
|
92
100
|
return sort(expandInner(expression))
|
|
93
101
|
}
|
|
94
102
|
|
|
95
|
-
// Flatten the given expression into an array of all licenses mentioned in the expression.
|
|
96
|
-
function flatten (expression) {
|
|
97
|
-
var expanded = expandInner(expression)
|
|
98
|
-
var flattened = expanded.reduce(function (result, clause) {
|
|
99
|
-
return Object.assign(result, clause)
|
|
100
|
-
}, {})
|
|
101
|
-
return sort([flattened])[0]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
103
|
function expandInner (expression) {
|
|
105
104
|
if (!expression.conjunction) return [{ [licenseString(expression)]: expression }]
|
|
106
105
|
if (expression.conjunction === 'or') return expandInner(expression.left).concat(expandInner(expression.right))
|
|
@@ -123,16 +122,23 @@ function sort (licenseList) {
|
|
|
123
122
|
})
|
|
124
123
|
}
|
|
125
124
|
|
|
126
|
-
function isANDCompatible (
|
|
127
|
-
return
|
|
128
|
-
return
|
|
125
|
+
function isANDCompatible (parsedExpression, parsedLicenses) {
|
|
126
|
+
return parsedExpression.every(function (element) {
|
|
127
|
+
return parsedLicenses.some(function (approvedLicense) {
|
|
128
|
+
return licensesAreCompatible(element, approvedLicense)
|
|
129
|
+
})
|
|
129
130
|
})
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
function satisfies (
|
|
133
|
-
var
|
|
134
|
-
var
|
|
135
|
-
|
|
133
|
+
function satisfies (spdxExpression, arrayOfLicenses) {
|
|
134
|
+
var parsedExpression = expand(replaceGPLOnlyOrLaterWithRanges(parse(spdxExpression)))
|
|
135
|
+
var parsedLicenses = arrayOfLicenses.map(function (l) { return replaceGPLOnlyOrLaterWithRanges(parse(l)) })
|
|
136
|
+
for (const parsed of parsedLicenses) {
|
|
137
|
+
if (parsed.hasOwnProperty('conjunction')) {
|
|
138
|
+
throw new Error('Approved licenses cannot be AND or OR expressions.')
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return parsedExpression.some(function (o) { return isANDCompatible(o, parsedLicenses) })
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
module.exports = satisfies
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spdx-satisfies",
|
|
3
3
|
"description": "test whether SPDX expressions satisfy licensing criteria",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.1",
|
|
5
5
|
"author": "Kyle E. Mitchell <kyle@kemitchell.com> (https://kemitchell.com)",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Kyle E. Mitchell <kyle@kemitchell.com> (https://kemitchell.com)",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"spdx-ranges": "^2.0.0"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"defence-cli": "^
|
|
17
|
+
"defence-cli": "^3.0.1",
|
|
18
18
|
"replace-require-self": "^1.1.1",
|
|
19
19
|
"standard": "^11.0.0"
|
|
20
20
|
},
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
"index.js"
|
|
35
35
|
],
|
|
36
36
|
"scripts": {
|
|
37
|
-
"test": "
|
|
37
|
+
"test": "npm run test:suite && npm run test:readme",
|
|
38
|
+
"test:suite": "node test.js",
|
|
39
|
+
"test:readme": "defence -i javascript README.md | replace-require-self | node",
|
|
38
40
|
"lint": "standard"
|
|
39
41
|
}
|
|
40
42
|
}
|