@hivetechs/hive-ai
Version:
Real-time streaming AI consensus platform with HTTP+SSE MCP integration for Claude Code, VS Code, Cursor, and Windsurf - powered by OpenRouter's unified API
137 lines • 4.5 kB
JavaScript
import { getLicenseKeyFromDB, saveLicenseKeyToDB, getConfig, setConfig, initializeDatabase } from '../storage/database.js';
export async function getLicenseKey() {
try {
// Ensure database is initialized
await initializeDatabase();
return await getLicenseKeyFromDB();
}
catch (error) {
console.error('Error getting license key:', error);
return null;
}
}
export async function saveLicenseKey(licenseKey, email) {
try {
// Ensure database is initialized
await initializeDatabase();
await saveLicenseKeyToDB(licenseKey, email);
}
catch (error) {
console.error('Error saving license key:', error);
throw error;
}
}
export async function getCachedSubscription() {
try {
// Get cached subscription info from SQLite
const cachedData = await getConfig('subscription_cache');
if (!cachedData) {
return null;
}
const cache = JSON.parse(cachedData);
// Check if cache is still valid (24 hours)
const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours
const cacheAge = Date.now() - new Date(cache.cachedAt).getTime();
if (cacheAge < CACHE_DURATION) {
return cache.subscription;
}
}
catch (error) {
console.error('Error getting cached subscription:', error);
}
return null;
}
export async function cacheSubscription(subscription) {
try {
const cacheData = {
subscription,
cachedAt: new Date().toISOString()
};
await setConfig('subscription_cache', JSON.stringify(cacheData));
}
catch (error) {
console.error('Error caching subscription:', error);
throw error;
}
}
export async function validateSubscription(licenseKey) {
// First check cache
const cached = await getCachedSubscription();
if (cached && !licenseKey) {
return cached;
}
// Get license key
const key = licenseKey || await getLicenseKey();
if (!key) {
return {
valid: false,
error: 'No license key found. Run "hive-ai configure" to add your license key.'
};
}
try {
// Import configurable endpoints (SECURITY: Remove hardcoded domains)
const { getApiEndpoint } = await import('../config/endpoints.js');
// Call the Cloudflare API to validate subscription
const response = await fetch(getApiEndpoint('subscription'), {
method: 'POST',
headers: {
'Authorization': `Bearer ${key}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
const error = await response.text();
return {
valid: false,
error: `Subscription validation failed: ${error}`
};
}
const data = await response.json();
const subscription = {
valid: data.active,
plan: data.plan,
email: data.email,
expiresAt: data.expiresAt,
remainingConversations: data.remainingConversations
};
// Cache the result
await cacheSubscription(subscription);
return subscription;
}
catch (error) {
// Fallback to cached subscription if available
if (cached) {
console.warn('Failed to validate subscription online, using cached data');
return cached;
}
return {
valid: false,
error: `Failed to validate subscription: ${error}`
};
}
}
export async function reportUsage(conversationId) {
const licenseKey = await getLicenseKey();
if (!licenseKey)
return;
try {
// Import configurable endpoints (SECURITY: Remove hardcoded domains)
const { getApiEndpoint } = await import('../config/endpoints.js');
await fetch(getApiEndpoint('usage'), {
method: 'POST',
headers: {
'Authorization': `Bearer ${licenseKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
conversationId,
timestamp: new Date().toISOString()
})
});
}
catch (error) {
// Silently fail - don't interrupt the user experience
console.error('Failed to report usage:', error);
}
}
//# sourceMappingURL=validator.js.map