65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import type { CatalogResult } from '../services/kiwix_catalog_service.js'
|
|
import type { SpecResource } from '../../types/collections.js'
|
|
import { isGatedResource } from './hosted_content.js'
|
|
|
|
export type ResolvedZimDownload = {
|
|
url: string
|
|
version: string
|
|
sizeBytes: number | undefined
|
|
}
|
|
|
|
function compareZimVersions(left: string, right: string): number {
|
|
const parse = (value: string): [number, number] | null => {
|
|
const match = /^(\d{4})-(\d{1,2})$/.exec(value)
|
|
if (!match) return null
|
|
|
|
const month = Number.parseInt(match[2], 10)
|
|
if (month < 1 || month > 12) return null
|
|
|
|
return [Number.parseInt(match[1], 10), month]
|
|
}
|
|
|
|
const leftParts = parse(left)
|
|
const rightParts = parse(right)
|
|
if (!leftParts || !rightParts) return left.localeCompare(right)
|
|
|
|
return leftParts[0] - rightParts[0] || leftParts[1] - rightParts[1]
|
|
}
|
|
|
|
export function resolveZimDownload(
|
|
resource: SpecResource,
|
|
latest: CatalogResult | null
|
|
): ResolvedZimDownload {
|
|
const manifestSizeBytes = resource.size_mb > 0 ? resource.size_mb * 1024 * 1024 : undefined
|
|
|
|
// Content we host ourselves is pinned to the manifest URL, never the Kiwix
|
|
// catalog. It isn't in the openzim catalog at all, so this is normally a no-op
|
|
// — but a resource-id collision would otherwise silently redirect a gated
|
|
// download to a third-party mirror, losing both the auth header and any
|
|
// guarantee about what the bytes are.
|
|
//
|
|
// Consequence, stated rather than implied: gated content does NOT participate
|
|
// in catalog-driven auto-update. New versions ship by bumping the manifest.
|
|
if (isGatedResource(resource)) {
|
|
return {
|
|
url: resource.url,
|
|
version: resource.version,
|
|
sizeBytes: manifestSizeBytes,
|
|
}
|
|
}
|
|
|
|
if (!latest || compareZimVersions(latest.version, resource.version) < 0) {
|
|
return {
|
|
url: resource.url,
|
|
version: resource.version,
|
|
sizeBytes: manifestSizeBytes,
|
|
}
|
|
}
|
|
|
|
return {
|
|
url: latest.download_url,
|
|
version: latest.version,
|
|
sizeBytes: latest.size_bytes > 0 ? latest.size_bytes : manifestSizeBytes,
|
|
}
|
|
}
|