#!/usr/bin/env node const axios = require('axios'); const fs = require('fs'); // Load environment require('dotenv').config({ path: '.env.ordrestyring' }); const API_BASE = 'https://v2.api.ordrestyring.dk'; const TOKEN = process.env.ORDRESTYRING_TOKEN; if (!TOKEN) { console.error('āŒ ORDRESTYRING_TOKEN not found in environment'); process.exit(1); } // API endpoints to analyze const endpoints = [ '/cases', '/case-materials', '/hours', '/debtors', '/debtor-invoices', '/users', '/departments', '/case-types', '/case-statuses', '/employee-types' ]; async function makeRequest(endpoint, params = {}) { try { const config = { method: 'GET', url: `${API_BASE}${endpoint}`, auth: { username: TOKEN, password: 'x' }, params: { pagesize: 5, // Just get 5 samples to analyze format ...params } }; console.log(`🌐 Making request to: ${config.url}`); console.log(`šŸ”‘ Auth: ${TOKEN.substring(0, 8)}***`); const response = await axios(config); console.log(`šŸ“¦ Response status: ${response.status}`); console.log(`šŸ“Š Response data structure:`, { hasData: !!response.data, dataType: typeof response.data, dataKeys: response.data ? Object.keys(response.data) : [], totalProperty: response.data?.total, dataLength: response.data?.data?.length }); return response.data; } catch (error) { console.error(`āŒ Error fetching ${endpoint}:`, { status: error.response?.status, statusText: error.response?.statusText, message: error.message, responseData: error.response?.data }); return null; } } async function analyzeDataFormats() { console.log('šŸ” Analyzing Ordrestyring API Data Formats'); console.log('=========================================='); const analysis = { timestamp: new Date().toISOString(), endpoints: {} }; for (const endpoint of endpoints) { console.log(`\nšŸ“Š Analyzing ${endpoint}...`); const data = await makeRequest(endpoint); if (data && typeof data === 'object') { // Check if response is an array-like object with numeric keys const dataKeys = Object.keys(data); const isArrayLike = dataKeys.length > 0 && dataKeys.every(key => !isNaN(key)); let records = []; let totalCount = 0; if (isArrayLike) { // Convert object with numeric keys to array records = Object.values(data); totalCount = records.length; } else if (data.data && Array.isArray(data.data)) { // Standard API response format records = data.data; totalCount = data.total || records.length; } else if (Array.isArray(data)) { // Direct array response records = data; totalCount = records.length; } if (records.length > 0) { const sampleRecord = records[0]; const recordStructure = analyzeRecordStructure(sampleRecord); analysis.endpoints[endpoint] = { available: true, totalRecords: totalCount, sampleRecord: sampleRecord, structure: recordStructure, suggestedTableName: endpoint.replace('/', '').replace('-', '_'), sqlSchema: generateSQLSchema(endpoint.replace('/', '').replace('-', '_'), recordStructure) }; console.log(`āœ… ${endpoint}: ${totalCount} records available`); console.log(` Structure: ${Object.keys(recordStructure).length} fields`); console.log(` Key fields: ${Object.keys(recordStructure).slice(0, 5).join(', ')}`); console.log(` Sample ID: ${sampleRecord.id || 'N/A'}`); } else { analysis.endpoints[endpoint] = { available: false, error: 'No records in response' }; console.log(`āŒ ${endpoint}: No records found`); } } else { analysis.endpoints[endpoint] = { available: false, error: 'No data or empty response' }; console.log(`āŒ ${endpoint}: No data available`); } // Small delay to be respectful to API await new Promise(resolve => setTimeout(resolve, 200)); } // Save analysis fs.writeFileSync('api_data_formats_analysis.json', JSON.stringify(analysis, null, 2)); console.log('\nšŸ’¾ Analysis saved to api_data_formats_analysis.json'); // Generate combined SQL schema generateCombinedSchema(analysis); return analysis; } function analyzeRecordStructure(record) { const structure = {}; for (const [key, value] of Object.entries(record)) { let type = typeof value; let sqlType = 'TEXT'; let maxLength = null; if (value === null) { type = 'null'; sqlType = 'TEXT NULL'; } else if (type === 'string') { maxLength = value.length; if (maxLength <= 255) { sqlType = `VARCHAR(${Math.max(255, maxLength * 2)})`; } else { sqlType = 'TEXT'; } // Check if it's a date if (isDateString(value)) { type = 'date'; sqlType = 'DATETIME'; } } else if (type === 'number') { if (Number.isInteger(value)) { sqlType = 'INT'; } else { sqlType = 'DECIMAL(10,2)'; } } else if (type === 'boolean') { sqlType = 'BOOLEAN'; } else if (type === 'object') { sqlType = 'JSON'; } structure[key] = { type, sqlType, maxLength, sampleValue: value }; } return structure; } function isDateString(str) { if (typeof str !== 'string') return false; const date = new Date(str); return !isNaN(date.getTime()) && (str.includes('T') || str.includes('-')); } function generateSQLSchema(tableName, structure) { const fields = []; // Add primary key if (structure.id) { fields.push(`id ${structure.id.sqlType} PRIMARY KEY`); } else { fields.push(`id INT AUTO_INCREMENT PRIMARY KEY`); } // Add other fields for (const [fieldName, fieldInfo] of Object.entries(structure)) { if (fieldName !== 'id') { const nullable = fieldInfo.type === 'null' ? '' : ' NULL'; fields.push(`${fieldName} ${fieldInfo.sqlType}${nullable}`); } } return `CREATE TABLE IF NOT EXISTS ${tableName} ( ${fields.join(',\n ')} );`; } function generateCombinedSchema(analysis) { let combinedSchema = `-- Ordrestyring API Database Schema -- Generated: ${new Date().toISOString()} -- -- This schema supports all data types from Ordrestyring API USE ordrestyring_local; `; for (const [endpoint, data] of Object.entries(analysis.endpoints)) { if (data.available && data.sqlSchema) { combinedSchema += `-- Table for ${endpoint}\n`; combinedSchema += data.sqlSchema + '\n\n'; } } fs.writeFileSync('ordrestyring_complete_schema.sql', combinedSchema); console.log('šŸ“ Complete SQL schema saved to ordrestyring_complete_schema.sql'); } // Run analysis analyzeDataFormats().catch(console.error);