# @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 ```bash npm install @push.rocks/smartregistry # or pnpm add @push.rocks/smartregistry ``` ## Usage ### Basic Setup ```typescript 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 ```typescript 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 ```typescript // 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.