{"version":3,"file":"cargo.mjs","names":[],"sources":["../../src/registries/cargo.ts"],"sourcesContent":["import type { Client } from \"../core/client.ts\";\nimport type { Dependency, Maintainer, Package, URLBuilder, Version } from \"../core/types.ts\";\nimport { Registry } from \"../core/registry.ts\";\nimport { normalizeLicense } from \"../core/license.ts\";\nimport { normalizeRepositoryURL } from \"../core/repository.ts\";\nimport { buildPURL } from \"../core/purl.ts\";\nimport { rethrowFetchError } from \"../core/errors.ts\";\n\n/** Crates.io API response for a single crate. */\ninterface CratesPackageResponse {\n  crate: {\n    id: number;\n    name: string;\n    updated_at: string;\n    created_at: string;\n    downloads: number;\n    recent_downloads: number;\n    max_version: string;\n    max_stable_version: string;\n    newest_version: string;\n    description: string;\n    homepage: string;\n    documentation: string;\n    repository: string;\n    keywords: string[];\n    categories: Array<{\n      id: string;\n      category: string;\n      created_at: string;\n    }>;\n    badges: unknown[];\n    links: Record<string, string>;\n  };\n  versions: CratesVersion[];\n}\n\n/** Crates.io version data. */\ninterface CratesVersion {\n  id: number;\n  num: string;\n  dl_path: string;\n  readme_path: string;\n  created_at: string;\n  updated_at: string;\n  downloads: number;\n  features: Record<string, string[]>;\n  yanked: boolean;\n  license: string;\n  links: Record<string, string>;\n  crate_size: number;\n  published_by: {\n    id: number;\n    login: string;\n    name: string;\n    avatar: string;\n    url: string;\n  };\n  checksum: string;\n}\n\n/** Crates.io dependencies response. */\ninterface CratesDependenciesResponse {\n  dependencies: CratesDependency[];\n  meta: {\n    prelude: boolean;\n  };\n}\n\n/** Crates.io dependency data. */\ninterface CratesDependency {\n  id: number;\n  version_id: number;\n  crate_id: string;\n  req: string;\n  optional: boolean;\n  default_features: boolean;\n  features: string[];\n  target: string | null;\n  kind: string;\n  downloads: number;\n}\n\n/** Crates.io maintainers response. */\ninterface CratesMaintainersResponse {\n  users: CratesMaintainer[];\n}\n\n/** Crates.io maintainer data. */\ninterface CratesMaintainer {\n  id: number;\n  login: string;\n  name: string;\n  avatar: string;\n  url: string;\n}\n\nfunction preferNonEmpty(value: string, fallback: string): string {\n  return value || fallback;\n}\n\n/** Crates.io registry client. */\nexport class CargoRegistry extends Registry {\n  constructor(baseURL: string, client: Client) {\n    super();\n    this.baseURL = baseURL;\n    this.client = client;\n  }\n\n  readonly baseURL: string;\n  readonly client: Client;\n\n  ecosystem(): string {\n    return \"cargo\";\n  }\n\n  async fetchPackage(name: string, signal?: AbortSignal): Promise<Package> {\n    const url = `${this.baseURL}/api/v1/crates/${name}`;\n\n    try {\n      const data = await this.client.getJSON<CratesPackageResponse>(url, signal);\n      const crateData = data.crate;\n      const latestVersion = preferNonEmpty(crateData.max_stable_version, crateData.max_version);\n      const latestVersionData = data.versions.find((v) => v.num === latestVersion);\n\n      return {\n        name: crateData.name,\n        description: crateData.description || \"\",\n        homepage: crateData.homepage || \"\",\n        documentation: crateData.documentation || \"\",\n        repository: normalizeRepositoryURL(crateData.repository || \"\"),\n        licenses: normalizeLicense(\n          latestVersionData ? latestVersionData.license : (data.versions[0]?.license ?? \"\"),\n        ),\n        keywords: crateData.keywords,\n        namespace: \"\",\n        latestVersion,\n        metadata: {\n          downloads: crateData.downloads,\n          recentDownloads: crateData.recent_downloads,\n          categories: crateData.categories,\n          newestVersion: crateData.newest_version,\n          defaultVersion: crateData.max_version,\n          updatedAt: crateData.updated_at,\n          createdAt: crateData.created_at,\n        },\n      };\n    } catch (error) {\n      rethrowFetchError(error, this.ecosystem(), name);\n    }\n  }\n\n  async fetchVersions(name: string, signal?: AbortSignal): Promise<Version[]> {\n    const url = `${this.baseURL}/api/v1/crates/${name}`;\n\n    try {\n      const data = await this.client.getJSON<CratesPackageResponse>(url, signal);\n      const versions: Version[] = [];\n\n      for (const versionData of data.versions) {\n        const publishedAt = new Date(versionData.created_at);\n        const status = versionData.yanked ? \"yanked\" : \"\";\n\n        versions.push({\n          number: versionData.num,\n          publishedAt,\n          licenses: normalizeLicense(versionData.license),\n          integrity: `sha256-${versionData.checksum}`,\n          status,\n          metadata: {\n            crateSize: versionData.crate_size,\n            features: versionData.features,\n            downloads: versionData.downloads,\n          },\n        });\n      }\n\n      return versions;\n    } catch (error) {\n      rethrowFetchError(error, this.ecosystem(), name);\n    }\n  }\n\n  async fetchDependencies(\n    name: string,\n    version: string,\n    signal?: AbortSignal,\n  ): Promise<Dependency[]> {\n    const url = `${this.baseURL}/api/v1/crates/${name}/${version}/dependencies`;\n\n    try {\n      const data = await this.client.getJSON<CratesDependenciesResponse>(url, signal);\n      const dependencies: Dependency[] = [];\n\n      for (const dep of data.dependencies) {\n        let scope: \"runtime\" | \"development\" | \"test\" | \"build\" | \"optional\";\n\n        if (dep.kind === \"dev\") {\n          scope = \"development\";\n        } else if (dep.kind === \"build\") {\n          scope = \"build\";\n        } else {\n          scope = \"runtime\";\n        }\n\n        dependencies.push({\n          name: dep.crate_id,\n          requirements: dep.req,\n          scope,\n          optional: dep.optional,\n        });\n      }\n\n      return dependencies;\n    } catch (error) {\n      rethrowFetchError(error, this.ecosystem(), name, version);\n    }\n  }\n\n  async fetchMaintainers(name: string, signal?: AbortSignal): Promise<Maintainer[]> {\n    const url = `${this.baseURL}/api/v1/crates/${name}/owner_user`;\n\n    try {\n      const data = await this.client.getJSON<CratesMaintainersResponse>(url, signal);\n      const maintainers: Maintainer[] = [];\n\n      for (const user of data.users) {\n        maintainers.push({\n          uuid: user.id.toString(),\n          login: user.login,\n          name: user.name,\n          email: \"\",\n          url: user.url,\n          role: \"\",\n        });\n      }\n\n      return maintainers;\n    } catch (error) {\n      rethrowFetchError(error, this.ecosystem(), name);\n    }\n  }\n\n  urls(): URLBuilder {\n    return {\n      registry: (name: string, version?: string) => {\n        const base = `https://crates.io/crates/${name}`;\n        return version ? `${base}/${version}` : base;\n      },\n      download: (name: string, version: string) => {\n        return `https://crates.io/api/v1/crates/${name}/${version}/download`;\n      },\n      documentation: (name: string, version?: string) => {\n        return version ? `https://docs.rs/${name}/${version}` : `https://docs.rs/${name}`;\n      },\n      readme: (name: string, version?: string) => {\n        return version\n          ? `https://crates.io/api/v1/crates/${name}/${version}/readme`\n          : `https://crates.io/crates/${name}`;\n      },\n      purl: (name: string, version?: string) => {\n        return buildPURL({ type: \"cargo\", name, version });\n      },\n    };\n  }\n}\n"],"mappings":"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"}