mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
redesign checkDependencies api
This commit is contained in:
@@ -75,7 +75,10 @@ import * as T from "./types"
|
|||||||
import { testTypeVersion, ValidateExVer } from "./exver"
|
import { testTypeVersion, ValidateExVer } from "./exver"
|
||||||
import { ExposedStorePaths } from "./store/setupExposeStore"
|
import { ExposedStorePaths } from "./store/setupExposeStore"
|
||||||
import { PathBuilder, extractJsonPath, pathBuilder } from "./store/PathBuilder"
|
import { PathBuilder, extractJsonPath, pathBuilder } from "./store/PathBuilder"
|
||||||
import { checkAllDependencies } from "./dependencies/dependencies"
|
import {
|
||||||
|
CheckDependencies,
|
||||||
|
checkDependencies,
|
||||||
|
} from "./dependencies/dependencies"
|
||||||
import { health } from "."
|
import { health } from "."
|
||||||
import { GetSslCertificate } from "./util/GetSslCertificate"
|
import { GetSslCertificate } from "./util/GetSslCertificate"
|
||||||
|
|
||||||
@@ -142,7 +145,13 @@ export class StartSdk<Manifest extends T.Manifest, Store> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
checkAllDependencies,
|
checkDependencies: checkDependencies as <
|
||||||
|
DependencyId extends keyof Manifest["dependencies"] &
|
||||||
|
PackageId = keyof Manifest["dependencies"] & PackageId,
|
||||||
|
>(
|
||||||
|
effects: Effects,
|
||||||
|
packageIds?: DependencyId[],
|
||||||
|
) => Promise<CheckDependencies<DependencyId>>,
|
||||||
serviceInterface: {
|
serviceInterface: {
|
||||||
getOwn: <E extends Effects>(effects: E, id: ServiceInterfaceId) =>
|
getOwn: <E extends Effects>(effects: E, id: ServiceInterfaceId) =>
|
||||||
removeCallbackTypes<E>(effects)(
|
removeCallbackTypes<E>(effects)(
|
||||||
|
|||||||
@@ -1,131 +1,206 @@
|
|||||||
|
import { ExtendedVersion, VersionRange } from "../exver"
|
||||||
import {
|
import {
|
||||||
Effects,
|
Effects,
|
||||||
PackageId,
|
PackageId,
|
||||||
DependencyRequirement,
|
DependencyRequirement,
|
||||||
SetHealth,
|
SetHealth,
|
||||||
CheckDependenciesResult,
|
CheckDependenciesResult,
|
||||||
|
HealthCheckId,
|
||||||
} from "../types"
|
} from "../types"
|
||||||
|
|
||||||
export type CheckAllDependencies = {
|
export type CheckDependencies<DependencyId extends PackageId = PackageId> = {
|
||||||
notInstalled: () => Promise<CheckDependenciesResult[]>
|
installedSatisfied: (packageId: DependencyId) => boolean
|
||||||
notRunning: () => Promise<CheckDependenciesResult[]>
|
installedVersionSatisfied: (packageId: DependencyId) => boolean
|
||||||
configNotSatisfied: () => Promise<CheckDependenciesResult[]>
|
runningSatisfied: (packageId: DependencyId) => boolean
|
||||||
healthErrors: () => Promise<{ [id: string]: SetHealth[] }>
|
configSatisfied: (packageId: DependencyId) => boolean
|
||||||
|
healthCheckSatisfied: (
|
||||||
|
packageId: DependencyId,
|
||||||
|
healthCheckId: HealthCheckId,
|
||||||
|
) => boolean
|
||||||
|
satisfied: () => boolean
|
||||||
|
|
||||||
isValid: () => Promise<boolean>
|
throwIfInstalledNotSatisfied: (packageId: DependencyId) => void
|
||||||
|
throwIfInstalledVersionNotSatisfied: (packageId: DependencyId) => void
|
||||||
throwIfNotRunning: () => Promise<void>
|
throwIfRunningNotSatisfied: (packageId: DependencyId) => void
|
||||||
throwIfNotInstalled: () => Promise<void>
|
throwIfConfigNotSatisfied: (packageId: DependencyId) => void
|
||||||
throwIfConfigNotSatisfied: () => Promise<void>
|
throwIfHealthNotSatisfied: (
|
||||||
throwIfHealthError: () => Promise<void>
|
packageId: DependencyId,
|
||||||
|
healthCheckId?: HealthCheckId,
|
||||||
throwIfNotValid: () => Promise<void>
|
) => void
|
||||||
|
throwIfNotSatisfied: (packageId?: DependencyId) => void
|
||||||
}
|
}
|
||||||
export function checkAllDependencies(effects: Effects): CheckAllDependencies {
|
export async function checkDependencies<
|
||||||
const dependenciesPromise = effects.getDependencies()
|
DependencyId extends PackageId = PackageId,
|
||||||
const resultsPromise = dependenciesPromise.then((dependencies) =>
|
>(
|
||||||
|
effects: Effects,
|
||||||
|
packageIds?: DependencyId[],
|
||||||
|
): Promise<CheckDependencies<DependencyId>> {
|
||||||
|
let [dependencies, results] = await Promise.all([
|
||||||
|
effects.getDependencies(),
|
||||||
effects.checkDependencies({
|
effects.checkDependencies({
|
||||||
packageIds: dependencies.map((dep) => dep.id),
|
packageIds,
|
||||||
}),
|
}),
|
||||||
)
|
])
|
||||||
|
if (packageIds) {
|
||||||
const dependenciesByIdPromise = dependenciesPromise.then((d) =>
|
dependencies = dependencies.filter((d) =>
|
||||||
d.reduce(
|
(packageIds as PackageId[]).includes(d.id),
|
||||||
(acc, dep) => {
|
|
||||||
acc[dep.id] = dep
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
{} as { [id: PackageId]: DependencyRequirement },
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
const healthErrors = async () => {
|
|
||||||
const results = await resultsPromise
|
|
||||||
const dependenciesById = await dependenciesByIdPromise
|
|
||||||
const answer: { [id: PackageId]: SetHealth[] } = {}
|
|
||||||
for (const result of results) {
|
|
||||||
const dependency = dependenciesById[result.packageId]
|
|
||||||
if (!dependency) continue
|
|
||||||
if (dependency.kind !== "running") continue
|
|
||||||
|
|
||||||
const healthChecks = Object.entries(result.healthChecks)
|
|
||||||
.map(([id, hc]) => ({ ...hc, id }))
|
|
||||||
.filter((x) => !!x.message)
|
|
||||||
if (healthChecks.length === 0) continue
|
|
||||||
answer[result.packageId] = healthChecks
|
|
||||||
}
|
|
||||||
return answer
|
|
||||||
}
|
|
||||||
const configNotSatisfied = () =>
|
|
||||||
resultsPromise.then((x) => x.filter((x) => !x.configSatisfied))
|
|
||||||
const notInstalled = () =>
|
|
||||||
resultsPromise.then((x) => x.filter((x) => !x.isInstalled))
|
|
||||||
const notRunning = async () => {
|
|
||||||
const results = await resultsPromise
|
|
||||||
const dependenciesById = await dependenciesByIdPromise
|
|
||||||
return results.filter((x) => {
|
|
||||||
const dependency = dependenciesById[x.packageId]
|
|
||||||
if (!dependency) return false
|
|
||||||
if (dependency.kind !== "running") return false
|
|
||||||
return !x.isRunning
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const entries = <B>(x: { [k: string]: B }) => Object.entries(x)
|
|
||||||
const first = <A>(x: A[]): A | undefined => x[0]
|
|
||||||
const sinkVoid = <A>(x: A) => void 0
|
|
||||||
const throwIfHealthError = () =>
|
|
||||||
healthErrors()
|
|
||||||
.then(entries)
|
|
||||||
.then(first)
|
|
||||||
.then((x) => {
|
|
||||||
if (!x) return
|
|
||||||
const [id, healthChecks] = x
|
|
||||||
if (healthChecks.length > 0)
|
|
||||||
throw `Package ${id} has the following errors: ${healthChecks.map((x) => x.message).join(", ")}`
|
|
||||||
})
|
|
||||||
|
|
||||||
const throwIfConfigNotSatisfied = () =>
|
|
||||||
configNotSatisfied().then((results) => {
|
|
||||||
throw new Error(
|
|
||||||
`Package ${results[0].packageId} does not have a valid configuration`,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const throwIfNotRunning = () =>
|
|
||||||
notRunning().then((results) => {
|
|
||||||
if (results[0])
|
|
||||||
throw new Error(`Package ${results[0].packageId} is not running`)
|
|
||||||
})
|
|
||||||
|
|
||||||
const throwIfNotInstalled = () =>
|
|
||||||
notInstalled().then((results) => {
|
|
||||||
if (results[0])
|
|
||||||
throw new Error(`Package ${results[0].packageId} is not installed`)
|
|
||||||
})
|
|
||||||
const throwIfNotValid = async () =>
|
|
||||||
Promise.all([
|
|
||||||
throwIfNotRunning(),
|
|
||||||
throwIfNotInstalled(),
|
|
||||||
throwIfConfigNotSatisfied(),
|
|
||||||
throwIfHealthError(),
|
|
||||||
]).then(sinkVoid)
|
|
||||||
|
|
||||||
const isValid = () =>
|
|
||||||
throwIfNotValid().then(
|
|
||||||
() => true,
|
|
||||||
() => false,
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const find = (packageId: DependencyId) => {
|
||||||
|
const dependencyRequirement = dependencies.find((d) => d.id === packageId)
|
||||||
|
const dependencyResult = results.find((d) => d.packageId === packageId)
|
||||||
|
if (!dependencyRequirement || !dependencyResult) {
|
||||||
|
throw new Error(`Unknown DependencyId ${packageId}`)
|
||||||
|
}
|
||||||
|
return { requirement: dependencyRequirement, result: dependencyResult }
|
||||||
|
}
|
||||||
|
|
||||||
|
const installedSatisfied = (packageId: DependencyId) =>
|
||||||
|
!!find(packageId).result.installedVersion
|
||||||
|
const installedVersionSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
return (
|
||||||
|
!!dep.result.installedVersion &&
|
||||||
|
ExtendedVersion.parse(dep.result.installedVersion).satisfies(
|
||||||
|
VersionRange.parse(dep.requirement.versionRange),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const runningSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
return dep.requirement.kind !== "running" || dep.result.isRunning
|
||||||
|
}
|
||||||
|
const configSatisfied = (packageId: DependencyId) =>
|
||||||
|
find(packageId).result.configSatisfied
|
||||||
|
const healthCheckSatisfied = (
|
||||||
|
packageId: DependencyId,
|
||||||
|
healthCheckId?: HealthCheckId,
|
||||||
|
) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (
|
||||||
|
healthCheckId &&
|
||||||
|
(dep.requirement.kind !== "running" ||
|
||||||
|
!dep.requirement.healthChecks.includes(healthCheckId))
|
||||||
|
) {
|
||||||
|
throw new Error(`Unknown HealthCheckId ${healthCheckId}`)
|
||||||
|
}
|
||||||
|
const errors = Object.entries(dep.result.healthChecks)
|
||||||
|
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||||
|
.filter(([_, res]) => res.result !== "success")
|
||||||
|
return errors.length === 0
|
||||||
|
}
|
||||||
|
const pkgSatisfied = (packageId: DependencyId) =>
|
||||||
|
installedSatisfied(packageId) &&
|
||||||
|
installedVersionSatisfied(packageId) &&
|
||||||
|
runningSatisfied(packageId) &&
|
||||||
|
configSatisfied(packageId) &&
|
||||||
|
healthCheckSatisfied(packageId)
|
||||||
|
const satisfied = (packageId?: DependencyId) =>
|
||||||
|
packageId
|
||||||
|
? pkgSatisfied(packageId)
|
||||||
|
: dependencies.every((d) => pkgSatisfied(d.id as DependencyId))
|
||||||
|
|
||||||
|
const throwIfInstalledNotSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (!dep.result.installedVersion) {
|
||||||
|
throw new Error(`${dep.result.title || packageId} is not installed`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const throwIfInstalledVersionNotSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (!dep.result.installedVersion) {
|
||||||
|
throw new Error(`${dep.result.title || packageId} is not installed`)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
![dep.result.installedVersion, ...dep.result.satisfies].find((v) =>
|
||||||
|
ExtendedVersion.parse(v).satisfies(
|
||||||
|
VersionRange.parse(dep.requirement.versionRange),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`Installed version ${dep.result.installedVersion} of ${dep.result.title || packageId} does not match expected version range ${dep.requirement.versionRange}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const throwIfRunningNotSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (dep.requirement.kind === "running" && !dep.result.isRunning) {
|
||||||
|
throw new Error(`${dep.result.title || packageId} is not running`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const throwIfConfigNotSatisfied = (packageId: DependencyId) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (!dep.result.configSatisfied) {
|
||||||
|
throw new Error(
|
||||||
|
`${dep.result.title || packageId}'s configuration does not satisfy requirements`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const throwIfHealthNotSatisfied = (
|
||||||
|
packageId: DependencyId,
|
||||||
|
healthCheckId?: HealthCheckId,
|
||||||
|
) => {
|
||||||
|
const dep = find(packageId)
|
||||||
|
if (
|
||||||
|
healthCheckId &&
|
||||||
|
(dep.requirement.kind !== "running" ||
|
||||||
|
!dep.requirement.healthChecks.includes(healthCheckId))
|
||||||
|
) {
|
||||||
|
throw new Error(`Unknown HealthCheckId ${healthCheckId}`)
|
||||||
|
}
|
||||||
|
const errors = Object.entries(dep.result.healthChecks)
|
||||||
|
.filter(([id, _]) => (healthCheckId ? id === healthCheckId : true))
|
||||||
|
.filter(([_, res]) => res.result !== "success")
|
||||||
|
if (errors.length) {
|
||||||
|
throw new Error(
|
||||||
|
errors
|
||||||
|
.map(
|
||||||
|
([_, e]) =>
|
||||||
|
`Health Check ${e.name} of ${dep.result.title || packageId} failed with status ${e.result}${e.message ? `: ${e.message}` : ""}`,
|
||||||
|
)
|
||||||
|
.join("; "),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const throwIfPkgNotSatisfied = (packageId: DependencyId) => {
|
||||||
|
throwIfInstalledNotSatisfied(packageId)
|
||||||
|
throwIfInstalledVersionNotSatisfied(packageId)
|
||||||
|
throwIfRunningNotSatisfied(packageId)
|
||||||
|
throwIfConfigNotSatisfied(packageId)
|
||||||
|
throwIfHealthNotSatisfied(packageId)
|
||||||
|
}
|
||||||
|
const throwIfNotSatisfied = (packageId?: DependencyId) =>
|
||||||
|
packageId
|
||||||
|
? throwIfPkgNotSatisfied(packageId)
|
||||||
|
: (() => {
|
||||||
|
const err = dependencies.flatMap((d) => {
|
||||||
|
try {
|
||||||
|
throwIfPkgNotSatisfied(d.id as DependencyId)
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof Error) return [e.message]
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
if (err.length) {
|
||||||
|
throw new Error(err.join("; "))
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
notRunning,
|
installedSatisfied,
|
||||||
notInstalled,
|
installedVersionSatisfied,
|
||||||
configNotSatisfied,
|
runningSatisfied,
|
||||||
healthErrors,
|
configSatisfied,
|
||||||
throwIfNotRunning,
|
healthCheckSatisfied,
|
||||||
|
satisfied,
|
||||||
|
throwIfInstalledNotSatisfied,
|
||||||
|
throwIfInstalledVersionNotSatisfied,
|
||||||
|
throwIfRunningNotSatisfied,
|
||||||
throwIfConfigNotSatisfied,
|
throwIfConfigNotSatisfied,
|
||||||
throwIfNotValid,
|
throwIfHealthNotSatisfied,
|
||||||
throwIfNotInstalled,
|
throwIfNotSatisfied,
|
||||||
throwIfHealthError,
|
|
||||||
isValid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type Not = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class VersionRange {
|
export class VersionRange {
|
||||||
private constructor(private atom: Anchor | And | Or | Not | P.Any | P.None) {}
|
private constructor(public atom: Anchor | And | Or | Not | P.Any | P.None) {}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
switch (this.atom.type) {
|
switch (this.atom.type) {
|
||||||
@@ -63,67 +63,6 @@ export class VersionRange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a boolean indicating whether a given version satisfies the VersionRange
|
|
||||||
* !( >= 1:1 <= 2:2) || <=#bitcoin:1.2.0-alpha:0
|
|
||||||
*/
|
|
||||||
satisfiedBy(version: ExtendedVersion): boolean {
|
|
||||||
switch (this.atom.type) {
|
|
||||||
case "Anchor":
|
|
||||||
const otherVersion = this.atom.version
|
|
||||||
switch (this.atom.operator) {
|
|
||||||
case "=":
|
|
||||||
return version.equals(otherVersion)
|
|
||||||
case ">":
|
|
||||||
return version.greaterThan(otherVersion)
|
|
||||||
case "<":
|
|
||||||
return version.lessThan(otherVersion)
|
|
||||||
case ">=":
|
|
||||||
return version.greaterThanOrEqual(otherVersion)
|
|
||||||
case "<=":
|
|
||||||
return version.lessThanOrEqual(otherVersion)
|
|
||||||
case "!=":
|
|
||||||
return !version.equals(otherVersion)
|
|
||||||
case "^":
|
|
||||||
const nextMajor = this.atom.version.incrementMajor()
|
|
||||||
if (
|
|
||||||
version.greaterThanOrEqual(otherVersion) &&
|
|
||||||
version.lessThan(nextMajor)
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
case "~":
|
|
||||||
const nextMinor = this.atom.version.incrementMinor()
|
|
||||||
if (
|
|
||||||
version.greaterThanOrEqual(otherVersion) &&
|
|
||||||
version.lessThan(nextMinor)
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "And":
|
|
||||||
return (
|
|
||||||
this.atom.left.satisfiedBy(version) &&
|
|
||||||
this.atom.right.satisfiedBy(version)
|
|
||||||
)
|
|
||||||
case "Or":
|
|
||||||
return (
|
|
||||||
this.atom.left.satisfiedBy(version) ||
|
|
||||||
this.atom.right.satisfiedBy(version)
|
|
||||||
)
|
|
||||||
case "Not":
|
|
||||||
return !this.atom.value.satisfiedBy(version)
|
|
||||||
case "Any":
|
|
||||||
return true
|
|
||||||
case "None":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static parseAtom(atom: P.VersionRangeAtom): VersionRange {
|
private static parseAtom(atom: P.VersionRangeAtom): VersionRange {
|
||||||
switch (atom.type) {
|
switch (atom.type) {
|
||||||
case "Not":
|
case "Not":
|
||||||
@@ -207,6 +146,10 @@ export class VersionRange {
|
|||||||
static none() {
|
static none() {
|
||||||
return new VersionRange({ type: "None" })
|
return new VersionRange({ type: "None" })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
satisfiedBy(version: Version | ExtendedVersion) {
|
||||||
|
return version.satisfies(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Version {
|
export class Version {
|
||||||
@@ -266,6 +209,12 @@ export class Version {
|
|||||||
const parsed = P.parse(version, { startRule: "Version" })
|
const parsed = P.parse(version, { startRule: "Version" })
|
||||||
return new Version(parsed.number, parsed.prerelease)
|
return new Version(parsed.number, parsed.prerelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
satisfies(versionRange: VersionRange): boolean {
|
||||||
|
return new ExtendedVersion(null, this, new Version([0], [])).satisfies(
|
||||||
|
versionRange,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #flavor:0.1.2-beta.1:0
|
// #flavor:0.1.2-beta.1:0
|
||||||
@@ -404,6 +353,67 @@ export class ExtendedVersion {
|
|||||||
updatedDownstream,
|
updatedDownstream,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean indicating whether a given version satisfies the VersionRange
|
||||||
|
* !( >= 1:1 <= 2:2) || <=#bitcoin:1.2.0-alpha:0
|
||||||
|
*/
|
||||||
|
satisfies(versionRange: VersionRange): boolean {
|
||||||
|
switch (versionRange.atom.type) {
|
||||||
|
case "Anchor":
|
||||||
|
const otherVersion = versionRange.atom.version
|
||||||
|
switch (versionRange.atom.operator) {
|
||||||
|
case "=":
|
||||||
|
return this.equals(otherVersion)
|
||||||
|
case ">":
|
||||||
|
return this.greaterThan(otherVersion)
|
||||||
|
case "<":
|
||||||
|
return this.lessThan(otherVersion)
|
||||||
|
case ">=":
|
||||||
|
return this.greaterThanOrEqual(otherVersion)
|
||||||
|
case "<=":
|
||||||
|
return this.lessThanOrEqual(otherVersion)
|
||||||
|
case "!=":
|
||||||
|
return !this.equals(otherVersion)
|
||||||
|
case "^":
|
||||||
|
const nextMajor = versionRange.atom.version.incrementMajor()
|
||||||
|
if (
|
||||||
|
this.greaterThanOrEqual(otherVersion) &&
|
||||||
|
this.lessThan(nextMajor)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case "~":
|
||||||
|
const nextMinor = versionRange.atom.version.incrementMinor()
|
||||||
|
if (
|
||||||
|
this.greaterThanOrEqual(otherVersion) &&
|
||||||
|
this.lessThan(nextMinor)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "And":
|
||||||
|
return (
|
||||||
|
this.satisfies(versionRange.atom.left) &&
|
||||||
|
this.satisfies(versionRange.atom.right)
|
||||||
|
)
|
||||||
|
case "Or":
|
||||||
|
return (
|
||||||
|
this.satisfies(versionRange.atom.left) ||
|
||||||
|
this.satisfies(versionRange.atom.right)
|
||||||
|
)
|
||||||
|
case "Not":
|
||||||
|
return !this.satisfies(versionRange.atom.value)
|
||||||
|
case "Any":
|
||||||
|
return true
|
||||||
|
case "None":
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const testTypeExVer = <T extends string>(t: T & ValidateExVer<T>) => t
|
export const testTypeExVer = <T extends string>(t: T & ValidateExVer<T>) => t
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import type { PackageId } from "./PackageId"
|
|||||||
|
|
||||||
export type CheckDependenciesResult = {
|
export type CheckDependenciesResult = {
|
||||||
packageId: PackageId
|
packageId: PackageId
|
||||||
isInstalled: boolean
|
title: string | null
|
||||||
|
installedVersion: string | null
|
||||||
|
satisfies: string[]
|
||||||
isRunning: boolean
|
isRunning: boolean
|
||||||
configSatisfied: boolean
|
configSatisfied: boolean
|
||||||
healthChecks: { [key: HealthCheckId]: NamedHealthCheckResult }
|
healthChecks: { [key: HealthCheckId]: NamedHealthCheckResult }
|
||||||
version: string | null
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user