chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
// Command Usage Tracking API Endpoint - Neon Database
|
||||
// Tracks CLI command executions for community analytics
|
||||
|
||||
import { neon } from '@neondatabase/serverless';
|
||||
|
||||
// Initialize Neon client
|
||||
function getNeonClient() {
|
||||
const connectionString = process.env.NEON_DATABASE_URL;
|
||||
|
||||
if (!connectionString) {
|
||||
throw new Error('NEON_DATABASE_URL not configured');
|
||||
}
|
||||
|
||||
return neon(connectionString);
|
||||
}
|
||||
|
||||
// Validate command data
|
||||
function validateCommandData(data) {
|
||||
const { command, cliVersion, nodeVersion, platform } = data;
|
||||
|
||||
if (!command) {
|
||||
return { valid: false, error: 'Command name is required' };
|
||||
}
|
||||
|
||||
// Valid commands to track
|
||||
const validCommands = [
|
||||
'chats',
|
||||
'analytics',
|
||||
'health-check',
|
||||
'plugins',
|
||||
'sandbox',
|
||||
'agents',
|
||||
'chats-mobile',
|
||||
'studio',
|
||||
'command-stats',
|
||||
'hook-stats',
|
||||
'mcp-stats',
|
||||
'skills-manager',
|
||||
'2025-year-in-review'
|
||||
];
|
||||
|
||||
if (!validCommands.includes(command)) {
|
||||
return { valid: false, error: 'Invalid command name' };
|
||||
}
|
||||
|
||||
if (command.length > 100) {
|
||||
return { valid: false, error: 'Command name too long' };
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
}
|
||||
|
||||
// Get client information from request
|
||||
function getClientInfo(req) {
|
||||
const userAgent = req.headers['user-agent'] || '';
|
||||
const ip = req.headers['x-forwarded-for']?.split(',')[0] ||
|
||||
req.headers['x-real-ip'] ||
|
||||
'unknown';
|
||||
|
||||
return { userAgent, ip };
|
||||
}
|
||||
|
||||
// Main handler
|
||||
export default async function handler(req, res) {
|
||||
// CORS headers
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, User-Agent');
|
||||
|
||||
// Handle preflight requests
|
||||
if (req.method === 'OPTIONS') {
|
||||
return res.status(200).json({ ok: true });
|
||||
}
|
||||
|
||||
// Only accept POST requests
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({
|
||||
error: 'Method not allowed',
|
||||
allowed: ['POST']
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
// Extract and validate request body
|
||||
const {
|
||||
command,
|
||||
cliVersion,
|
||||
nodeVersion,
|
||||
platform,
|
||||
arch,
|
||||
sessionId,
|
||||
metadata
|
||||
} = req.body;
|
||||
|
||||
const validation = validateCommandData({ command, cliVersion, nodeVersion, platform });
|
||||
|
||||
if (!validation.valid) {
|
||||
return res.status(400).json({ error: validation.error });
|
||||
}
|
||||
|
||||
// Get client information
|
||||
const clientInfo = getClientInfo(req);
|
||||
|
||||
// Initialize Neon client
|
||||
const sql = getNeonClient();
|
||||
|
||||
// Insert command log
|
||||
await sql`
|
||||
INSERT INTO command_usage_logs (
|
||||
command_name,
|
||||
cli_version,
|
||||
node_version,
|
||||
platform,
|
||||
arch,
|
||||
session_id,
|
||||
metadata
|
||||
) VALUES (
|
||||
${command},
|
||||
${cliVersion || 'unknown'},
|
||||
${nodeVersion || 'unknown'},
|
||||
${platform || 'unknown'},
|
||||
${arch || 'unknown'},
|
||||
${sessionId || null},
|
||||
${metadata ? JSON.stringify(metadata) : null}
|
||||
)
|
||||
`;
|
||||
|
||||
// Return success response
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Command execution tracked successfully',
|
||||
data: {
|
||||
command,
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Command tracking error:', error);
|
||||
|
||||
// Return error response
|
||||
res.status(500).json({
|
||||
error: 'Internal server error',
|
||||
message: 'Failed to track command execution',
|
||||
details: process.env.NODE_ENV === 'development' ? error.message : undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user