Documentation
Cloud Registry
Providers

Cloud Registry Providers

The @elixir-cloud/cloud-registry package provides providers for connecting to Cloud Registry APIs. The main provider is RestCloudRegistryProvider which implements the CloudRegistryProvider interface for REST-based cloud registry endpoints with both read and write capabilities.

Quick Start: Create a RestCloudRegistryProvider with your cloud registry URL and pass it to Cloud Registry components to start creating and managing services.

CloudRegistryProvider Interface

The CloudRegistryProvider interface extends ServiceRegistryProvider and defines the operations that all Cloud Registry providers must implement:

export interface CloudRegistryProvider extends ServiceRegistryProvider {
  // Inherited from ServiceRegistryProvider
  getServices(): Promise<ExternalService[]>;
  getServiceById(id: string): Promise<ExternalService>;
  getServiceTypes(): Promise<ServiceType[]>;
  // with the registration rules (Cloud Registry 0.6.0 and later)
  getServiceInfo(): Promise<RegistryServiceInfo>;
  
  // Cloud Registry specific methods for service management
  createService(service: ExternalServiceRegister): Promise<string>;
  createServiceWithId(id: string, service: ExternalServiceRegister): Promise<string>;
 
  // Update methods (Cloud Registry specific)
  updateService(id: string, service: ExternalServiceRegister): Promise<string>;
 
  // Deletion methods (Cloud Registry specific)
  deleteService?(id: string): Promise<string>;
 
  // Service info methods (Cloud Registry specific)
  createOrUpdateServiceInfo?(service: ServiceRegister): Promise<void>;
}

RestCloudRegistryProvider

The RestCloudRegistryProvider is the main implementation that communicates with Cloud Registry APIs using REST/HTTP.

Constructor

constructor(baseUrl: string)

