diff --git a/app/components/LicenseDisplay.vue b/app/components/LicenseDisplay.vue index c83cb46d3..62ade31fa 100644 --- a/app/components/LicenseDisplay.vue +++ b/app/components/LicenseDisplay.vue @@ -1,11 +1,29 @@ @@ -32,4 +50,31 @@ const hasAnyValidLicense = computed(() => tokens.value.some(t => t.type === 'lic aria-hidden="true" /> +
+

+ {{ $t('package.versions.license_change_warning') }} +

+ + + + + + +
diff --git a/app/composables/useLicenseChanges.ts b/app/composables/useLicenseChanges.ts new file mode 100644 index 000000000..25478a544 --- /dev/null +++ b/app/composables/useLicenseChanges.ts @@ -0,0 +1,74 @@ +import type { MaybeRefOrGetter } from 'vue' +import { toValue } from 'vue' + +export interface LicenseChange { + from: string + to: string + version: string +} + +export interface LicenseChangesResult { + changes: LicenseChange[] +} + +// Type definitions for npm registry response +interface NpmRegistryVersion { + version: string + license?: string +} + +// for registry responses of $fetch function, the type includes the key versions as well as many others too. +interface NpmRegistryResponse { + time: Record + versions: Record +} + +/** + * Composable to detect license changes across all versions of a package + */ +export function useLicenseChanges(packageName: MaybeRefOrGetter) { + return useAsyncData( + () => `license-changes:${toValue(packageName)}`, + async () => { + const name = toValue(packageName) + if (!name) return { changes: [] } + + // Fetch full package metadata from npm registry + const url = `https://registry.npmjs.org/${name}` + const data = await $fetch(url) + + const changes: LicenseChange[] = [] + let prevLicense: string | undefined = undefined + + // `data.versions` is an object with version keys + const versions = Object.values(data.versions) as NpmRegistryVersion[] + + // Sort versions ascending to compare chronologically + versions.sort((a, b) => { + const dateA = new Date(data.time[a.version] as string).getTime() + const dateB = new Date(data.time[b.version] as string).getTime() + + // Ascending order (oldest to newest) + return dateA - dateB + }) + + // Detect license changes + for (const version of versions) { + const license = (version.license as string) ?? 'UNKNOWN' + if (prevLicense && license !== prevLicense) { + changes.push({ + from: prevLicense, + to: license, + version: version.version as string, + }) + } + prevLicense = license + } + return { changes } + }, + { + default: () => ({ changes: [] }), + watch: [() => toValue(packageName)], + }, + ) +} diff --git a/app/pages/package/[[org]]/[name].vue b/app/pages/package/[[org]]/[name].vue index 4bc4d85bc..6105b7b72 100644 --- a/app/pages/package/[[org]]/[name].vue +++ b/app/pages/package/[[org]]/[name].vue @@ -582,7 +582,11 @@ const showSkeleton = shallowRef(false) {{ $t('package.stats.license') }}
- + {{ $t('package.license.none') }}
diff --git a/i18n/locales/en.json b/i18n/locales/en.json index 97008c630..5685df918 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -432,7 +432,11 @@ "filter_placeholder": "Filter by semver (e.g. ^3.0.0)", "filter_invalid": "Invalid semver range", "filter_help": "Semver range filter help", + "license_change_help": "License Change Details", + "license_change_item": "from {from} to {to} at version {version}", "filter_tooltip": "Filter versions using a {link}. For example, ^3.0.0 shows all 3.x versions.", + "changed_license": "The license was changed: {license_change}", + "license_change_warning": "change!", "filter_tooltip_link": "semver range", "no_matches": "No versions match this range", "copy_alt": { diff --git a/i18n/locales/tr-TR.json b/i18n/locales/tr-TR.json index 97308423f..30480a008 100644 --- a/i18n/locales/tr-TR.json +++ b/i18n/locales/tr-TR.json @@ -386,7 +386,11 @@ "filter_placeholder": "Semver ile filtrele (örn. ^3.0.0)", "filter_invalid": "Geçersiz semver aralığı", "filter_help": "Semver aralığı filtresi yardımı", + "license_change_help": "Lisans değişikliği yardımı", + "license_change_item": "{version} sürümünde {from}'den {to}'ya", "filter_tooltip": "Sürümleri {link} kullanarak filtreleyin. Örneğin, ^3.0.0 tüm 3.x sürümlerini gösterir.", + "changed_license": "Lisans değişikliği gerçekleşti: {license_change}", + "license_change_warning": "değişiklik!", "filter_tooltip_link": "semver aralığı", "no_matches": "Bu aralığa uygun sürüm yok", "copy_alt": { diff --git a/i18n/schema.json b/i18n/schema.json index 720013d90..10a241b95 100644 --- a/i18n/schema.json +++ b/i18n/schema.json @@ -1300,9 +1300,21 @@ "filter_help": { "type": "string" }, + "license_change_help": { + "type": "string" + }, + "license_change_item": { + "type": "string" + }, "filter_tooltip": { "type": "string" }, + "changed_license": { + "type": "string" + }, + "license_change_warning": { + "type": "string" + }, "filter_tooltip_link": { "type": "string" },