mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
add documentation for ai agents (#3115)
* add documentation for ai agents * docs: consolidate CLAUDE.md and CONTRIBUTING.md, add style guidelines - Refactor CLAUDE.md to reference CONTRIBUTING.md for build/test/format info - Expand CONTRIBUTING.md with comprehensive build targets, env vars, and testing - Add code style guidelines section with conventional commits - Standardize SDK prettier config to use single quotes (matching web) - Add project-level Claude Code settings to disable co-author attribution * style(sdk): apply prettier with single quotes Run prettier across sdk/base and sdk/package to apply the standardized quote style (single quotes matching web). * docs: add USER.md for per-developer TODO filtering - Add agents/USER.md to .gitignore (contains user identifier) - Document session startup flow in CLAUDE.md: - Create USER.md if missing, prompting for identifier - Filter TODOs by @username tags - Offer relevant TODOs on session start * docs: add i18n documentation task to agent TODOs * docs: document i18n ID patterns in core/ Add agents/i18n-patterns.md covering rust-i18n setup, translation file format, t!() macro usage, key naming conventions, and locale selection. Remove completed TODO item and add reference in CLAUDE.md. * chore: clarify that all builds work on any OS with Docker
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import { DeepMap } from "deep-equality-data-structures"
|
||||
import * as P from "./exver"
|
||||
import { DeepMap } from 'deep-equality-data-structures'
|
||||
import * as P from './exver'
|
||||
|
||||
// prettier-ignore
|
||||
export type ValidateVersion<T extends String> =
|
||||
@@ -22,35 +22,35 @@ export type ValidateExVers<T> =
|
||||
never[]
|
||||
|
||||
type Anchor = {
|
||||
type: "Anchor"
|
||||
type: 'Anchor'
|
||||
operator: P.CmpOp
|
||||
version: ExtendedVersion
|
||||
}
|
||||
|
||||
type And = {
|
||||
type: "And"
|
||||
type: 'And'
|
||||
left: VersionRange
|
||||
right: VersionRange
|
||||
}
|
||||
|
||||
type Or = {
|
||||
type: "Or"
|
||||
type: 'Or'
|
||||
left: VersionRange
|
||||
right: VersionRange
|
||||
}
|
||||
|
||||
type Not = {
|
||||
type: "Not"
|
||||
type: 'Not'
|
||||
value: VersionRange
|
||||
}
|
||||
|
||||
type Flavor = {
|
||||
type: "Flavor"
|
||||
type: 'Flavor'
|
||||
flavor: string | null
|
||||
}
|
||||
|
||||
type FlavorNot = {
|
||||
type: "FlavorNot"
|
||||
type: 'FlavorNot'
|
||||
flavors: Set<string | null>
|
||||
}
|
||||
|
||||
@@ -107,8 +107,8 @@ function adjacentVersionRangePoints(
|
||||
}
|
||||
|
||||
function flavorAnd(a: FlavorAtom, b: FlavorAtom): FlavorAtom | null {
|
||||
if (a.type == "Flavor") {
|
||||
if (b.type == "Flavor") {
|
||||
if (a.type == 'Flavor') {
|
||||
if (b.type == 'Flavor') {
|
||||
if (a.flavor == b.flavor) {
|
||||
return a
|
||||
} else {
|
||||
@@ -122,7 +122,7 @@ function flavorAnd(a: FlavorAtom, b: FlavorAtom): FlavorAtom | null {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (b.type == "Flavor") {
|
||||
if (b.type == 'Flavor') {
|
||||
if (a.flavors.has(b.flavor)) {
|
||||
return null
|
||||
} else {
|
||||
@@ -131,7 +131,7 @@ function flavorAnd(a: FlavorAtom, b: FlavorAtom): FlavorAtom | null {
|
||||
} else {
|
||||
// TODO: use Set.union if targeting esnext or later
|
||||
return {
|
||||
type: "FlavorNot",
|
||||
type: 'FlavorNot',
|
||||
flavors: new Set([...a.flavors, ...b.flavors]),
|
||||
}
|
||||
}
|
||||
@@ -218,12 +218,12 @@ class VersionRangeTable {
|
||||
static eqFlavor(flavor: string | null): VersionRangeTables {
|
||||
return new DeepMap([
|
||||
[
|
||||
{ type: "Flavor", flavor } as FlavorAtom,
|
||||
{ type: 'Flavor', flavor } as FlavorAtom,
|
||||
new VersionRangeTable([], [true]),
|
||||
],
|
||||
// make sure the truth table is exhaustive, or `not` will not work properly.
|
||||
[
|
||||
{ type: "FlavorNot", flavors: new Set([flavor]) } as FlavorAtom,
|
||||
{ type: 'FlavorNot', flavors: new Set([flavor]) } as FlavorAtom,
|
||||
new VersionRangeTable([], [false]),
|
||||
],
|
||||
])
|
||||
@@ -241,12 +241,12 @@ class VersionRangeTable {
|
||||
): VersionRangeTables {
|
||||
return new DeepMap([
|
||||
[
|
||||
{ type: "Flavor", flavor } as FlavorAtom,
|
||||
{ type: 'Flavor', flavor } as FlavorAtom,
|
||||
new VersionRangeTable([point], [left, right]),
|
||||
],
|
||||
// make sure the truth table is exhaustive, or `not` will not work properly.
|
||||
[
|
||||
{ type: "FlavorNot", flavors: new Set([flavor]) } as FlavorAtom,
|
||||
{ type: 'FlavorNot', flavors: new Set([flavor]) } as FlavorAtom,
|
||||
new VersionRangeTable([], [false]),
|
||||
],
|
||||
])
|
||||
@@ -383,7 +383,7 @@ class VersionRangeTable {
|
||||
let sum_terms: VersionRange[] = []
|
||||
for (let [flavor, table] of tables) {
|
||||
let cmp_flavor = null
|
||||
if (flavor.type == "Flavor") {
|
||||
if (flavor.type == 'Flavor') {
|
||||
cmp_flavor = flavor.flavor
|
||||
}
|
||||
for (let i = 0; i < table.values.length; i++) {
|
||||
@@ -392,7 +392,7 @@ class VersionRangeTable {
|
||||
continue
|
||||
}
|
||||
|
||||
if (flavor.type == "FlavorNot") {
|
||||
if (flavor.type == 'FlavorNot') {
|
||||
for (let not_flavor of flavor.flavors) {
|
||||
term.push(VersionRange.flavor(not_flavor).not())
|
||||
}
|
||||
@@ -410,7 +410,7 @@ class VersionRangeTable {
|
||||
if (p != null && q != null && adjacentVersionRangePoints(p, q)) {
|
||||
term.push(
|
||||
VersionRange.anchor(
|
||||
"=",
|
||||
'=',
|
||||
new ExtendedVersion(cmp_flavor, p.upstream, p.downstream),
|
||||
),
|
||||
)
|
||||
@@ -418,7 +418,7 @@ class VersionRangeTable {
|
||||
if (p != null && p.side < 0) {
|
||||
term.push(
|
||||
VersionRange.anchor(
|
||||
">=",
|
||||
'>=',
|
||||
new ExtendedVersion(cmp_flavor, p.upstream, p.downstream),
|
||||
),
|
||||
)
|
||||
@@ -426,7 +426,7 @@ class VersionRangeTable {
|
||||
if (p != null && p.side >= 0) {
|
||||
term.push(
|
||||
VersionRange.anchor(
|
||||
">",
|
||||
'>',
|
||||
new ExtendedVersion(cmp_flavor, p.upstream, p.downstream),
|
||||
),
|
||||
)
|
||||
@@ -434,7 +434,7 @@ class VersionRangeTable {
|
||||
if (q != null && q.side < 0) {
|
||||
term.push(
|
||||
VersionRange.anchor(
|
||||
"<",
|
||||
'<',
|
||||
new ExtendedVersion(cmp_flavor, q.upstream, q.downstream),
|
||||
),
|
||||
)
|
||||
@@ -442,7 +442,7 @@ class VersionRangeTable {
|
||||
if (q != null && q.side >= 0) {
|
||||
term.push(
|
||||
VersionRange.anchor(
|
||||
"<=",
|
||||
'<=',
|
||||
new ExtendedVersion(cmp_flavor, q.upstream, q.downstream),
|
||||
),
|
||||
)
|
||||
@@ -463,26 +463,26 @@ class VersionRangeTable {
|
||||
export class VersionRange {
|
||||
constructor(public atom: Anchor | And | Or | Not | P.Any | P.None | Flavor) {}
|
||||
|
||||
toStringParens(parent: "And" | "Or" | "Not") {
|
||||
toStringParens(parent: 'And' | 'Or' | 'Not') {
|
||||
let needs = true
|
||||
switch (this.atom.type) {
|
||||
case "And":
|
||||
case "Or":
|
||||
case 'And':
|
||||
case 'Or':
|
||||
needs = parent != this.atom.type
|
||||
break
|
||||
case "Anchor":
|
||||
case "Any":
|
||||
case "None":
|
||||
needs = parent == "Not"
|
||||
case 'Anchor':
|
||||
case 'Any':
|
||||
case 'None':
|
||||
needs = parent == 'Not'
|
||||
break
|
||||
case "Not":
|
||||
case "Flavor":
|
||||
case 'Not':
|
||||
case 'Flavor':
|
||||
needs = false
|
||||
break
|
||||
}
|
||||
|
||||
if (needs) {
|
||||
return "(" + this.toString() + ")"
|
||||
return '(' + this.toString() + ')'
|
||||
} else {
|
||||
return this.toString()
|
||||
}
|
||||
@@ -490,36 +490,36 @@ export class VersionRange {
|
||||
|
||||
toString(): string {
|
||||
switch (this.atom.type) {
|
||||
case "Anchor":
|
||||
case 'Anchor':
|
||||
return `${this.atom.operator}${this.atom.version}`
|
||||
case "And":
|
||||
case 'And':
|
||||
return `${this.atom.left.toStringParens(this.atom.type)} && ${this.atom.right.toStringParens(this.atom.type)}`
|
||||
case "Or":
|
||||
case 'Or':
|
||||
return `${this.atom.left.toStringParens(this.atom.type)} || ${this.atom.right.toStringParens(this.atom.type)}`
|
||||
case "Not":
|
||||
case 'Not':
|
||||
return `!${this.atom.value.toStringParens(this.atom.type)}`
|
||||
case "Flavor":
|
||||
case 'Flavor':
|
||||
return this.atom.flavor == null ? `#` : `#${this.atom.flavor}`
|
||||
case "Any":
|
||||
return "*"
|
||||
case "None":
|
||||
return "!"
|
||||
case 'Any':
|
||||
return '*'
|
||||
case 'None':
|
||||
return '!'
|
||||
}
|
||||
}
|
||||
|
||||
private static parseAtom(atom: P.VersionRangeAtom): VersionRange {
|
||||
switch (atom.type) {
|
||||
case "Not":
|
||||
case 'Not':
|
||||
return new VersionRange({
|
||||
type: "Not",
|
||||
type: 'Not',
|
||||
value: VersionRange.parseAtom(atom.value),
|
||||
})
|
||||
case "Parens":
|
||||
case 'Parens':
|
||||
return VersionRange.parseRange(atom.expr)
|
||||
case "Anchor":
|
||||
case 'Anchor':
|
||||
return new VersionRange({
|
||||
type: "Anchor",
|
||||
operator: atom.operator || "^",
|
||||
type: 'Anchor',
|
||||
operator: atom.operator || '^',
|
||||
version: new ExtendedVersion(
|
||||
atom.version.flavor,
|
||||
new Version(
|
||||
@@ -532,7 +532,7 @@ export class VersionRange {
|
||||
),
|
||||
),
|
||||
})
|
||||
case "Flavor":
|
||||
case 'Flavor':
|
||||
return VersionRange.flavor(atom.flavor)
|
||||
default:
|
||||
return new VersionRange(atom)
|
||||
@@ -543,17 +543,17 @@ export class VersionRange {
|
||||
let result = VersionRange.parseAtom(range[0])
|
||||
for (const next of range[1]) {
|
||||
switch (next[1]?.[0]) {
|
||||
case "||":
|
||||
case '||':
|
||||
result = new VersionRange({
|
||||
type: "Or",
|
||||
type: 'Or',
|
||||
left: result,
|
||||
right: VersionRange.parseAtom(next[2]),
|
||||
})
|
||||
break
|
||||
case "&&":
|
||||
case '&&':
|
||||
default:
|
||||
result = new VersionRange({
|
||||
type: "And",
|
||||
type: 'And',
|
||||
left: result,
|
||||
right: VersionRange.parseAtom(next[2]),
|
||||
})
|
||||
@@ -565,49 +565,49 @@ export class VersionRange {
|
||||
|
||||
static parse(range: string): VersionRange {
|
||||
return VersionRange.parseRange(
|
||||
P.parse(range, { startRule: "VersionRange" }),
|
||||
P.parse(range, { startRule: 'VersionRange' }),
|
||||
)
|
||||
}
|
||||
|
||||
static anchor(operator: P.CmpOp, version: ExtendedVersion) {
|
||||
return new VersionRange({ type: "Anchor", operator, version })
|
||||
return new VersionRange({ type: 'Anchor', operator, version })
|
||||
}
|
||||
|
||||
static flavor(flavor: string | null) {
|
||||
return new VersionRange({ type: "Flavor", flavor })
|
||||
return new VersionRange({ type: 'Flavor', flavor })
|
||||
}
|
||||
|
||||
static parseEmver(range: string): VersionRange {
|
||||
return VersionRange.parseRange(
|
||||
P.parse(range, { startRule: "EmverVersionRange" }),
|
||||
P.parse(range, { startRule: 'EmverVersionRange' }),
|
||||
)
|
||||
}
|
||||
|
||||
and(right: VersionRange) {
|
||||
return new VersionRange({ type: "And", left: this, right })
|
||||
return new VersionRange({ type: 'And', left: this, right })
|
||||
}
|
||||
|
||||
or(right: VersionRange) {
|
||||
return new VersionRange({ type: "Or", left: this, right })
|
||||
return new VersionRange({ type: 'Or', left: this, right })
|
||||
}
|
||||
|
||||
not() {
|
||||
return new VersionRange({ type: "Not", value: this })
|
||||
return new VersionRange({ type: 'Not', value: this })
|
||||
}
|
||||
|
||||
static and(...xs: Array<VersionRange>) {
|
||||
let y = VersionRange.any()
|
||||
for (let x of xs) {
|
||||
if (x.atom.type == "Any") {
|
||||
if (x.atom.type == 'Any') {
|
||||
continue
|
||||
}
|
||||
if (x.atom.type == "None") {
|
||||
if (x.atom.type == 'None') {
|
||||
return x
|
||||
}
|
||||
if (y.atom.type == "Any") {
|
||||
if (y.atom.type == 'Any') {
|
||||
y = x
|
||||
} else {
|
||||
y = new VersionRange({ type: "And", left: y, right: x })
|
||||
y = new VersionRange({ type: 'And', left: y, right: x })
|
||||
}
|
||||
}
|
||||
return y
|
||||
@@ -616,27 +616,27 @@ export class VersionRange {
|
||||
static or(...xs: Array<VersionRange>) {
|
||||
let y = VersionRange.none()
|
||||
for (let x of xs) {
|
||||
if (x.atom.type == "None") {
|
||||
if (x.atom.type == 'None') {
|
||||
continue
|
||||
}
|
||||
if (x.atom.type == "Any") {
|
||||
if (x.atom.type == 'Any') {
|
||||
return x
|
||||
}
|
||||
if (y.atom.type == "None") {
|
||||
if (y.atom.type == 'None') {
|
||||
y = x
|
||||
} else {
|
||||
y = new VersionRange({ type: "Or", left: y, right: x })
|
||||
y = new VersionRange({ type: 'Or', left: y, right: x })
|
||||
}
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
static any() {
|
||||
return new VersionRange({ type: "Any" })
|
||||
return new VersionRange({ type: 'Any' })
|
||||
}
|
||||
|
||||
static none() {
|
||||
return new VersionRange({ type: "None" })
|
||||
return new VersionRange({ type: 'None' })
|
||||
}
|
||||
|
||||
satisfiedBy(version: Version | ExtendedVersion) {
|
||||
@@ -645,23 +645,23 @@ export class VersionRange {
|
||||
|
||||
tables(): VersionRangeTables {
|
||||
switch (this.atom.type) {
|
||||
case "Anchor":
|
||||
case 'Anchor':
|
||||
switch (this.atom.operator) {
|
||||
case "=":
|
||||
case '=':
|
||||
// `=1.2.3` is equivalent to `>=1.2.3 && <=1.2.4 && #flavor`
|
||||
return VersionRangeTable.and(
|
||||
VersionRangeTable.cmp(this.atom.version, -1, false, true),
|
||||
VersionRangeTable.cmp(this.atom.version, 1, true, false),
|
||||
)
|
||||
case ">":
|
||||
case '>':
|
||||
return VersionRangeTable.cmp(this.atom.version, 1, false, true)
|
||||
case "<":
|
||||
case '<':
|
||||
return VersionRangeTable.cmp(this.atom.version, -1, true, false)
|
||||
case ">=":
|
||||
case '>=':
|
||||
return VersionRangeTable.cmp(this.atom.version, -1, false, true)
|
||||
case "<=":
|
||||
case '<=':
|
||||
return VersionRangeTable.cmp(this.atom.version, 1, true, false)
|
||||
case "!=":
|
||||
case '!=':
|
||||
// `!=1.2.3` is equivalent to `!(>=1.2.3 && <=1.2.3 && #flavor)`
|
||||
// **not** equivalent to `(<1.2.3 || >1.2.3) && #flavor`
|
||||
return VersionRangeTable.not(
|
||||
@@ -670,7 +670,7 @@ export class VersionRange {
|
||||
VersionRangeTable.cmp(this.atom.version, 1, true, false),
|
||||
),
|
||||
)
|
||||
case "^":
|
||||
case '^':
|
||||
// `^1.2.3` is equivalent to `>=1.2.3 && <2.0.0 && #flavor`
|
||||
return VersionRangeTable.and(
|
||||
VersionRangeTable.cmp(this.atom.version, -1, false, true),
|
||||
@@ -681,7 +681,7 @@ export class VersionRange {
|
||||
false,
|
||||
),
|
||||
)
|
||||
case "~":
|
||||
case '~':
|
||||
// `~1.2.3` is equivalent to `>=1.2.3 && <1.3.0 && #flavor`
|
||||
return VersionRangeTable.and(
|
||||
VersionRangeTable.cmp(this.atom.version, -1, false, true),
|
||||
@@ -693,23 +693,23 @@ export class VersionRange {
|
||||
),
|
||||
)
|
||||
}
|
||||
case "Flavor":
|
||||
case 'Flavor':
|
||||
return VersionRangeTable.eqFlavor(this.atom.flavor)
|
||||
case "Not":
|
||||
case 'Not':
|
||||
return VersionRangeTable.not(this.atom.value.tables())
|
||||
case "And":
|
||||
case 'And':
|
||||
return VersionRangeTable.and(
|
||||
this.atom.left.tables(),
|
||||
this.atom.right.tables(),
|
||||
)
|
||||
case "Or":
|
||||
case 'Or':
|
||||
return VersionRangeTable.or(
|
||||
this.atom.left.tables(),
|
||||
this.atom.right.tables(),
|
||||
)
|
||||
case "Any":
|
||||
case 'Any':
|
||||
return true
|
||||
case "None":
|
||||
case 'None':
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -734,23 +734,23 @@ export class Version {
|
||||
) {}
|
||||
|
||||
toString(): string {
|
||||
return `${this.number.join(".")}${this.prerelease.length > 0 ? `-${this.prerelease.join(".")}` : ""}`
|
||||
return `${this.number.join('.')}${this.prerelease.length > 0 ? `-${this.prerelease.join('.')}` : ''}`
|
||||
}
|
||||
|
||||
compare(other: Version): "greater" | "equal" | "less" {
|
||||
compare(other: Version): 'greater' | 'equal' | 'less' {
|
||||
const numLen = Math.max(this.number.length, other.number.length)
|
||||
for (let i = 0; i < numLen; i++) {
|
||||
if ((this.number[i] || 0) > (other.number[i] || 0)) {
|
||||
return "greater"
|
||||
return 'greater'
|
||||
} else if ((this.number[i] || 0) < (other.number[i] || 0)) {
|
||||
return "less"
|
||||
return 'less'
|
||||
}
|
||||
}
|
||||
|
||||
if (this.prerelease.length === 0 && other.prerelease.length !== 0) {
|
||||
return "greater"
|
||||
return 'greater'
|
||||
} else if (this.prerelease.length !== 0 && other.prerelease.length === 0) {
|
||||
return "less"
|
||||
return 'less'
|
||||
}
|
||||
|
||||
const prereleaseLen = Math.max(
|
||||
@@ -760,42 +760,42 @@ export class Version {
|
||||
for (let i = 0; i < prereleaseLen; i++) {
|
||||
if (typeof this.prerelease[i] === typeof other.prerelease[i]) {
|
||||
if (this.prerelease[i] > other.prerelease[i]) {
|
||||
return "greater"
|
||||
return 'greater'
|
||||
} else if (this.prerelease[i] < other.prerelease[i]) {
|
||||
return "less"
|
||||
return 'less'
|
||||
}
|
||||
} else {
|
||||
switch (`${typeof this.prerelease[1]}:${typeof other.prerelease[i]}`) {
|
||||
case "number:string":
|
||||
return "less"
|
||||
case "string:number":
|
||||
return "greater"
|
||||
case "number:undefined":
|
||||
case "string:undefined":
|
||||
return "greater"
|
||||
case "undefined:number":
|
||||
case "undefined:string":
|
||||
return "less"
|
||||
case 'number:string':
|
||||
return 'less'
|
||||
case 'string:number':
|
||||
return 'greater'
|
||||
case 'number:undefined':
|
||||
case 'string:undefined':
|
||||
return 'greater'
|
||||
case 'undefined:number':
|
||||
case 'undefined:string':
|
||||
return 'less'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "equal"
|
||||
return 'equal'
|
||||
}
|
||||
|
||||
compareForSort(other: Version): -1 | 0 | 1 {
|
||||
switch (this.compare(other)) {
|
||||
case "greater":
|
||||
case 'greater':
|
||||
return 1
|
||||
case "equal":
|
||||
case 'equal':
|
||||
return 0
|
||||
case "less":
|
||||
case 'less':
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
static parse(version: string): Version {
|
||||
const parsed = P.parse(version, { startRule: "Version" })
|
||||
const parsed = P.parse(version, { startRule: 'Version' })
|
||||
return new Version(parsed.number, parsed.prerelease)
|
||||
}
|
||||
|
||||
@@ -815,25 +815,25 @@ export class ExtendedVersion {
|
||||
) {}
|
||||
|
||||
toString(): string {
|
||||
return `${this.flavor ? `#${this.flavor}:` : ""}${this.upstream.toString()}:${this.downstream.toString()}`
|
||||
return `${this.flavor ? `#${this.flavor}:` : ''}${this.upstream.toString()}:${this.downstream.toString()}`
|
||||
}
|
||||
|
||||
compare(other: ExtendedVersion): "greater" | "equal" | "less" | null {
|
||||
compare(other: ExtendedVersion): 'greater' | 'equal' | 'less' | null {
|
||||
if (this.flavor !== other.flavor) {
|
||||
return null
|
||||
}
|
||||
const upstreamCmp = this.upstream.compare(other.upstream)
|
||||
if (upstreamCmp !== "equal") {
|
||||
if (upstreamCmp !== 'equal') {
|
||||
return upstreamCmp
|
||||
}
|
||||
return this.downstream.compare(other.downstream)
|
||||
}
|
||||
|
||||
compareLexicographic(other: ExtendedVersion): "greater" | "equal" | "less" {
|
||||
if ((this.flavor || "") > (other.flavor || "")) {
|
||||
return "greater"
|
||||
} else if ((this.flavor || "") > (other.flavor || "")) {
|
||||
return "less"
|
||||
compareLexicographic(other: ExtendedVersion): 'greater' | 'equal' | 'less' {
|
||||
if ((this.flavor || '') > (other.flavor || '')) {
|
||||
return 'greater'
|
||||
} else if ((this.flavor || '') > (other.flavor || '')) {
|
||||
return 'less'
|
||||
} else {
|
||||
return this.compare(other)!
|
||||
}
|
||||
@@ -841,37 +841,37 @@ export class ExtendedVersion {
|
||||
|
||||
compareForSort(other: ExtendedVersion): 1 | 0 | -1 {
|
||||
switch (this.compareLexicographic(other)) {
|
||||
case "greater":
|
||||
case 'greater':
|
||||
return 1
|
||||
case "equal":
|
||||
case 'equal':
|
||||
return 0
|
||||
case "less":
|
||||
case 'less':
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
greaterThan(other: ExtendedVersion): boolean {
|
||||
return this.compare(other) === "greater"
|
||||
return this.compare(other) === 'greater'
|
||||
}
|
||||
|
||||
greaterThanOrEqual(other: ExtendedVersion): boolean {
|
||||
return ["greater", "equal"].includes(this.compare(other) as string)
|
||||
return ['greater', 'equal'].includes(this.compare(other) as string)
|
||||
}
|
||||
|
||||
equals(other: ExtendedVersion): boolean {
|
||||
return this.compare(other) === "equal"
|
||||
return this.compare(other) === 'equal'
|
||||
}
|
||||
|
||||
lessThan(other: ExtendedVersion): boolean {
|
||||
return this.compare(other) === "less"
|
||||
return this.compare(other) === 'less'
|
||||
}
|
||||
|
||||
lessThanOrEqual(other: ExtendedVersion): boolean {
|
||||
return ["less", "equal"].includes(this.compare(other) as string)
|
||||
return ['less', 'equal'].includes(this.compare(other) as string)
|
||||
}
|
||||
|
||||
static parse(extendedVersion: string): ExtendedVersion {
|
||||
const parsed = P.parse(extendedVersion, { startRule: "ExtendedVersion" })
|
||||
const parsed = P.parse(extendedVersion, { startRule: 'ExtendedVersion' })
|
||||
return new ExtendedVersion(
|
||||
parsed.flavor || null,
|
||||
new Version(parsed.upstream.number, parsed.upstream.prerelease),
|
||||
@@ -881,7 +881,7 @@ export class ExtendedVersion {
|
||||
|
||||
static parseEmver(extendedVersion: string): ExtendedVersion {
|
||||
try {
|
||||
const parsed = P.parse(extendedVersion, { startRule: "Emver" })
|
||||
const parsed = P.parse(extendedVersion, { startRule: 'Emver' })
|
||||
return new ExtendedVersion(
|
||||
parsed.flavor || null,
|
||||
new Version(parsed.upstream.number, parsed.upstream.prerelease),
|
||||
@@ -956,22 +956,22 @@ export class ExtendedVersion {
|
||||
*/
|
||||
satisfies(versionRange: VersionRange): boolean {
|
||||
switch (versionRange.atom.type) {
|
||||
case "Anchor":
|
||||
case 'Anchor':
|
||||
const otherVersion = versionRange.atom.version
|
||||
switch (versionRange.atom.operator) {
|
||||
case "=":
|
||||
case '=':
|
||||
return this.equals(otherVersion)
|
||||
case ">":
|
||||
case '>':
|
||||
return this.greaterThan(otherVersion)
|
||||
case "<":
|
||||
case '<':
|
||||
return this.lessThan(otherVersion)
|
||||
case ">=":
|
||||
case '>=':
|
||||
return this.greaterThanOrEqual(otherVersion)
|
||||
case "<=":
|
||||
case '<=':
|
||||
return this.lessThanOrEqual(otherVersion)
|
||||
case "!=":
|
||||
case '!=':
|
||||
return !this.equals(otherVersion)
|
||||
case "^":
|
||||
case '^':
|
||||
const nextMajor = versionRange.atom.version.incrementMajor()
|
||||
if (
|
||||
this.greaterThanOrEqual(otherVersion) &&
|
||||
@@ -981,7 +981,7 @@ export class ExtendedVersion {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case "~":
|
||||
case '~':
|
||||
const nextMinor = versionRange.atom.version.incrementMinor()
|
||||
if (
|
||||
this.greaterThanOrEqual(otherVersion) &&
|
||||
@@ -992,23 +992,23 @@ export class ExtendedVersion {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case "Flavor":
|
||||
case 'Flavor':
|
||||
return versionRange.atom.flavor == this.flavor
|
||||
case "And":
|
||||
case 'And':
|
||||
return (
|
||||
this.satisfies(versionRange.atom.left) &&
|
||||
this.satisfies(versionRange.atom.right)
|
||||
)
|
||||
case "Or":
|
||||
case 'Or':
|
||||
return (
|
||||
this.satisfies(versionRange.atom.left) ||
|
||||
this.satisfies(versionRange.atom.right)
|
||||
)
|
||||
case "Not":
|
||||
case 'Not':
|
||||
return !this.satisfies(versionRange.atom.value)
|
||||
case "Any":
|
||||
case 'Any':
|
||||
return true
|
||||
case "None":
|
||||
case 'None':
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1020,34 +1020,34 @@ export const testTypeVersion = <T extends string>(t: T & ValidateVersion<T>) =>
|
||||
t
|
||||
|
||||
function tests() {
|
||||
testTypeVersion("1.2.3")
|
||||
testTypeVersion("1")
|
||||
testTypeVersion("12.34.56")
|
||||
testTypeVersion("1.2-3")
|
||||
testTypeVersion("1-3")
|
||||
testTypeVersion("1-alpha")
|
||||
testTypeVersion('1.2.3')
|
||||
testTypeVersion('1')
|
||||
testTypeVersion('12.34.56')
|
||||
testTypeVersion('1.2-3')
|
||||
testTypeVersion('1-3')
|
||||
testTypeVersion('1-alpha')
|
||||
// @ts-expect-error
|
||||
testTypeVersion("-3")
|
||||
testTypeVersion('-3')
|
||||
// @ts-expect-error
|
||||
testTypeVersion("1.2.3:1")
|
||||
testTypeVersion('1.2.3:1')
|
||||
// @ts-expect-error
|
||||
testTypeVersion("#cat:1:1")
|
||||
testTypeVersion('#cat:1:1')
|
||||
|
||||
testTypeExVer("1.2.3:1.2.3")
|
||||
testTypeExVer("1.2.3.4.5.6.7.8.9.0:1")
|
||||
testTypeExVer("100:1")
|
||||
testTypeExVer("#cat:1:1")
|
||||
testTypeExVer("1.2.3.4.5.6.7.8.9.11.22.33:1")
|
||||
testTypeExVer("1-0:1")
|
||||
testTypeExVer("1-0:1")
|
||||
testTypeExVer('1.2.3:1.2.3')
|
||||
testTypeExVer('1.2.3.4.5.6.7.8.9.0:1')
|
||||
testTypeExVer('100:1')
|
||||
testTypeExVer('#cat:1:1')
|
||||
testTypeExVer('1.2.3.4.5.6.7.8.9.11.22.33:1')
|
||||
testTypeExVer('1-0:1')
|
||||
testTypeExVer('1-0:1')
|
||||
// @ts-expect-error
|
||||
testTypeExVer("1.2-3")
|
||||
testTypeExVer('1.2-3')
|
||||
// @ts-expect-error
|
||||
testTypeExVer("1-3")
|
||||
testTypeExVer('1-3')
|
||||
// @ts-expect-error
|
||||
testTypeExVer("1.2.3.4.5.6.7.8.9.0.10:1" as string)
|
||||
testTypeExVer('1.2.3.4.5.6.7.8.9.0.10:1' as string)
|
||||
// @ts-expect-error
|
||||
testTypeExVer("1.-2:1")
|
||||
testTypeExVer('1.-2:1')
|
||||
// @ts-expect-error
|
||||
testTypeExVer("1..2.3:3")
|
||||
testTypeExVer('1..2.3:3')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user