Registry Abstraction
Relevant source files
The following files were used as context for generating this wiki page:
- packages/core/src/registry/package-registry.ts
- packages/core/tests/unit/registry/catalog.test.ts
- packages/core/tests/unit/registry/manifest-reader-integration.test.ts
- packages/core/tests/unit/ecosystem/infer.test.ts
- packages/core/tests/unit/tasks/required-conditions-check.test.ts
- plugins/pubm-plugin/skills/publish-setup/SKILL.md
The Registry Abstraction system in pubm provides a unified interface for interacting with diverse package registries such as npm, JSR, and crates.io. By abstracting registry-specific logic—including authentication, manifest reading, and publishing protocols—the system allows the core CLI to manage multi-registry releases through a single, consistent workflow.
This architecture supports automatic ecosystem detection, pre-publish validation, and concurrent publishing across different platforms. It also handles private registries by allowing custom URL and token configurations while adhering to the same abstract interface used by built-in registries.
Core Architecture
The system is built around an abstract base class that defines the lifecycle and capabilities of a registry handler. Registry-specific implementations extend this base to provide concrete logic for network requests and CLI tool invocations.
The PackageRegistry Base Class
The PackageRegistry abstract class serves as the blueprint for all registry interactions. It enforces a contract for checking package existence, verifying permissions, and executing the publish command.
The diagram shows the inheritance hierarchy where specialized registries implement the abstract members of the core Registry class.
Sources: packages/core/src/registry/package-registry.ts:12-104, packages/core/tests/unit/registry/catalog.test.ts:133-145
Registry Catalog and Descriptors
The RegistryCatalog manages a collection of RegistryDescriptor objects. These descriptors contain metadata and factory functions used to instantiate the correct registry handler based on the project's configuration or auto-detection results.
| Field | Description |
|---|---|
key | Unique identifier for the registry (e.g., "npm", "jsr"). |
ecosystem | The target environment ("js" or "rust"). |
tokenConfig | Defines environment variables and labels for authentication tokens. |
factory | Async function that creates an instance of the specific PackageRegistry. |
taskFactory | Generates Listr2 tasks for publish and dry-run operations. |
Sources: packages/core/tests/unit/registry/catalog.test.ts:24-42, packages/core/tests/unit/registry/catalog.test.ts:107-131
Automated Registry Inference
pubm utilizes a "Zero Config" approach by scanning project manifest files to determine which registries should be targeted.
Logic flow for inferring target registries based on the presence of specific manifest files and configuration entries.
Sources: packages/core/tests/unit/ecosystem/infer.test.ts:26-177, plugins/pubm-plugin/skills/publish-setup/SKILL.md:38-49
Inference Rules
- npm: Inferred if
package.jsonexists. If apublishConfig.registryor.npmrcregistry entry is found, it replaces the default npm registry with a custom URL. - JSR: Inferred if
jsr.json,deno.json, ordeno.jsoncexists.deno.jsonmust containname,version, andexportsfields to be considered a publishable JSR package. - crates.io: Inferred for any project containing a
Cargo.tomlfile in the Rust ecosystem.
Sources: packages/core/tests/unit/ecosystem/infer.test.ts:31-62, packages/core/tests/unit/ecosystem/infer.test.ts:193-217
Validation and Preflight Checks
Before any publishing actions occur, the registry abstraction facilitates a series of required condition checks to ensure the environment is ready.
Registry Connectivity and Auth
The system pings each configured registry to verify network availability and validates authentication tokens stored in the OS keychain or provided via environment variables.
| Registry | Token Env Var | Validation Endpoint / Logic |
|---|---|---|
| npm | NODE_AUTH_TOKEN | GET /-/whoami |
| JSR | JSR_TOKEN | GET /api/user |
| crates.io | CARGO_REGISTRY_TOKEN | Length check (min 32 chars) |
Sources: packages/core/tests/unit/registry/catalog.test.ts:213-288, packages/core/tests/unit/tasks/required-conditions-check.test.ts:133-195
Availability Checks
Each registry implementation provides a checkAvailability method. This method determines if the package name is available or if the user has the necessary permissions to publish a new version. If a package is already published, it verifies if the specific version being released is already taken.
Sources: packages/core/src/registry/package-registry.ts:93-104, packages/core/tests/unit/tasks/required-conditions-check.test.ts:400-445
Registry-Specific Implementations
JavaScript Registries (npm/JSR)
JavaScript registries often share the same source code but require different manifest formats. The abstraction layer uses a ManifestReader to unify these inputs.
- npm: Primary focus is on
package.json. It supports "provenance" in CI environments and requiresid-token: writepermissions. - JSR: Uses
jsr.jsonordeno.json. JSR descriptors often require "early auth" (authentication verification earlier in the pipeline).
Sources: packages/core/tests/unit/registry/manifest-reader-integration.test.ts:21-125, packages/core/tests/unit/registry/catalog.test.ts:184-187
Rust Registry (crates.io)
The CratesPackageRegistry interacts with Cargo.toml. Unlike JS registries, crates.io publishing is typically not concurrent (sequential ordering is often required for dependency management) and uses the "Yank" terminology for unpublishing.
Sources: packages/core/tests/unit/registry/manifest-reader-integration.test.ts:127-200, packages/core/tests/unit/registry/catalog.test.ts:176-182
Data Flow for Multi-Registry Publishing
The following sequence illustrates how the registry abstraction handles a single release across multiple targets:
Conclusion
The Registry Abstraction provides the extensibility required for pubm to serve as a universal publisher. By standardizing how registries are detected, validated, and targeted, the system ensures that adding support for new platforms or private internal registries requires minimal changes to the core publishing logic.