feat: add configurable VPS provider API URLs for emulator testing

- Add LINODE_API_URL and VULTR_API_URL environment variables
- Update LinodeProvider and VultrProvider to accept optional baseUrl
- Update ProvisioningService to pass API URLs to providers
- Add source_provider and source_region_code to PricingWithProvider type
- Use source_provider (linode/vultr) instead of provider_name (Anvil)
- Improve error handling for non-JSON responses in LinodeProvider

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-28 10:21:27 +09:00
parent 006b938ad2
commit 7d9edc14a3
7 changed files with 51 additions and 18 deletions

View File

@@ -26,10 +26,12 @@ interface LinodeError {
}
export class LinodeProvider extends VPSProviderBase {
constructor(apiKey: string, timeout: number = 30000) {
static readonly DEFAULT_BASE_URL = 'https://api.linode.com/v4';
constructor(apiKey: string, baseUrl?: string, timeout: number = 30000) {
super({
apiKey,
baseUrl: 'https://api.linode.com/v4',
baseUrl: baseUrl || LinodeProvider.DEFAULT_BASE_URL,
timeout,
});
}
@@ -58,18 +60,32 @@ export class LinodeProvider extends VPSProviderBase {
body: JSON.stringify(body),
});
// Read response text first to handle both JSON and HTML errors
const responseText = await response.text();
if (!response.ok) {
const error = (await response.json()) as LinodeError;
return {
success: false,
error: {
code: `LINODE_${response.status}`,
message: error.errors?.[0]?.reason || 'Unknown error',
},
};
// Try to parse as JSON, but handle HTML responses gracefully
try {
const error = JSON.parse(responseText) as LinodeError;
return {
success: false,
error: {
code: `LINODE_${response.status}`,
message: error.errors?.[0]?.reason || 'Unknown error',
},
};
} catch {
return {
success: false,
error: {
code: `LINODE_${response.status}`,
message: `Non-JSON response: ${responseText.substring(0, 200)}`,
},
};
}
}
const data = (await response.json()) as LinodeInstance;
const data = JSON.parse(responseText) as LinodeInstance;
return {
success: true,