npm package: @infrasamurai/hosting-core
Description: Core interfaces and base classes for hosting providers
Latest version: 0.0.2

# @infrasamurai/hosting-core

Core interfaces, base classes, and schema types for InfraSamurai hosting providers.

## Installation

```bash
npm install @infrasamurai/hosting-core
# or
yarn add @infrasamurai/hosting-core
```

## Overview

This package provides:

- **Interfaces**: `IHostingProvider`, `INetworkCapableProvider` - contracts for provider implementations
- **Models**: `ServerLocation`, `ServerType`, `ServerImage`, `CreateServerRequest`, etc.
- **Base Class**: `BaseHostingProvider` - common functionality with retry logic
- **Errors**: `HostingError`, `HostingErrorType`, `classifyHostingError`
- **Schema Types**: `ProviderUISchema`, `FieldDefinition` - for dynamic UI rendering

## Usage

### Implementing a Provider

```typescript
import {
  BaseHostingProvider,
  IHostingProvider,
  INetworkCapableProvider,
  HostingProviderType,
  ServerLocation,
  ServerType,
  ServerImage,
  ProviderSshKey,
  ProviderNetwork,
  CreateServerRequest,
  CreateServerResponse,
  ServerDetails,
  HostingProvisioningStep,
  classifyHostingError,
} from '@infrasamurai/hosting-core';

export class MyCloudProvider
  extends BaseHostingProvider
  implements INetworkCapableProvider
{
  readonly providerType: HostingProviderType = 'MYCLOUD';

  async validateCredentials(): Promise<{ valid: boolean; error?: string }> {
    try {
      await this.request('GET', '/account');
      return { valid: true };
    } catch (error) {
      return { valid: false, error: error.message };
    }
  }

  async getLocations(): Promise<ServerLocation[]> {
    try {
      const response = await this.request('GET', '/locations');
      return response.locations.map(this.mapLocation);
    } catch (error) {
      throw classifyHostingError(error, HostingProvisioningStep.VALIDATE_CREDENTIAL);
    }
  }

  async getNetworks(): Promise<ProviderNetwork[]> {
    // ...
  }

  // ... implement other methods
}
```

### Type Guards

```typescript
import { hasNetworkCapability, IHostingProvider } from '@infrasamurai/hosting-core';

function getNetworksIfSupported(provider: IHostingProvider) {
  if (hasNetworkCapability(provider)) {
    return provider.getNetworks();
  }
  return [];
}
```

### Error Handling

```typescript
import {
  HostingError,
  HostingErrorType,
  HostingProvisioningStep,
} from '@infrasamurai/hosting-core';

try {
  await provider.createServer({ ... });
} catch (error) {
  if (error instanceof HostingError) {
    if (error.errorType === HostingErrorType.QUOTA_EXCEEDED) {
      console.error('Quota exceeded:', error.getUserMessage());
    }
    if (error.isRetryable()) {
      // Can retry this operation
    }
  }
}
```

### Custom Logger

```typescript
import { BaseHostingProvider, ProviderLogger } from '@infrasamurai/hosting-core';

const logger: ProviderLogger = {
  debug: (msg) => console.debug(`[DEBUG] ${msg}`),
  log: (msg) => console.log(`[INFO] ${msg}`),
  warn: (msg) => console.warn(`[WARN] ${msg}`),
  error: (msg) => console.error(`[ERROR] ${msg}`),
};

const provider = new MyCloudProvider('token', { logger });
```

## API Reference

### Interfaces

#### IHostingProvider

```typescript
interface IHostingProvider {
  readonly providerType: HostingProviderType;

  validateCredentials(): Promise<{ valid: boolean; error?: string }>;
  getLocations(): Promise<ServerLocation[]>;
  getServerTypes(location?: string): Promise<ServerType[]>;
  getImages(): Promise<ServerImage[]>;
  getSshKeys(): Promise<ProviderSshKey[]>;
  createSshKey(name: string, publicKey: string): Promise<ProviderSshKey>;
  deleteSshKey(keyId: string): Promise<void>;
  createServer(request: CreateServerRequest): Promise<CreateServerResponse>;
  getServer(serverId: string): Promise<ServerDetails>;
  waitForServerReady(serverId: string, timeoutMs?: number): Promise<ServerDetails>;
  deleteServer(serverId: string): Promise<void>;
}
```

#### INetworkCapableProvider

```typescript
interface INetworkCapableProvider extends IHostingProvider {
  getNetworks(): Promise<ProviderNetwork[]>;
}
```

### BaseProviderOptions

```typescript
interface BaseProviderOptions {
  logger?: ProviderLogger;      // Custom logger
  httpTimeout?: number;         // Request timeout (default: 30000ms)
  pollInterval?: number;        // Polling interval (default: 5000ms)
  maxWaitTime?: number;         // Max wait time (default: 300000ms)
  maxRetries?: number;          // Max retries (default: 3)
  retryDelayMs?: number;        // Initial retry delay (default: 1000ms)
}
```

### Error Types

```typescript
enum HostingErrorType {
  CREDENTIAL_NOT_FOUND,
  CREDENTIAL_INVALID,
  API_AUTH_FAILED,
  API_RATE_LIMITED,
  API_TIMEOUT,
  API_NETWORK_ERROR,
  API_ERROR,
  RESOURCE_NOT_FOUND,
  QUOTA_EXCEEDED,
  INVALID_REQUEST,
  SERVER_CREATION_FAILED,
  SERVER_NOT_FOUND,
  SERVER_NOT_READY,
  SSH_KEY_SYNC_FAILED,
  SSH_CONNECTION_FAILED,
  TIMEOUT,
  UNKNOWN,
}
```

## License

MIT