Skip to content

Commit 6716b8d

Browse files
[refactor] replace manual semver operations with semver package
Replace custom compareVersions and isSemVer functions with the robust semver package to handle version comparisons more reliably. This addresses edge cases and follows industry standards for semantic version handling.
1 parent 3f290e2 commit 6716b8d

File tree

8 files changed

+99
-104
lines changed

8 files changed

+99
-104
lines changed

src/components/dialog/content/MissingCoreNodesMessage.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@
4444
<script setup lang="ts">
4545
import { whenever } from '@vueuse/core'
4646
import Message from 'primevue/message'
47+
import * as semver from 'semver'
4748
import { computed, ref } from 'vue'
4849
4950
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
5051
import { useSystemStatsStore } from '@/stores/systemStatsStore'
51-
import { compareVersions } from '@/utils/formatUtil'
5252
5353
const props = defineProps<{
5454
missingCoreNodes: Record<string, LGraphNode[]>
@@ -78,7 +78,10 @@ whenever(
7878
const sortedMissingCoreNodes = computed(() => {
7979
return Object.entries(props.missingCoreNodes).sort(([a], [b]) => {
8080
// Sort by version in descending order (newest first)
81-
return compareVersions(b, a) // Reversed for descending order
81+
const versionA = semver.coerce(a)
82+
const versionB = semver.coerce(b)
83+
if (!versionA || !versionB) return 0
84+
return semver.rcompare(versionA, versionB)
8285
})
8386
})
8487

src/components/dialog/content/manager/PackVersionBadge.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737

3838
<script setup lang="ts">
3939
import Popover from 'primevue/popover'
40+
import * as semver from 'semver'
4041
import { computed, ref, watch } from 'vue'
4142
4243
import PackVersionSelectorPopover from '@/components/dialog/content/manager/PackVersionSelectorPopover.vue'
4344
import { usePackUpdateStatus } from '@/composables/nodePack/usePackUpdateStatus'
4445
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
4546
import { SelectedVersion } from '@/types/comfyManagerTypes'
4647
import { components } from '@/types/comfyRegistryTypes'
47-
import { isSemVer } from '@/utils/formatUtil'
4848
4949
const TRUNCATED_HASH_LENGTH = 7
5050
@@ -71,7 +71,9 @@ const installedVersion = computed(() => {
7171
SelectedVersion.NIGHTLY
7272
7373
// If Git hash, truncate to 7 characters
74-
return isSemVer(version) ? version : version.slice(0, TRUNCATED_HASH_LENGTH)
74+
return semver.valid(version)
75+
? version
76+
: version.slice(0, TRUNCATED_HASH_LENGTH)
7577
})
7678
7779
const toggleVersionSelector = (event: Event) => {

src/components/dialog/content/manager/PackVersionSelectorPopover.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ import { whenever } from '@vueuse/core'
6262
import Button from 'primevue/button'
6363
import Listbox from 'primevue/listbox'
6464
import ProgressSpinner from 'primevue/progressspinner'
65+
import * as semver from 'semver'
6566
import { onMounted, ref } from 'vue'
6667
import { useI18n } from 'vue-i18n'
6768
@@ -75,7 +76,6 @@ import {
7576
SelectedVersion
7677
} from '@/types/comfyManagerTypes'
7778
import { components } from '@/types/comfyRegistryTypes'
78-
import { isSemVer } from '@/utils/formatUtil'
7979
8080
const { nodePack } = defineProps<{
8181
nodePack: components['schemas']['Node']
@@ -97,7 +97,7 @@ onMounted(() => {
9797
const initialVersion = getInitialSelectedVersion() ?? SelectedVersion.LATEST
9898
selectedVersion.value =
9999
// Use NIGHTLY when version is a Git hash
100-
isSemVer(initialVersion) ? initialVersion : SelectedVersion.NIGHTLY
100+
semver.valid(initialVersion) ? initialVersion : SelectedVersion.NIGHTLY
101101
})
102102
103103
const getInitialSelectedVersion = () => {

src/composables/nodePack/usePackUpdateStatus.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import * as semver from 'semver'
12
import { computed } from 'vue'
23

34
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
45
import type { components } from '@/types/comfyRegistryTypes'
5-
import { compareVersions, isSemVer } from '@/utils/formatUtil'
66

77
export const usePackUpdateStatus = (
88
nodePack: components['schemas']['Node']
@@ -16,14 +16,17 @@ export const usePackUpdateStatus = (
1616
const latestVersion = computed(() => nodePack.latest_version?.version)
1717

1818
const isNightlyPack = computed(
19-
() => !!installedVersion.value && !isSemVer(installedVersion.value)
19+
() => !!installedVersion.value && !semver.valid(installedVersion.value)
2020
)
2121

2222
const isUpdateAvailable = computed(() => {
2323
if (!isInstalled.value || isNightlyPack.value || !latestVersion.value) {
2424
return false
2525
}
26-
return compareVersions(latestVersion.value, installedVersion.value) > 0
26+
const installedSemver = semver.coerce(installedVersion.value)
27+
const latestSemver = semver.coerce(latestVersion.value)
28+
if (!installedSemver || !latestSemver) return false
29+
return semver.gt(latestSemver, installedSemver)
2730
})
2831

2932
return {

src/stores/releaseStore.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { defineStore } from 'pinia'
2+
import * as semver from 'semver'
23
import { computed, ref } from 'vue'
34

45
import { type ReleaseNote, useReleaseService } from '@/services/releaseService'
56
import { useSettingStore } from '@/stores/settingStore'
67
import { useSystemStatsStore } from '@/stores/systemStatsStore'
78
import { isElectron } from '@/utils/envUtil'
8-
import { compareVersions, stringToLocale } from '@/utils/formatUtil'
9+
import { stringToLocale } from '@/utils/formatUtil'
910

1011
// Store for managing release notes
1112
export const useReleaseStore = defineStore('release', () => {
@@ -54,16 +55,19 @@ export const useReleaseStore = defineStore('release', () => {
5455
const isNewVersionAvailable = computed(
5556
() =>
5657
!!recentRelease.value &&
57-
compareVersions(
58-
recentRelease.value.version,
59-
currentComfyUIVersion.value
60-
) > 0
58+
semver.gt(
59+
semver.coerce(recentRelease.value.version) || '0.0.0',
60+
semver.coerce(currentComfyUIVersion.value) || '0.0.0'
61+
)
6162
)
6263

6364
const isLatestVersion = computed(
6465
() =>
6566
!!recentRelease.value &&
66-
!compareVersions(recentRelease.value.version, currentComfyUIVersion.value)
67+
semver.eq(
68+
semver.coerce(recentRelease.value.version) || '0.0.0',
69+
semver.coerce(currentComfyUIVersion.value) || '0.0.0'
70+
)
6771
)
6872

6973
const hasMediumOrHighAttention = computed(() =>

src/stores/settingStore.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import _ from 'lodash'
22
import { defineStore } from 'pinia'
3+
import * as semver from 'semver'
34
import { ref } from 'vue'
45

56
import type { Settings } from '@/schemas/apiSchema'
67
import { api } from '@/scripts/api'
78
import { app } from '@/scripts/app'
89
import type { SettingParams } from '@/types/settingTypes'
910
import type { TreeNode } from '@/types/treeExplorerTypes'
10-
import { compareVersions, isSemVer } from '@/utils/formatUtil'
1111

1212
export const getSettingInfo = (setting: SettingParams) => {
1313
const parts = setting.category || setting.id.split('.')
@@ -132,17 +132,30 @@ export const useSettingStore = defineStore('setting', () => {
132132

133133
if (installedVersion) {
134134
const sortedVersions = Object.keys(defaultsByInstallVersion).sort(
135-
(a, b) => compareVersions(b, a)
135+
(a, b) => {
136+
const versionA = semver.coerce(a)
137+
const versionB = semver.coerce(b)
138+
if (!versionA || !versionB) return 0
139+
return semver.rcompare(versionA, versionB)
140+
}
136141
)
137142

138143
for (const version of sortedVersions) {
139-
// Ensure the version is in a valid format before comparing
140-
if (!isSemVer(version)) {
144+
if (!semver.valid(version)) {
141145
continue
142146
}
143147

144-
if (compareVersions(installedVersion, version) >= 0) {
145-
const versionedDefault = defaultsByInstallVersion[version]
148+
const installedSemver = semver.coerce(installedVersion)
149+
const targetSemver = semver.coerce(version)
150+
if (
151+
installedSemver &&
152+
targetSemver &&
153+
semver.gte(installedSemver, targetSemver)
154+
) {
155+
const versionedDefault =
156+
defaultsByInstallVersion[
157+
version as `${number}.${number}.${number}`
158+
]
146159
return typeof versionedDefault === 'function'
147160
? versionedDefault()
148161
: versionedDefault

src/utils/formatUtil.ts

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -390,39 +390,6 @@ export const downloadUrlToHfRepoUrl = (url: string): string => {
390390
}
391391
}
392392

393-
export const isSemVer = (
394-
version: string
395-
): version is `${number}.${number}.${number}` => {
396-
const regex = /^\d+\.\d+\.\d+$/
397-
return regex.test(version)
398-
}
399-
400-
const normalizeVersion = (version: string) =>
401-
version
402-
.split(/[+.-]/)
403-
.map(Number)
404-
.filter((part) => !Number.isNaN(part))
405-
406-
export function compareVersions(
407-
versionA: string | undefined,
408-
versionB: string | undefined
409-
): number {
410-
versionA ??= '0.0.0'
411-
versionB ??= '0.0.0'
412-
413-
const aParts = normalizeVersion(versionA)
414-
const bParts = normalizeVersion(versionB)
415-
416-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
417-
const aPart = aParts[i] ?? 0
418-
const bPart = bParts[i] ?? 0
419-
if (aPart < bPart) return -1
420-
if (aPart > bPart) return 1
421-
}
422-
423-
return 0
424-
}
425-
426393
/**
427394
* Converts a currency amount to Metronome's integer representation.
428395
* For USD, converts to cents (multiplied by 100).

0 commit comments

Comments
 (0)