118 lines
2.4 KiB
JavaScript
118 lines
2.4 KiB
JavaScript
const constants = require('./constants')
|
|
const errors = require('./errors')
|
|
const Version = require('./version')
|
|
const Comparator = require('./comparator')
|
|
|
|
const Range = module.exports = exports = class Range {
|
|
constructor (comparators = []) {
|
|
this.comparators = comparators
|
|
}
|
|
|
|
test (version) {
|
|
for (const set of this.comparators) {
|
|
let matches = true
|
|
|
|
for (const comparator of set) {
|
|
if (comparator.test(version)) continue
|
|
matches = false
|
|
break
|
|
}
|
|
|
|
if (matches) return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
toString () {
|
|
let result = ''
|
|
let first = true
|
|
|
|
for (const set of this.comparators) {
|
|
if (first) first = false
|
|
else result += ' || '
|
|
|
|
result += set.join(' ')
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|
|
|
|
exports.parse = function parse (input, state = { position: 0, partial: false }) {
|
|
let i = state.position
|
|
let c
|
|
|
|
const unexpected = (expected) => {
|
|
let msg
|
|
|
|
if (i >= input.length) {
|
|
msg = `Unexpected end of input in '${input}'`
|
|
} else {
|
|
msg = `Unexpected token '${input[i]}' in '${input}' at position ${i}`
|
|
}
|
|
|
|
if (expected) msg += `, ${expected}`
|
|
|
|
throw errors.INVALID_VERSION(msg, unexpected)
|
|
}
|
|
|
|
const comparators = []
|
|
|
|
while (i < input.length) {
|
|
const set = []
|
|
|
|
while (i < input.length) {
|
|
c = input[i]
|
|
|
|
let operator = constants.EQ
|
|
|
|
if (c === '<') {
|
|
operator = constants.LT
|
|
c = input[++i]
|
|
|
|
if (c === '=') {
|
|
operator = constants.LTE
|
|
c = input[++i]
|
|
}
|
|
} else if (c === '>') {
|
|
operator = constants.GT
|
|
c = input[++i]
|
|
|
|
if (c === '=') {
|
|
operator = constants.GTE
|
|
c = input[++i]
|
|
}
|
|
} else if (c === '=') {
|
|
c = input[++i]
|
|
}
|
|
|
|
const state = { position: i, partial: true }
|
|
|
|
set.push(new Comparator(operator, Version.parse(input, state)))
|
|
|
|
c = input[i = state.position]
|
|
|
|
while (c === ' ') c = input[++i]
|
|
|
|
if (c === '|' && input[i + 1] === '|') {
|
|
c = input[i += 2]
|
|
|
|
while (c === ' ') c = input[++i]
|
|
|
|
break
|
|
}
|
|
|
|
if (c && c !== '<' && c !== '>') unexpected('expected \'||\', \'<\', or \'>\'')
|
|
}
|
|
|
|
if (set.length) comparators.push(set)
|
|
}
|
|
|
|
if (i < input.length && state.partial === false) unexpected('expected end of input')
|
|
|
|
state.position = i
|
|
|
|
return new Range(comparators)
|
|
}
|