Files
cloud-server/src/constants.ts
kappa 9f3d3a245a refactor: simplify pricing tables to USD-only
- Remove KRW pricing calculations from all pricing tables
- Simplify pricing table to store only wholesale USD prices
- Simplify anvil_pricing to store only retail USD prices
- Remove KRW environment variables (KRW_EXCHANGE_RATE, KRW_MARGIN_RATE)
- Remove KRW functions from constants.ts
- Update GPU/G8/VPU pricing repositories to match
- Add Anvil tables and repositories for branded product support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 21:16:25 +09:00

278 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Cloud Server API - Constants
*
* Centralized constants for the cloud server API.
* All magic numbers and repeated constants should be defined here.
*/
// ============================================================
// Provider Configuration
// ============================================================
/**
* Supported cloud providers
*/
export const SUPPORTED_PROVIDERS = ['linode', 'vultr', 'aws'] as const;
export type SupportedProvider = typeof SUPPORTED_PROVIDERS[number];
// ============================================================
// Cache Configuration
// ============================================================
/**
* Cache TTL values in seconds
*/
export const CACHE_TTL = {
/** Cache TTL for instance queries (5 minutes) */
INSTANCES: 300,
/** Cache TTL for health checks (30 seconds) */
HEALTH: 30,
/** Cache TTL for pricing data (1 hour) */
PRICING: 3600,
/** Default cache TTL (5 minutes) */
DEFAULT: 300,
} as const;
/**
* Cache TTL values in milliseconds
*/
export const CACHE_TTL_MS = {
/** Cache TTL for instance queries (5 minutes) */
INSTANCES: 5 * 60 * 1000,
/** Cache TTL for health checks (30 seconds) */
HEALTH: 30 * 1000,
/** Cache TTL for pricing data (1 hour) */
PRICING: 60 * 60 * 1000,
} as const;
// ============================================================
// Rate Limiting Configuration
// ============================================================
/**
* Rate limiting defaults
*/
export const RATE_LIMIT_DEFAULTS = {
/** Time window in milliseconds (1 minute) */
WINDOW_MS: 60 * 1000,
/** Maximum requests per window for /instances endpoint */
MAX_REQUESTS_INSTANCES: 100,
/** Maximum requests per window for /sync endpoint */
MAX_REQUESTS_SYNC: 10,
} as const;
// ============================================================
// Pagination Configuration
// ============================================================
/**
* Pagination defaults
*/
export const PAGINATION = {
/** Default page number (1-indexed) */
DEFAULT_PAGE: 1,
/** Default number of results per page */
DEFAULT_LIMIT: 50,
/** Maximum number of results per page */
MAX_LIMIT: 100,
/** Default offset for pagination */
DEFAULT_OFFSET: 0,
} as const;
// ============================================================
// HTTP Status Codes
// ============================================================
/**
* HTTP status codes used throughout the API
*/
export const HTTP_STATUS = {
/** 200 - OK */
OK: 200,
/** 201 - Created */
CREATED: 201,
/** 204 - No Content */
NO_CONTENT: 204,
/** 400 - Bad Request */
BAD_REQUEST: 400,
/** 401 - Unauthorized */
UNAUTHORIZED: 401,
/** 404 - Not Found */
NOT_FOUND: 404,
/** 413 - Payload Too Large */
PAYLOAD_TOO_LARGE: 413,
/** 429 - Too Many Requests */
TOO_MANY_REQUESTS: 429,
/** 500 - Internal Server Error */
INTERNAL_ERROR: 500,
/** 503 - Service Unavailable */
SERVICE_UNAVAILABLE: 503,
} as const;
// ============================================================
// Database Configuration
// ============================================================
/**
* Database table names
*/
export const TABLES = {
PROVIDERS: 'providers',
REGIONS: 'regions',
INSTANCE_TYPES: 'instance_types',
PRICING: 'pricing',
PRICE_HISTORY: 'price_history',
} as const;
// ============================================================
// Query Configuration
// ============================================================
/**
* Valid sort fields for instance queries
*/
export const VALID_SORT_FIELDS = [
'price',
'hourly_price',
'monthly_price',
'vcpu',
'memory_mb',
'memory_gb',
'storage_gb',
'instance_name',
'provider',
'region',
] as const;
export type ValidSortField = typeof VALID_SORT_FIELDS[number];
/**
* Valid sort orders
*/
export const SORT_ORDERS = ['asc', 'desc'] as const;
export type SortOrder = typeof SORT_ORDERS[number];
/**
* Valid instance families
*/
export const INSTANCE_FAMILIES = ['general', 'compute', 'memory', 'storage', 'gpu'] as const;
export type InstanceFamily = typeof INSTANCE_FAMILIES[number];
// ============================================================
// CORS Configuration
// ============================================================
/**
* CORS configuration
*
* NOTE: localhost origin is included for development purposes.
* In production, filter allowed origins based on environment.
* Example: const allowedOrigins = CORS.ALLOWED_ORIGINS.filter(o => !o.includes('localhost'))
*/
export const CORS = {
/** Default CORS origin */
DEFAULT_ORIGIN: '*',
/** Allowed origins for CORS */
ALLOWED_ORIGINS: [
'https://anvil.it.com',
'https://cloud.anvil.it.com',
'https://hosting.anvil.it.com',
'http://localhost:3000', // DEVELOPMENT ONLY - exclude in production
] as string[],
/** Max age for CORS preflight cache (24 hours) */
MAX_AGE: '86400',
} as const;
// ============================================================
// Timeout Configuration
// ============================================================
/**
* Timeout values in milliseconds
*/
export const TIMEOUTS = {
/** Request timeout for AWS API calls (15 seconds) */
AWS_REQUEST: 15000,
/** Default API request timeout (30 seconds) */
DEFAULT_REQUEST: 30000,
} as const;
// ============================================================
// Validation Constants
// ============================================================
/**
* Validation rules
*/
export const VALIDATION = {
/** Minimum memory in MB */
MIN_MEMORY_MB: 1,
/** Minimum vCPU count */
MIN_VCPU: 1,
/** Minimum price in USD */
MIN_PRICE: 0,
} as const;
// ============================================================
// Request Security Configuration
// ============================================================
/**
* Request security limits
*/
export const REQUEST_LIMITS = {
/** Maximum request body size in bytes (10KB) */
MAX_BODY_SIZE: 10 * 1024,
} as const;
// ============================================================
// USD Retail Pricing Configuration
// ============================================================
/**
* Default USD retail pricing configuration
*
* These defaults are used to calculate retail prices from wholesale prices.
* Calculation formula:
* Retail = Wholesale × Margin (1.1) × VAT (1.1)
* Retail = Wholesale × 1.21
*/
export const USD_RETAIL_DEFAULTS = {
/** Margin multiplier (10% margin) */
MARGIN_MULTIPLIER: 1.1,
/** VAT multiplier (10% VAT) */
VAT_MULTIPLIER: 1.1,
/** Total multiplier (margin × VAT) */
TOTAL_MULTIPLIER: 1.21,
} as const;
/**
* Calculate USD retail hourly price from wholesale price
* Applies margin and VAT
*
* @param wholesale - Wholesale hourly price in USD
* @returns Retail price in USD, rounded to 4 decimal places
*
* @example
* calculateRetailHourly(0.0075) // Returns 0.0091 (with defaults)
* calculateRetailHourly(0.144) // Returns 0.1742 (with defaults)
*/
export function calculateRetailHourly(wholesale: number): number {
return Math.round(wholesale * USD_RETAIL_DEFAULTS.TOTAL_MULTIPLIER * 10000) / 10000;
}
/**
* Calculate USD retail monthly price from wholesale price
* Applies margin and VAT
*
* @param wholesale - Wholesale monthly price in USD
* @returns Retail price in USD, rounded to nearest $1
*
* @example
* calculateRetailMonthly(5) // Returns 6 (with defaults)
* calculateRetailMonthly(96) // Returns 116 (with defaults)
*/
export function calculateRetailMonthly(wholesale: number): number {
return Math.round(wholesale * USD_RETAIL_DEFAULTS.TOTAL_MULTIPLIER);
}