use std::sync::Arc; /// Failures acquiring, verifying, and resolving registry packages. /// /// Every variant preserves the historical message so lockfile, cache, and /// authority diagnostics stay stable; the structure lets callers match on /// failure kinds instead of substrings. #[derive(Clone, Debug, thiserror::Error)] pub enum RegistryError { #[error(transparent)] Url(#[from] url::ParseError), #[error(transparent)] Caps(#[from] crate::caps::CapabilitiesError), #[error(transparent)] Io(Arc), #[error(transparent)] Json(Arc), #[error(transparent)] Fjson(#[from] serde_fjson::Error), #[error(transparent)] Hyper(Arc), // -- mod.rs: options and lockfile ------------------------------------- #[error("Update and frozen-lock modes cannot be combined")] UpdateAndFrozen, #[error("npm project root must be an absolute path")] NpmProjectRootNotAbsolute, #[error("Frozen lockfile does not exist: {}", path.display())] FrozenLockfileDoesNotExist { path: std::path::PathBuf }, #[error("HTTP package configs cannot use the configured JSR registry: {name}")] HttpConfigUsesJsrRegistry { name: String }, #[error("HTTP package configs cannot redirect into the configured JSR registry: {url}")] HttpConfigRedirectsIntoJsr { url: String }, #[error("Frozen lockfile is missing remote source: {name}")] FrozenLockfileMissingRemote { name: String }, #[error("Remote integrity or final URL mismatch: {name}")] RemoteIntegrityMismatch { name: String }, #[error("HTTP module was not acquired: {name}")] HttpModuleNotAcquired { name: String }, #[error("Cannot prune a frozen lockfile")] PruneFrozen, #[error("Lockfile changed concurrently for {key}")] LockfileChanged { key: String }, #[error("Locked metadata changed for {url}")] LockedMetadataChanged { url: String }, #[error("Locked npm package changed for {key}")] LockedNpmPackageChanged { key: String }, #[error("Locked npm instance changed for {id}")] LockedNpmInstanceChanged { id: String }, #[error("Missing acquired artifact while vendoring: {name}")] MissingVendoredArtifact { name: String }, #[error("npm instance registry mismatch: {package}")] NpmInstanceRegistryMismatch { package: String }, #[error("npm file integrity mismatch: {rel}")] NpmFileIntegrityMismatch { rel: String }, #[error("Offline package cache miss: {url}")] OfflineCacheMiss { url: String }, #[error("Registry returned {status} for {url}")] RegistryStatus { status: String, url: String }, #[error("Registry returned HTML instead of an artifact: {url}")] RegistryHtmlArtifact { url: String }, #[error("Registry artifact is too large: {url}")] RegistryArtifactTooLarge { url: String }, #[error("Registry request timed out: {url}")] RegistryTimeout { url: String }, #[error("Package integrity mismatch")] IntegrityMismatch, #[error("{name}: Package integrity mismatch")] VerifyMismatch { name: String }, #[error("Package artifacts must be regular files")] ArtifactNotRegularFile, #[error("Cached package artifact is too large")] CachedArtifactTooLarge, #[error("Lockfile must be a regular file")] LockfileNotRegularFile, #[error("{name}: not UTF-8")] LockfileNotUtf8 { name: String }, #[error("{detail}")] LockfileParse { detail: String }, #[error("{name}: {source}")] LockfileJson { name: String, source: std::sync::Arc, }, #[error("Registry must be an absolute base URL without credentials, query, or fragment")] InvalidRegistryBaseUrl, #[error("Lockfile is too large")] LockfileTooLarge, #[error("Lockfile needs a parent directory")] LockfileNeedsParent, #[error("Output needs a parent directory")] OutputNeedsParent, #[error("Registries require HTTPS (HTTP is allowed only for loopback testing)")] RegistryRequiresHttps, #[error("Unsupported lockfile version: {version}")] UnsupportedLockfileVersion { version: u32 }, #[error("Lockfile JSR registry does not match the configured JSR registry")] LockfileJsrRegistryMismatch, #[error("Lockfile version 1 cannot carry npm pins")] LockfileV1NpmPins, #[error("Lockfile npm registry does not match the configured npm registry")] LockfileNpmRegistryMismatch, #[error("Lockfile npm packages require an npm registry")] LockfileNpmPackagesWithoutRegistry, #[error("Registry module cannot use a remote lock entry: {name}")] RegistryModuleRemoteLockEntry { name: String }, #[error("{0} kept changing while it was being updated")] FileKeptChanging(String), #[error("Output must be a regular non-symlink file")] OutputNotRegularFile, #[error("Module is not UTF-8: {name}")] ModuleNotUtf8 { name: String }, #[error("HTTP acquisition worker stopped")] HttpAcquisitionWorkerStopped, #[error("Package acquisition worker stopped")] PackageAcquisitionWorkerStopped, #[error("{detail}")] WorkerJoin { detail: String }, #[error("{detail}")] Persist { detail: String }, // -- sub-registry errors (each module's own type; transparent here) --- #[error("{detail}")] HttpRequest { detail: String }, #[error(transparent)] Http(#[from] super::http::HttpError), #[error(transparent)] Jsr(#[from] super::jsr::JsrError), #[error(transparent)] Npm(#[from] super::npm::NpmError), #[error(transparent)] NpmStorage(#[from] super::npm::storage::StorageError), } // Explicit textual rendering for generic plumbing (such as update_file) // shared with callers that carry their own error types. Prefer carrying // RegistryError itself wherever possible. impl From for String { fn from(error: RegistryError) -> Self { error.to_string() } } impl From for RegistryError { fn from(error: std::io::Error) -> Self { Self::Io(Arc::new(error)) } } impl From for RegistryError { fn from(error: serde_json::Error) -> Self { Self::Json(Arc::new(error)) } }