UNPKG

collectlie

Version:

TypeScript SDK for Collectlie - flexible data collection platform with custom types, schema validation, and Supabase backend integration

697 lines (576 loc) 17.5 kB
# Getting Started with Collectlie Ultra-minimal TypeScript SDK for flexible user submission platform. Only one method to learn: `submit()`. ## Installation ```bash npm install collectlie ``` ## Environment Setup ### 1. Create .env file ```bash # Copy from .env.example cp .env.example .env ``` ### 2. Add your credentials ```env # Your project credentials from the dashboard COLLECTLIE_PROJECT_ID=your_project_id_here COLLECTLIE_API_KEY=proj_your_api_key_here # Optional settings NODE_ENV=development ``` ### 3. Environment Detection The SDK automatically detects environment variables based on your platform: - **Node.js**: `COLLECTLIE_PROJECT_ID`, `COLLECTLIE_API_KEY` - **Vite**: `VITE_COLLECTLIE_PROJECT_ID`, `VITE_COLLECTLIE_API_KEY` - **React**: `REACT_APP_COLLECTLIE_PROJECT_ID`, `REACT_APP_COLLECTLIE_API_KEY` - **Next.js**: `NEXT_PUBLIC_COLLECTLIE_PROJECT_ID`, `NEXT_PUBLIC_COLLECTLIE_API_KEY` ### 4. Manual Configuration (Alternative) If environment variables aren't available, you can pass credentials manually: ```javascript const collectlie = new Collectlie({ projectId: 'your_project_id', apiKey: 'proj_your_api_key' }); ``` ## Quick Start Examples ### Option 1: Full SDK Import ```javascript import { Collectlie } from 'collectlie'; // SDK automatically picks up environment variables const collectlie = new Collectlie(); // Basic submission await collectlie.submit({ type: 'issue', title: 'Bug Report', content: 'Found a bug in the checkout process', author: { email: 'user@example.com', name: 'John Doe' } }); // With automatic data gathering (recommended) await collectlie.submit({ type: 'issue', title: 'Performance Issue', content: 'Page loads slowly on mobile', author: { email: 'user@example.com' } }, true); // Automatically gather browser, device, source, performance, error data // With selective data gathering await collectlie.submit({ type: 'issue', title: 'UI Layout Problem', content: 'Button overlaps text on small screens' }, { browser: { viewport: true, screen: true }, // Just dimensions device: { deviceType: true }, // Just mobile/desktop source: { url: true, title: true } // Just URL and page title }); // Submit with tags await collectlie.submit({ type: 'feature', title: 'Add dark mode', content: 'Users are requesting a dark theme option', tags: ['feature', 'ui', 'theme'] // Multiple tags }); // Submit with single tag await collectlie.submit({ type: 'issue', title: 'Login problem', content: 'Cannot authenticate with Google', tags: 'authentication' // Single tag }); ``` ### Option 2: Standalone Submit Function ```javascript import { submit } from 'collectlie'; // Basic submission (uses environment variables) await submit({ type: 'issue', title: 'Bug Report', content: 'Found a bug in the checkout process', author: { email: 'user@example.com', name: 'John Doe' } }); // With automatic data gathering await submit({ type: 'feature', title: 'Add dark mode', content: 'Users are requesting a dark theme option', tags: ['feature', 'ui', 'theme'] }, { browser: true, // All browser info device: true, // All device info performance: true // All performance data }); // With explicit configuration (legacy) await submit({ type: 'feedback', title: 'Great app!', content: 'Love the new features' }, { projectId: 'your-project-id', apiKey: 'proj-your-api-key' }); ``` ### File Upload Examples ```javascript // Submit with file attachments const fileInput = document.querySelector('#screenshot'); const file = fileInput.files[0]; if (file) { await collectlie.submit({ type: 'bug', title: 'UI Issue with Screenshot', content: 'Button is not aligned properly on mobile', author: { email: 'user@example.com' }, attachments: [{ filename: file.name, data: file }] }); } ``` ### React Integration ```jsx import React, { useState } from 'react'; import { Collectlie } from 'collectlie'; // Initialize SDK (uses environment variables) const collectlie = new Collectlie(); function SubmissionForm() { const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(null); const handleSubmit = async (e) => { e.preventDefault(); setIsSubmitting(true); setError(null); try { const result = await collectlie.submit({ type: 'feedback', title: 'User Feedback', content: 'This is great!', // Custom fields source: 'react_form', component: 'SubmissionForm' }, { // Automatically gather technical context (recommended) browser: true, // Browser info and capabilities device: true, // Device type and screen info source: true, // Current page URL and title performance: true // Page load time and performance data }); console.log('Submitted:', result); } catch (err) { setError(err.message); } finally { setIsSubmitting(false); } }; return ( <form onSubmit={handleSubmit}> {error && <div className="error">{error}</div>} <button type="submit" disabled={isSubmitting}> {isSubmitting ? 'Submitting...' : 'Submit'} </button> </form> ); } ``` ### Node.js ```javascript const { Collectlie } = require('collectlie'); const collectlie = new Collectlie(); // Submit server-side data await collectlie.submit({ type: 'server_log', title: 'Error Report', content: 'Server error occurred during processing', metadata: { error_code: 500, timestamp: new Date().toISOString(), server_id: 'web-01' } }); ``` ## Basic Usage Patterns ### Simple Submission ```typescript await collectlie.submit({ type: 'issue', title: 'Bug Report', content: 'Description of the issue', author: { email: 'user@example.com' } }); ``` ### Submission with Custom Fields ```typescript await collectlie.submit({ type: 'feedback', title: 'User Feedback', content: 'This is great!', author: { email: 'user@example.com', name: 'Jane Smith' }, metadata: { priority: 'high', category: 'ui', browser: 'Chrome', version: '1.2.3' } }); ``` ### File Upload Examples #### Simple File Upload ```typescript // Single file upload const fileInput = document.querySelector('#file-input') as HTMLInputElement; const selectedFile = fileInput.files?.[0]; if (selectedFile) { await collectlie.submit({ type: 'bug', title: 'Error Screenshot', content: 'Application crashes when clicking save button', author: { email: 'tester@company.com' }, attachments: [{ filename: selectedFile.name, data: selectedFile }] }); } ``` #### Multiple File Upload ```typescript // Multiple files from input const fileInput = document.querySelector('#files') as HTMLInputElement; const files = Array.from(fileInput.files || []); await collectlie.submit({ type: 'feature', title: 'Feature Request with Mockups', content: 'Please implement dark mode as shown in attached designs', author: { email: 'designer@company.com', name: 'Sarah Designer' }, attachments: files.map(file => ({ filename: file.name, mimeType: file.type, data: file })) }); ``` #### File Upload with Configuration ```typescript // Note: Backend enforces all file limits (1MB, images only) // No client-side validation - maximum freedom for users const sdk = new Collectlie({ // All file validation handled by backend // Users can attach any files they want }); // Upload any files - backend validates try { await collectlie.submit({ type: 'feedback', title: 'Feedback with Documents', content: 'Please review the attached specifications', attachments: [{ filename: 'requirements.pdf', data: pdfFile }] }); console.log('Upload successful!'); } catch (error) { if (error.message.includes('file size')) { console.error('File too large'); } else if (error.message.includes('file type')) { console.error('File type not supported'); } } ``` ``` ### Submission with Metadata ```typescript await collectlie.submit({ type: 'rating', title: 'App Rating', metadata: { rating: 5, category: 'overall' } }, { metadata: { source: 'mobile_app', user_id: 'user_123', session_id: 'session_abc' } }); ``` ## Data Types Overview ### SubmissionData ```typescript interface SubmissionData { type: string; // Required: submission type title?: string; // Optional: submission title content?: string; // Optional: main content author?: AuthorInfo; // Optional: author information metadata?: Record<string, any>; // Optional: any metadata attachments?: AttachmentInfo[]; // Optional: file attachments } interface AttachmentInfo { filename: string; // Original filename mimeType?: string; // MIME type (auto-detected) size?: number; // File size in bytes data?: File | Blob; // File data for upload url?: string; // URL of existing file } interface AuthorInfo { email?: string; // Author's email address name?: string; // Author's display name avatar?: string; // URL to author's avatar userId?: string; // Internal user ID username?: string; // Author's username } ``` ### SubmissionConfig ```typescript interface SubmissionConfig { projectId?: string; // Project ID (auto-detected from env) apiKey?: string; // API key (auto-detected from env) // File Upload Configuration (backend enforced) maxFileSize?: number; // Informational: backend enforces 1MB allowedFileTypes?: string[]; // Informational: backend enforces images only } ``` ## Error Handling ```typescript try { await collectlie.submit(data); } catch (error) { if (error.message.includes('Validation failed')) { // Handle validation errors console.error('Data validation failed:', error.message); } else if (error.message.includes('401') || error.message.includes('403')) { // Handle authentication errors console.error('Authentication failed - check your API key'); } else if (error.message.includes('timeout')) { // Handle timeouts console.error('Request timed out - please try again'); } else { // Handle other errors console.error('Submission failed:', error.message); } } ``` ## Development Workflow ### 1. Environment Setup ```bash # Copy environment template cp .env.example .env # Edit with your credentials # COLLECTLIE_PROJECT_ID=your_project_id # COLLECTLIE_API_KEY=proj_your_api_key ``` ### 2. Development ```bash # Build the SDK npm run build # Run in development mode npm run dev ``` ### 3. Verify Your Integration ```javascript // verify-integration.js import { Collectlie } from 'collectlie'; const collectlie = new Collectlie(); // Verify your integration is working await collectlie.submit({ type: 'feedback', title: 'Integration Verification', content: 'Testing that the SDK is properly integrated' }); ``` ## File Upload Technical Details ### Upload Process - **Automatic Upload**: Files are uploaded automatically when `data` field is present - **Multipart Form Data**: Uses `multipart/form-data` for efficient binary transfer - **Atomic Operations**: All files must upload successfully or submission fails - **MIME Detection**: Automatically detects file types if not provided - **Size Validation**: Files validated against limits before upload ### File Upload Technical Details #### Default Settings - **Max File Size**: 1MB per file (backend enforced) - **Allowed Types**: Images only (JPEG, PNG, GIF, WebP) - backend enforced - **Supported Formats**: `File`, `Blob` objects, or URLs to existing files - **Validation**: All validation handled by backend for maximum user freedom - **No Client Limits**: Users can attach any files, backend validates #### Backend Security Features - **MIME Type Validation**: Backend validates image types only - **Size Limits**: Backend enforces 1MB per file limit - **Content Validation**: Server-side binary content verification - **No Client Restrictions**: Maximum user freedom, backend handles security #### File Upload Patterns **Simple File Upload:** ```typescript // Basic file attachment const fileInput = document.querySelector('#file') as HTMLInputElement; const file = fileInput.files?.[0]; if (file) { await collectlie.submit({ type: 'bug', title: 'Issue with screenshot', content: 'Attaching screenshot of the problem', attachments: [{ filename: file.name, data: file // SDK handles upload automatically }] }); } ``` **Multiple File Upload (No Client Validation):** ```typescript // Upload any files - backend handles all validation const files = Array.from(fileInput.files || []); const attachments = files.map(file => ({ filename: file.name, mimeType: file.type, data: file })); try { await collectlie.submit({ type: 'feedback', title: 'Feedback with attachments', content: 'Please see attached files', attachments }); console.log('Files uploaded successfully!'); } catch (error) { // Backend will provide specific error messages console.error('Upload failed:', error.message); } ``` **File Upload with Progress Handling:** ```typescript // Handle upload progress and errors gracefully async function uploadWithProgress(files: File[]) { const attachments = files.map(file => ({ filename: file.name, mimeType: file.type, data: file })); try { console.log('Starting upload...', attachments.length, 'files'); const result = await collectlie.submit({ type: 'bug', title: 'Bug report with files', content: 'Detailed bug report with supporting files', attachments }); console.log('✅ Upload completed successfully!'); return result; } catch (error) { if (error.message.includes('file size')) { console.error('❌ File too large'); } else if (error.message.includes('file type')) { console.error('❌ Unsupported file type'); } else if (error.message.includes('network')) { console.error('❌ Network error during upload'); } else { console.error('❌ Upload failed:', error.message); } throw error; } } ``` ### Example File Types ```typescript // Default allowed file types const defaultAllowedTypes = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp' ]; ``` ## File Upload Error Handling ```typescript // Comprehensive error handling for file uploads try { await collectlie.submit({ type: 'feedback', title: 'Feedback with files', content: 'Attaching relevant files', attachments: [{ filename: 'screenshot.png', data: selectedFile }] }); console.log('✅ Files uploaded successfully!'); } catch (error) { // Handle specific file upload errors if (error.message.includes('File size exceeds')) { alert('One or more files are too large. Maximum size: 1MB per file.'); } else if (error.message.includes('File type not allowed')) { alert('Unsupported file type. Backend only accepts images.'); } else if (error.message.includes('Too many attachments')) { alert('File upload failed. Please try again.'); } else if (error.message.includes('Upload timeout')) { alert('Upload timed out. Please check your connection and try again.'); } else if (error.message.includes('Virus detected')) { alert('File failed security scan. Please check your files.'); } else { alert('Upload failed: ' + error.message); } } ``` ## Verify Your Setup After setting up your environment variables, you can verify everything is working by making a test submission: ```javascript // verify-setup.js import { Collectlie } from 'collectlie'; const collectlie = new Collectlie(); try { const result = await collectlie.submit({ type: 'test', title: 'Setup Verification', content: 'Testing that my API credentials are working' }); console.log('✅ Setup verified successfully!', result); } catch (error) { console.error('❌ Setup verification failed:', error.message); } ``` You should see the submission appear in your Collectlie dashboard. ## Next Steps - **[Complete API Reference](./api-reference.md)** - Detailed API documentation - **[Framework Examples](./examples/)** - Specific integration guides - **[Best Practices](./advanced/best-practices.md)** - Production recommendations ## Common Issues ### Missing Environment Variables ``` Error: project_id is required. Set COLLECTLIE_PROJECT_ID environment variable ``` **Solution**: Add `COLLECTLIE_PROJECT_ID=your_project_id` to your `.env` file ### Invalid API Key ``` Error: API key is required ``` **Solution**: Add your API key to your `.env` file ### Network Timeout ``` Error: Request timeout after 10000ms ``` **Solution**: Check your internet connection or increase timeout in SDK config ## Support - Check your `.env` file setup - Verify API key starts with `proj_` - Ensure project ID is correct - [GitHub Issues](https://github.com/collectlie/collectlie/issues) for bugs and questions