@push.rocks/smartregistry

A TypeScript library implementing the OCI Distribution Specification v1.1 for building container and artifact registries.

Features

  • OCI Distribution Spec v1.1 Compliant: Implements all required and optional endpoints
  • Cloud-Agnostic Storage: Uses @push.rocks/smartbucket for S3-compatible object storage
  • Pluggable Authentication: Async callbacks for login and authorization
  • Bearer Token Auth: JWT-based authentication following Docker Registry Token Authentication spec
  • Programmatic API: Use as a library in any Node.js/TypeScript application
  • Full CRUD Operations: Push, pull, list, and delete manifests and blobs
  • Content Discovery: Tag listing and referrers API for artifact relationships
  • Chunked Uploads: Support for large blob uploads with resumable sessions

Installation

npm install @push.rocks/smartregistry
# or
pnpm add @push.rocks/smartregistry

Usage

Basic Setup

import { SmartRegistry, IRegistryConfig, TLoginCallback, TAuthCallback } from '@push.rocks/smartregistry';

// Implement login callback
const loginCallback: TLoginCallback = async (credentials) => {
  // Validate credentials and return JWT token
  // This should create a proper JWT with required claims
  return generateJWT(credentials.username);
};

// Implement authorization callback
const authCallback: TAuthCallback = async (token, repository, action) => {
  // Validate token and check permissions
  const claims = verifyJWT(token);
  return hasPermission(claims, repository, action);
};

// Configure registry
const config: IRegistryConfig = {
  storage: {
    accessKey: 'your-s3-access-key',
    accessSecret: 'your-s3-secret',
    endpoint: 's3.amazonaws.com',
    port: 443,
    useSsl: true,
    region: 'us-east-1',
    bucketName: 'my-registry',
  },
  serviceName: 'my-registry',
  tokenRealm: 'https://auth.example.com/token',
  loginCallback,
  authCallback,
};

// Create and initialize registry
const registry = new SmartRegistry(config);
await registry.init();

Integration with HTTP Server

import express from 'express';

const app = express();

// OCI Distribution API endpoints
app.get('/v2/', (req, res) => {
  res.status(200).json({});
});

app.get('/v2/:name(*)/manifests/:reference', async (req, res) => {
  const { name, reference } = req.params;
  const token = req.headers.authorization?.replace('Bearer ', '');

  const result = await registry.getManifest(name, reference, token);

  if ('errors' in result) {
    return res.status(404).json(result);
  }

  res.setHeader('Content-Type', result.contentType);
  res.setHeader('Docker-Content-Digest', result.digest);
  res.send(result.data);
});

app.get('/v2/:name(*)/blobs/:digest', async (req, res) => {
  const { name, digest } = req.params;
  const token = req.headers.authorization?.replace('Bearer ', '');

  const result = await registry.getBlob(name, digest, token);

  if ('errors' in result) {
    return res.status(404).json(result);
  }

  res.setHeader('Content-Type', 'application/octet-stream');
  res.send(result.data);
});

// ... implement other endpoints

app.listen(5000);

Authentication Flow

// Client requests without token
const challenge = registry.getAuthChallenge('library/nginx', ['pull', 'push']);
// Returns: Bearer realm="https://auth.example.com/token",service="my-registry",scope="repository:library/nginx:pull,push"

// Client authenticates
const token = await registry.login({ username: 'user', password: 'pass' });

// Client uses token for subsequent requests
const manifest = await registry.getManifest('library/nginx', 'latest', token);

API Reference

Pull Operations (Required)

  • getManifest(repository, reference, token?) - Download a manifest
  • headManifest(repository, reference, token?) - Check manifest existence
  • getBlob(repository, digest, token?, range?) - Download a blob
  • headBlob(repository, digest, token?) - Check blob existence

Push Operations

  • initiateUpload(repository, token, mountDigest?, fromRepository?) - Start blob upload
  • uploadChunk(uploadId, data, contentRange, token) - Upload blob chunk
  • completeUpload(uploadId, digest, token, finalData?) - Finalize blob upload
  • putManifest(repository, reference, manifest, contentType, token) - Upload manifest

Content Discovery

  • listTags(repository, token?, pagination?) - List all tags
  • getReferrers(repository, digest, token?, artifactType?) - Get referencing artifacts

Content Management

  • deleteManifest(repository, digest, token) - Delete manifest
  • deleteBlob(repository, digest, token) - Delete blob
  • deleteTag(repository, tag, token) - Delete tag

Authentication

  • login(credentials) - Get authentication token
  • getAuthChallenge(repository, actions) - Generate WWW-Authenticate header

OCI Specification Compliance

This library implements:

  • Pull Category (required): All manifest and blob retrieval operations
  • Push Category: Complete blob upload workflow with chunked and monolithic modes
  • Content Discovery: Tag listing and referrers API
  • Content Management: Deletion operations for manifests, blobs, and tags

License

MIT

Contributing

See the main repository for contribution guidelines.

Description
a module implementing package registries for oci, npm, maven
Readme 1.1 MiB
Languages
TypeScript 100%