/** * Minimal Showpad Integration Test * Tests Showpad API connection and asset fetching * * REQUIREMENTS: * - SHOWPAD_CLIENT_ID and SHOWPAD_CLIENT_SECRET must be set * - Create OAuth client at: https://tdcerhverv.showpad.biz Admin > API > OAuth Clients */ import { config } from 'dotenv'; import { resolve } from 'path'; // Load environment const __dirname = new URL('.', import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1'); config({ path: resolve(__dirname, '../.env') }); console.log('Testing Showpad Integration...\n'); console.log('Config:'); console.log(' Subdomain:', process.env.SHOWPAD_SUBDOMAIN || '(missing)'); console.log(' Username:', process.env.SHOWPAD_USERNAME || '(missing)'); console.log(' Password:', process.env.SHOWPAD_PASSWORD ? '***' : '(missing)'); console.log(' Client ID:', process.env.SHOWPAD_CLIENT_ID || 'āŒ MISSING - CREATE AT SHOWPAD ADMIN'); console.log(' Client Secret:', process.env.SHOWPAD_CLIENT_SECRET ? '***' : 'āŒ MISSING - CREATE AT SHOWPAD ADMIN'); console.log(''); interface ShowpadAuthResponse { access_token: string; token_type: string; expires_in: number; } async function testShowpadAuth(): Promise { const baseUrl = process.env.SHOWPAD_BASE_URL || 'https://tdcerhverv.showpad.biz'; const username = process.env.SHOWPAD_USERNAME; const password = process.env.SHOWPAD_PASSWORD; const clientId = process.env.SHOWPAD_CLIENT_ID; const clientSecret = process.env.SHOWPAD_CLIENT_SECRET; if (!username || !password) { console.error('āŒ Missing SHOWPAD_USERNAME or SHOWPAD_PASSWORD'); return null; } if (!clientId || !clientSecret) { console.error('āŒ Missing SHOWPAD_CLIENT_ID or SHOWPAD_CLIENT_SECRET'); console.error(''); console.error('šŸ“‹ To get OAuth credentials:'); console.error(' 1. Go to https://tdcerhverv.showpad.biz'); console.error(' 2. Navigate to Admin > Settings > API'); console.error(' 3. Click "Manage OAuth Clients"'); console.error(' 4. Create a new OAuth client'); console.error(' 5. Copy the Client ID and Secret to your .env file'); return null; } console.log('Attempting Showpad authentication...'); const tokenUrl = `${baseUrl}/api/v3/oauth2/token`; const params = new URLSearchParams({ grant_type: 'password', username, password, client_id: clientId, client_secret: clientSecret }); try { const response = await fetch(tokenUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString() }); console.log(`Auth Response: ${response.status} ${response.statusText}`); if (!response.ok) { const error = await response.text(); console.error('āŒ Auth failed:', error); return null; } const data: ShowpadAuthResponse = await response.json(); console.log('āœ… Authentication successful!'); console.log(` Token type: ${data.token_type}`); console.log(` Expires in: ${data.expires_in}s`); return data.access_token; } catch (error) { console.error('āŒ Auth error:', error); return null; } } async function testFetchAssets(token: string): Promise { const subdomain = process.env.SHOWPAD_SUBDOMAIN || 'tdcerhverv'; const apiUrl = `https://${subdomain}.api.showpad.com/v4/assets?limit=10`; console.log('\nFetching assets...'); console.log(`API URL: ${apiUrl}`); try { const response = await fetch(apiUrl, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } }); console.log(`Assets Response: ${response.status} ${response.statusText}`); if (!response.ok) { const error = await response.text(); console.error('āŒ Fetch failed:', error); return; } const data = await response.json(); const items = data.items || []; console.log(`āœ… Fetched ${items.length} assets`); // Count images const imageTypes = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml']; const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg']; let imageCount = 0; for (const asset of items) { const isImage = (asset.mimeType && imageTypes.includes(asset.mimeType)) || (asset.name && imageExtensions.some((ext: string) => asset.name.toLowerCase().endsWith(ext))) || asset.resourcetype === 'image'; if (isImage) imageCount++; console.log(` - ${asset.name} (${asset.mimeType || asset.resourcetype || 'unknown'})`); } console.log(`\nšŸ“Š Summary: ${imageCount} images out of ${items.length} assets`); } catch (error) { console.error('āŒ Fetch error:', error); } } async function main() { const token = await testShowpadAuth(); if (token) { await testFetchAssets(token); } console.log('\nTest complete.'); } main().catch(console.error);