From 5b21ee08b4ea3c42ad4522cc37cc8cfd11563661 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 12:46:06 -0600 Subject: [PATCH 1/8] feat: emvar lite --- emvar-lite/mod.ts | 151 +++++++++++++++++++++++++++++++++++++++ emvar-lite/range.test.ts | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 emvar-lite/mod.ts create mode 100644 emvar-lite/range.test.ts diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts new file mode 100644 index 0000000..2963484 --- /dev/null +++ b/emvar-lite/mod.ts @@ -0,0 +1,151 @@ + +const starSub = /((\d+\.)*\d+)\.\*/ + +function incrementLastNumber(list: number[]) { + const newList = [...list] + newList[newList.length - 1]++ + return newList +} +export function rangeOf(range: string | Checker): Checker { + if (range instanceof Checker) { + return range + } + if (range === '*') return new Checker((version) => { + EmVar.from(version) + return true + }); + const starSubMatches = starSub.exec(range) + if (starSubMatches != null) { + const emVarLower = EmVar.parse(starSubMatches[1]) + const emVarUpper = emVarLower.withLastIncremented() + + return new Checker((version) => { + const v = EmVar.from(version); + return (v.greaterThan(emVarLower) || v.equals(emVarLower)) && !v.greaterThan(emVarUpper) && !v.equals(emVarUpper); + }) + } + + switch (range.substring(0, 2)) { + case '>=': { + const emVar = EmVar.parse(range.substring(2)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.greaterThan(emVar) || v.equals(emVar); + }) + } + case '<=': { + const emVar = EmVar.parse(range.substring(2)); + return new Checker((version) => { + const v = EmVar.from(version); + return !v.greaterThan(emVar); + }) + } + + } + + switch (range.substring(0, 1)) { + case '>': { + console.log('greaterThan') + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.greaterThan(emVar); + }) + } + case '<': { + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return !v.greaterThan(emVar) && !v.equals(emVar); + }) + } + case '=': { + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.equals(emVar); + }) + } + + } + throw new Error("Couldn't parse range: " + range); +} + +export function rangeAnd(...ranges: (string | Checker)[]): Checker { + let [firstCheck, ...rest] = ranges.map(rangeOf); + for (const checker of rest) { + firstCheck = firstCheck.and(checker); + } + return firstCheck; +} + +export function rangeOr(...ranges: (string | Checker)[]): Checker { + let [firstCheck, ...rest] = ranges.map(rangeOf); + for (const checker of rest) { + firstCheck = firstCheck.or(checker); + } + return firstCheck; +} + + +export class EmVar { + static from(range: string | EmVar): EmVar { + if (range instanceof EmVar) { + return range + } + return EmVar.parse(range) + } + static parse(range: string): EmVar { + const values = range.split('.').map(x => parseInt(x)); + for (const value of values) { + if (isNaN(value)) { + throw new Error(`Couldn't parse range: ${range}`); + } + } + return new EmVar(values); + } + private constructor(public readonly values: number[]) { } + + public withLastIncremented() { + return new EmVar(incrementLastNumber(this.values)) + } + + public greaterThan(other: EmVar): boolean { + for (const i in this.values) { + if (other.values[i] == null) { + return true + } + if (this.values[i] > other.values[i]) { + return true; + } + + if (this.values[i] < other.values[i]) { + return false; + } + } + return false; + } + + public equals(other: EmVar): boolean { + if (other.values.length !== this.values.length) { + return false + } + for (const i in this.values) { + if (this.values[i] !== other.values[i]) { + return false; + } + } + return true; + } +} + +export class Checker { + constructor(public readonly check: (value: string | EmVar) => boolean) { } + + public and(other: Checker): Checker { + return new Checker((value) => this.check(value) && other.check(value)); + } + public or(other: Checker): Checker { + return new Checker((value) => this.check(value) || other.check(value)); + } +} \ No newline at end of file diff --git a/emvar-lite/range.test.ts b/emvar-lite/range.test.ts new file mode 100644 index 0000000..62a1f9d --- /dev/null +++ b/emvar-lite/range.test.ts @@ -0,0 +1,140 @@ + +import { expect } from "https://deno.land/x/expect@v0.2.9/mod.ts"; +import { rangeAnd, rangeOf, rangeOr } from "./mod.ts"; +const { test } = Deno; + + +{ + const checker = rangeOf("*"); + test("rangeOf('*')", () => { + expect(checker.check("1")).toBe(true); + expect(checker.check("1.2")).toBe(true); + expect(checker.check("1.2.3.4")).toBe(true); + }) + test("rangeOf('*') invalid", () => { + expect(() => checker.check("a")).toThrow(); + expect(() => checker.check("")).toThrow(); + expect(() => checker.check("1..3")).toThrow(); + }) +} + +{ + const checker = rangeOf(">1.2.3.4"); + test(`rangeOf(">1.2.3.4") valid`, () => { + expect(checker.check("2")).toBe(true); + expect(checker.check("1.2.3.5")).toBe(true); + expect(checker.check("1.2.3.4.1")).toBe(true); + }) + + test(`rangeOf(">1.2.3.4") invalid`, () => { + expect(checker.check("1.2.3.4")).toBe(false); + expect(checker.check("1.2.3")).toBe(false); + expect(checker.check("1")).toBe(false); + }) +} +{ + const checker = rangeOf("=1.2.3"); + test(`rangeOf("=1.2.3") valid`, () => { + expect(checker.check("1.2.3")).toBe(true); + }) + + test(`rangeOf("=1.2.3") invalid`, () => { + expect(checker.check("2")).toBe(false); + expect(checker.check("1.2.3.1")).toBe(false); + expect(checker.check("1.2")).toBe(false); + }) +} +{ + const checker = rangeOf(">=1.2.3.4"); + test(`rangeOf(">=1.2.3.4") valid`, () => { + expect(checker.check("2")).toBe(true); + expect(checker.check("1.2.3.5")).toBe(true); + expect(checker.check("1.2.3.4.1")).toBe(true); + expect(checker.check("1.2.3.4")).toBe(true); + }) + + test(`rangeOf(">=1.2.3.4") invalid`, () => { + expect(checker.check("1.2.3")).toBe(false); + expect(checker.check("1")).toBe(false); + }) +} +{ + const checker = rangeOf("<1.2.3.4"); + test(`rangeOf("<1.2.3.4") invalid`, () => { + expect(checker.check("2")).toBe(false); + expect(checker.check("1.2.3.5")).toBe(false); + expect(checker.check("1.2.3.4.1")).toBe(false); + expect(checker.check("1.2.3.4")).toBe(false); + }) + + test(`rangeOf("<1.2.3.4") valid`, () => { + expect(checker.check("1.2.3")).toBe(true); + expect(checker.check("1")).toBe(true); + }) +} +{ + const checker = rangeOf("<=1.2.3.4"); + test(`rangeOf("<=1.2.3.4") invalid`, () => { + expect(checker.check("2")).toBe(false); + expect(checker.check("1.2.3.5")).toBe(false); + expect(checker.check("1.2.3.4.1")).toBe(false); + }) + + test(`rangeOf("<=1.2.3.4") valid`, () => { + expect(checker.check("1.2.3")).toBe(true); + expect(checker.check("1")).toBe(true); + expect(checker.check("1.2.3.4")).toBe(true); + }) +} + +{ + + const checkA = rangeOf(">1"); + const checkB = rangeOf("<=2"); + + const checker = rangeAnd(checkA, checkB); + test(`simple and(checkers) valid`, () => { + expect(checker.check("2")).toBe(true); + + expect(checker.check("1.1")).toBe(true); + }) + test(`simple and(checkers) invalid`, () => { + expect(checker.check("2.1")).toBe(false); + expect(checker.check("1")).toBe(false); + expect(checker.check("0")).toBe(false); + }) +} +{ + + const checkA = rangeOf("<1"); + const checkB = rangeOf("=2"); + + const checker = rangeOr(checkA, checkB); + test(`simple or(checkers) valid`, () => { + expect(checker.check("2")).toBe(true); + expect(checker.check("0.1")).toBe(true); + }) + test(`simple or(checkers) invalid`, () => { + expect(checker.check("2.1")).toBe(false); + expect(checker.check("1")).toBe(false); + expect(checker.check("1.1")).toBe(false); + }) +} +{ + const checker = rangeOf('1.2.*'); + test(`rangeOf(1.2.*) valid`, () => { + expect(checker.check("1.2")).toBe(true); + expect(checker.check("1.2.1")).toBe(true); + }) + test(`rangeOf(1.2.*) invalid`, () => { + expect(checker.check("1.3")).toBe(false); + expect(checker.check("1.3.1")).toBe(false); + + expect(checker.check("1.1.1")).toBe(false); + expect(checker.check("1.1")).toBe(false); + expect(checker.check("1")).toBe(false); + + + expect(checker.check("2")).toBe(false); + }) +} \ No newline at end of file From 3cac71aa96687680a0d4b4b59538b3891bd5e4bc Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 12:52:50 -0600 Subject: [PATCH 2/8] feat: add not --- emvar-lite/mod.ts | 7 +++++++ emvar-lite/{range.test.ts => test.ts} | 22 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) rename emvar-lite/{range.test.ts => test.ts} (87%) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index 2963484..01846c4 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -87,6 +87,10 @@ export function rangeOr(...ranges: (string | Checker)[]): Checker { return firstCheck; } +export function notRange(range: string | Checker): Checker { + return rangeOf(range).not(); +} + export class EmVar { static from(range: string | EmVar): EmVar { @@ -148,4 +152,7 @@ export class Checker { public or(other: Checker): Checker { return new Checker((value) => this.check(value) || other.check(value)); } + public not(): Checker { + return new Checker((value) => !this.check(value)); + } } \ No newline at end of file diff --git a/emvar-lite/range.test.ts b/emvar-lite/test.ts similarity index 87% rename from emvar-lite/range.test.ts rename to emvar-lite/test.ts index 62a1f9d..1ad79f9 100644 --- a/emvar-lite/range.test.ts +++ b/emvar-lite/test.ts @@ -1,6 +1,6 @@ import { expect } from "https://deno.land/x/expect@v0.2.9/mod.ts"; -import { rangeAnd, rangeOf, rangeOr } from "./mod.ts"; +import { notRange, rangeAnd, rangeOf, rangeOr } from "./mod.ts"; const { test } = Deno; @@ -137,4 +137,24 @@ const { test } = Deno; expect(checker.check("2")).toBe(false); }) +} + + +{ + const checker = notRange(rangeOf('1.2.*')); + test(`!rangeOf(1.2.*) valid`, () => { + expect(checker.check("1.3")).toBe(true); + expect(checker.check("1.3.1")).toBe(true); + + expect(checker.check("1.1.1")).toBe(true); + expect(checker.check("1.1")).toBe(true); + expect(checker.check("1")).toBe(true); + + + expect(checker.check("2")).toBe(true); + }) + test(`!rangeOf(1.2.*) invalid `, () => { + expect(checker.check("1.2")).toBe(false); + expect(checker.check("1.2.1")).toBe(false); + }) } \ No newline at end of file From 75375c4a289540898e17df7b6a25320fd416b603 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 12:55:52 -0600 Subject: [PATCH 3/8] chore: Testing that we have some ranges for the and and or combinators --- emvar-lite/mod.ts | 6 ++++++ emvar-lite/test.ts | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index 01846c4..55cb718 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -72,6 +72,9 @@ export function rangeOf(range: string | Checker): Checker { } export function rangeAnd(...ranges: (string | Checker)[]): Checker { + if (ranges.length === 0) { + throw new Error('No ranges given'); + } let [firstCheck, ...rest] = ranges.map(rangeOf); for (const checker of rest) { firstCheck = firstCheck.and(checker); @@ -80,6 +83,9 @@ export function rangeAnd(...ranges: (string | Checker)[]): Checker { } export function rangeOr(...ranges: (string | Checker)[]): Checker { + if (ranges.length === 0) { + throw new Error('No ranges given'); + } let [firstCheck, ...rest] = ranges.map(rangeOf); for (const checker of rest) { firstCheck = firstCheck.or(checker); diff --git a/emvar-lite/test.ts b/emvar-lite/test.ts index 1ad79f9..2e93784 100644 --- a/emvar-lite/test.ts +++ b/emvar-lite/test.ts @@ -157,4 +157,13 @@ const { test } = Deno; expect(checker.check("1.2")).toBe(false); expect(checker.check("1.2.1")).toBe(false); }) +} + +{ + test(`no and ranges`, () => { + expect(() => rangeAnd()).toThrow() + }) + test(`no or ranges`, () => { + expect(() => rangeOr()).toThrow() + }) } \ No newline at end of file From 08881c70ee4354ffc0d73f2f7cc41084295c3f96 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 13:04:06 -0600 Subject: [PATCH 4/8] chore: add some docs + use chaining --- emvar-lite/mod.ts | 63 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index 55cb718..c1eff52 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -6,6 +6,12 @@ function incrementLastNumber(list: number[]) { newList[newList.length - 1]++ return newList } +/** + * Will take in a range, like `>1.2` or `<1.2.3.4` or `=1.2` or `1.*` + * and return a checker, that has the check function for checking that a version is in the valid + * @param range + * @returns + */ export function rangeOf(range: string | Checker): Checker { if (range instanceof Checker) { return range @@ -30,14 +36,14 @@ export function rangeOf(range: string | Checker): Checker { const emVar = EmVar.parse(range.substring(2)); return new Checker((version) => { const v = EmVar.from(version); - return v.greaterThan(emVar) || v.equals(emVar); + return v.greaterThanOrEqual(emVar) }) } case '<=': { const emVar = EmVar.parse(range.substring(2)); return new Checker((version) => { const v = EmVar.from(version); - return !v.greaterThan(emVar); + return v.lessThanOrEqual(emVar); }) } @@ -56,7 +62,7 @@ export function rangeOf(range: string | Checker): Checker { const emVar = EmVar.parse(range.substring(1)); return new Checker((version) => { const v = EmVar.from(version); - return !v.greaterThan(emVar) && !v.equals(emVar); + return v.lessThan(emVar) }) } case '=': { @@ -71,6 +77,11 @@ export function rangeOf(range: string | Checker): Checker { throw new Error("Couldn't parse range: " + range); } +/** + * Used to create a checker that will `and` all the ranges passed in + * @param ranges + * @returns + */ export function rangeAnd(...ranges: (string | Checker)[]): Checker { if (ranges.length === 0) { throw new Error('No ranges given'); @@ -82,6 +93,11 @@ export function rangeAnd(...ranges: (string | Checker)[]): Checker { return firstCheck; } +/** + * Used to create a checker that will `or` all the ranges passed in + * @param ranges + * @returns + */ export function rangeOr(...ranges: (string | Checker)[]): Checker { if (ranges.length === 0) { throw new Error('No ranges given'); @@ -93,18 +109,35 @@ export function rangeOr(...ranges: (string | Checker)[]): Checker { return firstCheck; } +/** + * This will negate the checker, so given a checker that checks for >= 1.0.0, it will check for < 1.0.0 + * @param range + * @returns + */ export function notRange(range: string | Checker): Checker { return rangeOf(range).not(); } +/** + * EmVar is a set of versioning of any pattern like 1 or 1.2 or 1.2.3 or 1.2.3.4 or .. + */ export class EmVar { + /** + * Convert the range, should be 1.2.* or * into a emvar + * Or an already made emvar + * IsUnsafe + */ static from(range: string | EmVar): EmVar { if (range instanceof EmVar) { return range } return EmVar.parse(range) } + /** + * Convert the range, should be 1.2.* or * into a emvar + * IsUnsafe + */ static parse(range: string): EmVar { const values = range.split('.').map(x => parseInt(x)); for (const value of values) { @@ -116,6 +149,9 @@ export class EmVar { } private constructor(public readonly values: number[]) { } + /** + * Used when we need a new emvar that has the last number incremented, used in the 1.* like things + */ public withLastIncremented() { return new EmVar(incrementLastNumber(this.values)) } @@ -147,10 +183,29 @@ export class EmVar { } return true; } + public greaterThanOrEqual(other: EmVar): boolean { + return this.greaterThan(other) || this.equals(other); + } + public lessThanOrEqual(other: EmVar): boolean { + return !this.greaterThan(other); + } + public lessThan(other: EmVar): boolean { + return !this.greaterThanOrEqual(other); + } } +/** + * A checker is a function that takes a version and returns true if the version matches the checker. + * Used when we are doing range checking, like saying ">=1.0.0".check("1.2.3") will be true + */ export class Checker { - constructor(public readonly check: (value: string | EmVar) => boolean) { } + constructor( + /** + * Check is the function that will be given a emvar or unparsed emvar and should give if it follows + * a pattern + */ + public readonly check: (value: string | EmVar) => boolean + ) { } public and(other: Checker): Checker { return new Checker((value) => this.check(value) && other.check(value)); From a738d1e76e105131533d02ccd62c70cf04353fee Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 13:11:56 -0600 Subject: [PATCH 5/8] chore: More on the class --- emvar-lite/mod.ts | 176 ++++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 76 deletions(-) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index c1eff52..8c11273 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -13,68 +13,7 @@ function incrementLastNumber(list: number[]) { * @returns */ export function rangeOf(range: string | Checker): Checker { - if (range instanceof Checker) { - return range - } - if (range === '*') return new Checker((version) => { - EmVar.from(version) - return true - }); - const starSubMatches = starSub.exec(range) - if (starSubMatches != null) { - const emVarLower = EmVar.parse(starSubMatches[1]) - const emVarUpper = emVarLower.withLastIncremented() - - return new Checker((version) => { - const v = EmVar.from(version); - return (v.greaterThan(emVarLower) || v.equals(emVarLower)) && !v.greaterThan(emVarUpper) && !v.equals(emVarUpper); - }) - } - - switch (range.substring(0, 2)) { - case '>=': { - const emVar = EmVar.parse(range.substring(2)); - return new Checker((version) => { - const v = EmVar.from(version); - return v.greaterThanOrEqual(emVar) - }) - } - case '<=': { - const emVar = EmVar.parse(range.substring(2)); - return new Checker((version) => { - const v = EmVar.from(version); - return v.lessThanOrEqual(emVar); - }) - } - - } - - switch (range.substring(0, 1)) { - case '>': { - console.log('greaterThan') - const emVar = EmVar.parse(range.substring(1)); - return new Checker((version) => { - const v = EmVar.from(version); - return v.greaterThan(emVar); - }) - } - case '<': { - const emVar = EmVar.parse(range.substring(1)); - return new Checker((version) => { - const v = EmVar.from(version); - return v.lessThan(emVar) - }) - } - case '=': { - const emVar = EmVar.parse(range.substring(1)); - return new Checker((version) => { - const v = EmVar.from(version); - return v.equals(emVar); - }) - } - - } - throw new Error("Couldn't parse range: " + range); + return Checker.parse(range) } /** @@ -86,11 +25,8 @@ export function rangeAnd(...ranges: (string | Checker)[]): Checker { if (ranges.length === 0) { throw new Error('No ranges given'); } - let [firstCheck, ...rest] = ranges.map(rangeOf); - for (const checker of rest) { - firstCheck = firstCheck.and(checker); - } - return firstCheck; + const [firstCheck, ...rest] = ranges; + return Checker.parse(firstCheck).and(...rest); } /** @@ -102,11 +38,8 @@ export function rangeOr(...ranges: (string | Checker)[]): Checker { if (ranges.length === 0) { throw new Error('No ranges given'); } - let [firstCheck, ...rest] = ranges.map(rangeOf); - for (const checker of rest) { - firstCheck = firstCheck.or(checker); - } - return firstCheck; + const [firstCheck, ...rest] = ranges; + return Checker.parse(firstCheck).or(...rest); } /** @@ -199,6 +132,76 @@ export class EmVar { * Used when we are doing range checking, like saying ">=1.0.0".check("1.2.3") will be true */ export class Checker { + /** + * Will take in a range, like `>1.2` or `<1.2.3.4` or `=1.2` or `1.*` + * and return a checker, that has the check function for checking that a version is in the valid + * @param range + * @returns + */ + static parse(range: string | Checker): Checker { + if (range instanceof Checker) { + return range + } + if (range === '*') return new Checker((version) => { + EmVar.from(version) + return true + }); + const starSubMatches = starSub.exec(range) + if (starSubMatches != null) { + const emVarLower = EmVar.parse(starSubMatches[1]) + const emVarUpper = emVarLower.withLastIncremented() + + return new Checker((version) => { + const v = EmVar.from(version); + return (v.greaterThan(emVarLower) || v.equals(emVarLower)) && !v.greaterThan(emVarUpper) && !v.equals(emVarUpper); + }) + } + + switch (range.substring(0, 2)) { + case '>=': { + const emVar = EmVar.parse(range.substring(2)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.greaterThanOrEqual(emVar) + }) + } + case '<=': { + const emVar = EmVar.parse(range.substring(2)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.lessThanOrEqual(emVar); + }) + } + + } + + switch (range.substring(0, 1)) { + case '>': { + console.log('greaterThan') + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.greaterThan(emVar); + }) + } + case '<': { + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.lessThan(emVar) + }) + } + case '=': { + const emVar = EmVar.parse(range.substring(1)); + return new Checker((version) => { + const v = EmVar.from(version); + return v.equals(emVar); + }) + } + + } + throw new Error("Couldn't parse range: " + range); + } constructor( /** * Check is the function that will be given a emvar or unparsed emvar and should give if it follows @@ -207,11 +210,32 @@ export class Checker { public readonly check: (value: string | EmVar) => boolean ) { } - public and(other: Checker): Checker { - return new Checker((value) => this.check(value) && other.check(value)); + + public and(...others: (Checker | string)[]): Checker { + return new Checker((value) => { + if (!this.check(value)) { + return false; + } + for (const other of others) { + if (!Checker.parse(other).check(value)) { + return false + } + } + return true + }); } - public or(other: Checker): Checker { - return new Checker((value) => this.check(value) || other.check(value)); + public or(...others: (Checker | string)[]): Checker { + return new Checker((value) => { + if (this.check(value)) { + return true; + } + for (const other of others) { + if (Checker.parse(other).check(value)) { + return true + } + } + return false + }); } public not(): Checker { return new Checker((value) => !this.check(value)); From ef55bf00602ea50dc76d9b95503c1e9fe353b092 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 13:16:34 -0600 Subject: [PATCH 6/8] feat: Negation at the begining --- emvar-lite/mod.ts | 3 +++ emvar-lite/test.ts | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index 8c11273..e5239b5 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -146,6 +146,9 @@ export class Checker { EmVar.from(version) return true }); + if (range.startsWith('!')) { + return Checker.parse(range.substring(1)).not() + } const starSubMatches = starSub.exec(range) if (starSubMatches != null) { const emVarLower = EmVar.parse(starSubMatches[1]) diff --git a/emvar-lite/test.ts b/emvar-lite/test.ts index 2e93784..4edeba6 100644 --- a/emvar-lite/test.ts +++ b/emvar-lite/test.ts @@ -142,7 +142,7 @@ const { test } = Deno; { const checker = notRange(rangeOf('1.2.*')); - test(`!rangeOf(1.2.*) valid`, () => { + test(`notRange(rangeOf(1.2.*)) valid`, () => { expect(checker.check("1.3")).toBe(true); expect(checker.check("1.3.1")).toBe(true); @@ -153,7 +153,26 @@ const { test } = Deno; expect(checker.check("2")).toBe(true); }) - test(`!rangeOf(1.2.*) invalid `, () => { + test(`notRange(rangeOf(1.2.*)) invalid `, () => { + expect(checker.check("1.2")).toBe(false); + expect(checker.check("1.2.1")).toBe(false); + }) +} + +{ + const checker = rangeOf('!1.2.*'); + test(`!(rangeOf(1.2.*)) valid`, () => { + expect(checker.check("1.3")).toBe(true); + expect(checker.check("1.3.1")).toBe(true); + + expect(checker.check("1.1.1")).toBe(true); + expect(checker.check("1.1")).toBe(true); + expect(checker.check("1")).toBe(true); + + + expect(checker.check("2")).toBe(true); + }) + test(`!(rangeOf(1.2.*)) invalid `, () => { expect(checker.check("1.2")).toBe(false); expect(checker.check("1.2.1")).toBe(false); }) @@ -166,4 +185,18 @@ const { test } = Deno; test(`no or ranges`, () => { expect(() => rangeOr()).toThrow() }) +} +{ + const checker = rangeOf("!>1.2.3.4"); + test(`rangeOf("!>1.2.3.4") invalid`, () => { + expect(checker.check("2")).toBe(false); + expect(checker.check("1.2.3.5")).toBe(false); + expect(checker.check("1.2.3.4.1")).toBe(false); + }) + + test(`rangeOf("!>1.2.3.4") valid`, () => { + expect(checker.check("1.2.3.4")).toBe(true); + expect(checker.check("1.2.3")).toBe(true); + expect(checker.check("1")).toBe(true); + }) } \ No newline at end of file From bd780db93182cd651578bf23a5236630cd611137 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 13:22:42 -0600 Subject: [PATCH 7/8] feat: Anding and or in the parsing --- emvar-lite/mod.ts | 7 +++++++ emvar-lite/test.ts | 29 ++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index e5239b5..5193fbc 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -142,6 +142,13 @@ export class Checker { if (range instanceof Checker) { return range } + range = range.trim(); + if (range.indexOf('&&') !== -1) { + return rangeAnd(...range.split('&&').map(x => Checker.parse(x))); + } + if (range.indexOf('||') !== -1) { + return rangeOr(...range.split('||').map(x => Checker.parse(x))); + } if (range === '*') return new Checker((version) => { EmVar.from(version) return true diff --git a/emvar-lite/test.ts b/emvar-lite/test.ts index 4edeba6..3280ee8 100644 --- a/emvar-lite/test.ts +++ b/emvar-lite/test.ts @@ -199,4 +199,31 @@ const { test } = Deno; expect(checker.check("1.2.3")).toBe(true); expect(checker.check("1")).toBe(true); }) -} \ No newline at end of file +} + +test(">1 && =1.2", () => { + const checker = rangeOf(">1 && =1.2"); + + expect(checker.check("1.2")).toBe(true); + expect(checker.check("1.2.1")).toBe(false); + +}) +test("=1 || =2", () => { + const checker = rangeOf("=1 || =2"); + + expect(checker.check("1")).toBe(true); + expect(checker.check("2")).toBe(true); + expect(checker.check("3")).toBe(false); + +}) + + +test(">1 && =1.2 || =2", () => { + const checker = rangeOf(">1 && =1.2 || =2"); + + expect(checker.check("1.2")).toBe(true); + expect(checker.check("1")).toBe(false); + expect(checker.check("2")).toBe(true); + expect(checker.check("3")).toBe(false); + +}) \ No newline at end of file From 59a827160a91e82533483a5a6e6e89db838a1619 Mon Sep 17 00:00:00 2001 From: BluJ Date: Fri, 15 Jul 2022 13:38:29 -0600 Subject: [PATCH 8/8] chore: Order of operations for the and and or --- emvar-lite/mod.ts | 6 +++--- emvar-lite/test.ts | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/emvar-lite/mod.ts b/emvar-lite/mod.ts index 5193fbc..16991a5 100644 --- a/emvar-lite/mod.ts +++ b/emvar-lite/mod.ts @@ -143,12 +143,12 @@ export class Checker { return range } range = range.trim(); - if (range.indexOf('&&') !== -1) { - return rangeAnd(...range.split('&&').map(x => Checker.parse(x))); - } if (range.indexOf('||') !== -1) { return rangeOr(...range.split('||').map(x => Checker.parse(x))); } + if (range.indexOf('&&') !== -1) { + return rangeAnd(...range.split('&&').map(x => Checker.parse(x))); + } if (range === '*') return new Checker((version) => { EmVar.from(version) return true diff --git a/emvar-lite/test.ts b/emvar-lite/test.ts index 3280ee8..93ac26b 100644 --- a/emvar-lite/test.ts +++ b/emvar-lite/test.ts @@ -226,4 +226,15 @@ test(">1 && =1.2 || =2", () => { expect(checker.check("2")).toBe(true); expect(checker.check("3")).toBe(false); +}) + +test("&& before || order of operationns: <1.5 && >1 || >1.5 && <3", () => { + const checker = rangeOf("<1.5 && >1 || >1.5 && <3"); + expect(checker.check("1.1")).toBe(true); + expect(checker.check("2")).toBe(true); + + expect(checker.check("1.5")).toBe(false); + expect(checker.check("1")).toBe(false); + expect(checker.check("3")).toBe(false); + }) \ No newline at end of file