@bramato/openrouter-mock-generator
Version:
AI-powered mock data generator using OpenRouter API with JSON mode support
263 lines • 11.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DigitalOceanSpaces = void 0;
const crypto_1 = require("crypto");
class DigitalOceanSpaces {
constructor(config) {
this.config = config;
this.endpoint = config.endpoint || `https://${config.region}.digitaloceanspaces.com`;
this.cdnEndpoint = `https://${config.spaceName}.${config.region}.cdn.digitaloceanspaces.com`;
}
static getAvailableRegions() {
return this.AVAILABLE_REGIONS;
}
async listSpaces() {
try {
const timestamp = new Date().toISOString().replace(/[:-]|\.\d{3}/g, '');
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
const headers = {
Host: `${this.config.region}.digitaloceanspaces.com`,
'x-amz-date': timestamp,
'x-amz-content-sha256': this.sha256(''),
};
const authorization = this.generateAuthHeader('GET', '/', headers, timestamp, date);
const response = await fetch(`${this.endpoint}/`, {
method: 'GET',
headers: {
...headers,
Authorization: authorization,
},
});
if (!response.ok) {
throw new Error(`Failed to list spaces: ${response.status} ${response.statusText}`);
}
const xmlText = await response.text();
return this.parseListBucketsResponse(xmlText);
}
catch (error) {
console.error('Error listing spaces:', error);
throw error;
}
}
async createSpace(spaceName, region, makePublic = true) {
const targetRegion = region || this.config.region;
const spaceEndpoint = `https://${targetRegion}.digitaloceanspaces.com`;
try {
const timestamp = new Date().toISOString().replace(/[:-]|\.\d{3}/g, '');
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
const headers = {
Host: `${spaceName}.${targetRegion}.digitaloceanspaces.com`,
'x-amz-date': timestamp,
'x-amz-content-sha256': this.sha256(''),
};
if (makePublic) {
headers['x-amz-acl'] = 'public-read';
}
const authorization = this.generateAuthHeader('PUT', '/', headers, timestamp, date, targetRegion);
const response = await fetch(`https://${spaceName}.${targetRegion}.digitaloceanspaces.com/`, {
method: 'PUT',
headers: {
...headers,
Authorization: authorization,
},
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Failed to create space: ${response.status} ${response.statusText}\n${errorText}`);
}
console.log(`✅ Space "${spaceName}" created successfully in region ${targetRegion}`);
return {
name: spaceName,
region: targetRegion,
endpoint: `https://${spaceName}.${targetRegion}.digitaloceanspaces.com`,
cdnEndpoint: `https://${spaceName}.${targetRegion}.cdn.digitaloceanspaces.com`,
createdAt: new Date().toISOString(),
};
}
catch (error) {
console.error(`Error creating space "${spaceName}":`, error);
throw error;
}
}
async uploadImage(imageData, filename, contentType = 'image/png', makePublic = true) {
if (!this.config.spaceName) {
throw new Error('Space name is required for upload');
}
const buffer = typeof imageData === 'string' ? Buffer.from(imageData, 'base64') : imageData;
const key = this.generateImageKey(filename);
try {
const url = await this.uploadToSpace(buffer, key, contentType, makePublic);
return {
url,
key,
cdnUrl: `${this.cdnEndpoint}/${key}`,
};
}
catch (error) {
console.error('Failed to upload image to DigitalOcean Space:', error);
throw new Error(`Space upload failed: ${error}`);
}
}
async uploadMultipleImages(images) {
const results = [];
for (const image of images) {
try {
const result = await this.uploadImage(image.data, image.filename, image.contentType);
results.push(result);
}
catch (error) {
console.error(`Failed to upload ${image.filename}:`, error);
results.push({
url: '',
key: '',
etag: `ERROR: ${error}`,
});
}
}
return results;
}
async uploadToSpace(buffer, key, contentType, makePublic = true) {
const url = `https://${this.config.spaceName}.${this.config.region}.digitaloceanspaces.com/${key}`;
const timestamp = new Date().toISOString().replace(/[:-]|\.\d{3}/g, '');
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
const headers = {
'Content-Type': contentType,
'Content-Length': buffer.length.toString(),
'x-amz-content-sha256': this.sha256(buffer),
'x-amz-date': timestamp,
Host: `${this.config.spaceName}.${this.config.region}.digitaloceanspaces.com`,
};
if (makePublic) {
headers['x-amz-acl'] = 'public-read';
}
const authorization = this.generateAuthHeader('PUT', `/${key}`, headers, timestamp, date);
const response = await fetch(url, {
method: 'PUT',
headers: {
...headers,
Authorization: authorization,
},
body: buffer,
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Space upload failed: ${response.status} ${response.statusText}\n${errorText}`);
}
return url;
}
generateImageKey(filename) {
const timestamp = new Date().toISOString().slice(0, 10);
const hash = (0, crypto_1.createHash)('md5')
.update(filename + Date.now())
.digest('hex')
.slice(0, 8);
const extension = filename.split('.').pop() || 'png';
return `generated-images/${timestamp}/${hash}.${extension}`;
}
generateAuthHeader(method, path, headers, timestamp, date, region) {
const targetRegion = region || this.config.region;
const service = 's3';
// Create canonical request
const canonicalHeaders = Object.entries(headers)
.map(([k, v]) => `${k.toLowerCase()}:${v}`)
.sort()
.join('\n');
const signedHeaders = Object.keys(headers)
.map(k => k.toLowerCase())
.sort()
.join(';');
const canonicalRequest = [
method,
path,
'',
canonicalHeaders,
'',
signedHeaders,
headers['x-amz-content-sha256'],
].join('\n');
// Create string to sign
const credentialScope = `${date}/${targetRegion}/${service}/aws4_request`;
const stringToSign = [
'AWS4-HMAC-SHA256',
timestamp,
credentialScope,
this.sha256(canonicalRequest),
].join('\n');
// Calculate signature
const signature = this.calculateSignature(stringToSign, date, targetRegion, service);
// Return authorization header
return `AWS4-HMAC-SHA256 Credential=${this.config.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
}
calculateSignature(stringToSign, date, region, service) {
const kDate = this.hmacSha256(`AWS4${this.config.secretAccessKey}`, date);
const kRegion = this.hmacSha256(kDate, region);
const kService = this.hmacSha256(kRegion, service);
const kSigning = this.hmacSha256(kService, 'aws4_request');
return this.hmacSha256(kSigning, stringToSign).toString('hex');
}
hmacSha256(key, data) {
const crypto = require('crypto');
return crypto.createHmac('sha256', key).update(data).digest();
}
sha256(data) {
return (0, crypto_1.createHash)('sha256').update(data).digest('hex');
}
parseListBucketsResponse(xmlText) {
const spaces = [];
// Simple XML parsing per estrarre i bucket
const bucketMatches = xmlText.match(/<Bucket>[\s\S]*?<\/Bucket>/g);
if (bucketMatches) {
bucketMatches.forEach(bucketXml => {
const nameMatch = bucketXml.match(/<Name>(.*?)<\/Name>/);
const dateMatch = bucketXml.match(/<CreationDate>(.*?)<\/CreationDate>/);
if (nameMatch) {
spaces.push({
name: nameMatch[1],
region: this.config.region,
endpoint: `https://${nameMatch[1]}.${this.config.region}.digitaloceanspaces.com`,
cdnEndpoint: `https://${nameMatch[1]}.${this.config.region}.cdn.digitaloceanspaces.com`,
createdAt: dateMatch ? dateMatch[1] : undefined,
});
}
});
}
return spaces;
}
async testConnection() {
try {
await this.listSpaces();
return true;
}
catch (error) {
console.error('DigitalOcean Spaces connection test failed:', error);
return false;
}
}
async enableCDN(spaceName) {
const targetSpace = spaceName || this.config.spaceName;
if (!targetSpace) {
throw new Error('Space name is required to enable CDN');
}
// Note: CDN enabling typically requires DigitalOcean API, not Spaces API
// For now, return the CDN URL format
const cdnUrl = `https://${targetSpace}.${this.config.region}.cdn.digitaloceanspaces.com`;
console.log(`📡 CDN URL for space "${targetSpace}": ${cdnUrl}`);
console.log('💡 Enable CDN manually in DigitalOcean Control Panel for optimal performance');
return cdnUrl;
}
}
exports.DigitalOceanSpaces = DigitalOceanSpaces;
// Regioni disponibili per DigitalOcean Spaces
DigitalOceanSpaces.AVAILABLE_REGIONS = [
{ code: 'nyc3', name: 'New York 3', location: 'New York, USA' },
{ code: 'ams3', name: 'Amsterdam 3', location: 'Amsterdam, Netherlands' },
{ code: 'lon1', name: 'London 1', location: 'London, UK' },
{ code: 'sgp1', name: 'Singapore 1', location: 'Singapore' },
{ code: 'sfo2', name: 'San Francisco 2', location: 'San Francisco, USA' },
{ code: 'sfo3', name: 'San Francisco 3', location: 'San Francisco, USA' },
{ code: 'tor1', name: 'Toronto 1', location: 'Toronto, Canada' },
{ code: 'fra1', name: 'Frankfurt 1', location: 'Frankfurt, Germany' },
{ code: 'blr1', name: 'Bangalore 1', location: 'Bangalore, India' },
{ code: 'syd1', name: 'Sydney 1', location: 'Sydney, Australia' },
];
//# sourceMappingURL=digitalocean-spaces.js.map