Parameters:

  • baseUrl: The base URL of the Cloud Registry API endpoint (e.g., https://cloud-registry.example.com/ga4gh/registry/v1)

Basic Usage

import { RestCloudRegistryProvider } from '@elixir-cloud/cloud-registry/providers';
import { EccClientElixirCloudRegistryServiceCreate } from '@elixir-cloud/cloud-registry';
 
function ServiceCreator() {
  const provider = new RestCloudRegistryProvider(
    'https://cloud-registry.example.com/ga4gh/registry/v1'
  );
 
  return (
    <div>
      <h2>Register New Service</h2>
      <EccClientElixirCloudRegistryServiceCreate provider={provider} />
    </div>
  );
}

Provider Methods

createService()

Creates a new service in the cloud registry.

createService(service: ExternalServiceRegister): Promise<string>

createServiceWithId()

Creates a new service with a specific ID.

createServiceWithId(id: string, service: ExternalServiceRegister): Promise<string>

updateService()

Updates an existing service's information.

updateService(id: string, service: ExternalServiceRegister): Promise<string>

deleteService()

Removes a service from the registry.

deleteService?(id: string): Promise<string>

createOrUpdateServiceInfo()

Creates or updates the service registry's own service information.

createOrUpdateServiceInfo?(service: ServiceRegister): Promise<void>

Errors

If the registry answers with an error status, the methods of RestCloudRegistryProvider reject with a CloudRegistryError. It extends Error and carries the status and the problem details (opens in a new tab) that the registry sends:

PropertyTypeDescription
messagestringThe problem's detail (else a message field, as some servers send), or the failed action and the status, e.g. "Failed to create service (502)"
statusnumberHTTP status, e.g. 401 (log in) or 403 (no role on the service)
titlestring | undefinedShort summary of the problem type, e.g. "Conflict"
detailstring | undefinedExplanation of this occurrence, e.g. which field is invalid
serviceIdstring | undefinedID of the existing service, for duplicate registrations (409)
problemProblemDetails | undefinedThe whole response body, if it was a JSON object
import {
  CloudRegistryError,
  RestCloudRegistryProvider,
} from '@elixir-cloud/cloud-registry/providers';
 
const provider = new RestCloudRegistryProvider(
  'https://cloud-registry.example.com/ga4gh/registry/v1'
);
 
try {
  await provider.createService(service);
} catch (error) {
  if (error instanceof CloudRegistryError && error.status === 401) {
    // ask the user to log in
  } else if (error instanceof CloudRegistryError && error.status === 409) {
    console.log('Already registered as', error.serviceId);
  }
}

Type Definitions

ServiceTypeRegister

interface ServiceTypeRegister {
  group: string;
  artifact: string;
  version: string;
}

ServiceRegister

interface ServiceRegister {
  id: string;
  name: string;
  type: ServiceTypeRegister;
  description?: string;
  organization: Organization;
  contactUrl?: string;
  documentationUrl?: string;
  createdAt?: string;
  updatedAt?: string;
  environment?: string;
  version: string;
}

ExternalServiceRegister

interface ExternalServiceRegister {
  name: string;
  type: ServiceTypeRegister;
  description?: string;
  organization: Organization;
  contactUrl?: string;
  documentationUrl?: string;
  createdAt?: string;
  updatedAt?: string;
  environment?: string;
  version: string;
  url: string;
}

RegistryServiceInfo and RegistrationRules

Cloud Registry 0.6.0 and later extend their service info (getServiceInfo()) with the rules for registrations, which the create form reads (e.g. the allowed environments). Custom providers can return them from getServiceInfo(); without them, the form falls back to its properties.

interface RegistryServiceInfo extends Service {
  registration_rules?: RegistrationRules;
}
 
interface RegistrationRules {
  environments: string[]; // empty if any value is allowed
  url_schemes: string[]; // e.g. ['https']
  service_types: string; // 'open', 'controlled' or 'moderated'
  max_unused_service_types?: number;
}

Using with Components

Service Creation

import { RestCloudRegistryProvider } from '@elixir-cloud/cloud-registry/providers';
import { EccClientElixirCloudRegistryServiceCreate } from '@elixir-cloud/cloud-registry';
 
// created once: a new provider makes the components load their data again
const provider = new RestCloudRegistryProvider('https://cloud-registry.example.com/ga4gh/registry/v1');
 
function ServiceRegistration() {
 
  return (
    <EccClientElixirCloudRegistryServiceCreate 
      provider={provider}
      onEccServiceCreated={(event) => {
        console.log('Service created:', event.detail.serviceId);
        // Navigate to service details or show success message
      }}
      onEccServiceCreateFailed={(event) => {
        console.error('Service creation failed:', event.detail.error);
      }}
      onEccServiceCreateValidationFailed={(event) => {
        console.error('Validation failed:', event.detail.errors);
      }}
    />
  );
}

Combined Service Management

import { RestCloudRegistryProvider } from '@elixir-cloud/cloud-registry/providers';
import { 
  EccClientGa4ghServiceRegistryServices,
  EccClientElixirCloudRegistryServiceCreate 
} from '@elixir-cloud/cloud-registry';
 
// created once: a new provider makes the components load their data again
const provider = new RestCloudRegistryProvider('https://cloud-registry.example.com/ga4gh/registry/v1');
 
function ServiceManagement() {
  const [view, setView] = useState('list');
 
  return (
    <div>
      <nav>
        <button onClick={() => setView('list')}>View Services</button>
        <button onClick={() => setView('create')}>Create Service</button>
      </nav>
 
      {view === 'list' && (
        <EccClientGa4ghServiceRegistryServices provider={provider} />
      )}
 
      {view === 'create' && (
        <EccClientElixirCloudRegistryServiceCreate 
          provider={provider}
          onEccServiceCreated={() => setView('list')}
        />
      )}
    </div>
  );
}

Custom Providers

For custom use cases, you can extend RestCloudRegistryProvider or implement the CloudRegistryProvider interface directly. This is useful for:

  • Adding custom authentication
  • Implementing caching or offline support
  • Connecting to non-standard APIs
  • Adding custom error handling or retry logic
// Example: Custom provider with authentication
class CustomCloudRegistryProvider extends RestCloudRegistryProvider {
  constructor(baseUrl, apiKey) {
    super(baseUrl);
    this.apiKey = apiKey;
  }
 
  async fetch(url, options = {}) {
    return super.fetch(url, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        ...options.headers
      }
    });
  }
}

For comprehensive patterns and examples, see the Providers Overview documentation.

Testing

Test your Cloud Registry provider setup:

async function testCloudRegistryProvider(provider) {
  try {
    console.log('Testing Cloud Registry provider...');
    
    // Test service info
    const serviceInfo = await provider.getServiceInfo();
    console.log('✅ Service info:', serviceInfo.name);
    
    // Test service creation with a test service
    const testService = {
      name: "test-service-" + Date.now(),
      type: {
        group: "org.ga4gh",
        artifact: "test",
        version: "1.0.0"
      },
      description: "Test service for provider validation",
      organization: {
        name: "Test Organization",
        url: "https://test.example.com"
      },
      version: "1.0.0"
    };
 
    const serviceId = await provider.createService(testService);
    console.log('✅ Service creation works:', serviceId);
    
    // Test service retrieval
    const retrievedService = await provider.getServiceById(serviceId);
    console.log('✅ Service retrieval works:', retrievedService.name);
    
    // Clean up test service
    await provider.deleteService(serviceId);
    console.log('✅ Service deletion works');
    
    console.log('✅ Cloud Registry provider is working correctly!');
    return true;
  } catch (error) {
    console.error('❌ Cloud Registry provider test failed:', error);
    return false;
  }
}
 
// Usage
const provider = new RestCloudRegistryProvider('https://cloud-registry.example.com/ga4gh/registry/v1');
testCloudRegistryProvider(provider);

Next Steps: Check the Providers Overview for patterns on authentication, error handling, caching, and environment configuration that you can apply to your Cloud Registry provider.

Released under Apache 2.0 License.

Copyright © 2023-2026 ELIXIR