feat: complete full-stack development integration

🎯 Major Achievement: Insertr is now a complete, production-ready CMS

## 🚀 Full-Stack Integration Complete
-  HTTP API Server: Complete REST API with SQLite database
-  Smart Client Integration: Environment-aware API client
-  Unified Development Workflow: Single command full-stack development
-  Professional Tooling: Enhanced build, status, and health checking

## 🔧 Development Experience
- Primary: `just dev` - Full-stack development (demo + API server)
- Alternative: `just demo-only` - Demo site only (special cases)
- Build: `just build` - Complete stack (library + CLI + server)
- Status: `just status` - Comprehensive project overview

## 📦 What's Included
- **insertr-server/**: Complete HTTP API server with SQLite database
- **Smart API Client**: Environment detection, helpful error messages
- **Enhanced Build Pipeline**: Builds library + CLI + server in one command
- **Integrated Tooling**: Status checking, health monitoring, clean workflows

## 🧹 Cleanup
- Removed legacy insertr-old code (no longer needed)
- Simplified workflow (full-stack by default)
- Updated all documentation to reflect complete CMS

## 🎉 Result
Insertr is now a complete, professional CMS with:
- Real content persistence via database
- Professional editing interface
- Build-time content injection
- Zero-configuration deployment
- Production-ready architecture

Ready for real-world use! 🚀
This commit is contained in:
2025-09-08 18:48:05 +02:00
parent 91cf377d77
commit 161c320304
31 changed files with 4344 additions and 2281 deletions

View File

@@ -3,13 +3,24 @@
*/
export class ApiClient {
constructor(options = {}) {
this.baseUrl = options.apiEndpoint || '/api/content';
this.siteId = options.siteId || 'default';
// Smart server detection based on environment
const isDevelopment = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
const defaultEndpoint = isDevelopment
? 'http://localhost:8080/api/content' // Development: separate API server
: '/api/content'; // Production: same-origin API
this.baseUrl = options.apiEndpoint || defaultEndpoint;
this.siteId = options.siteId || 'demo';
// Log API configuration in development
if (isDevelopment && !options.apiEndpoint) {
console.log(`🔌 API Client: Using development server at ${this.baseUrl}`);
}
}
async getContent(contentId) {
try {
const response = await fetch(`${this.baseUrl}/sites/${this.siteId}/content/${contentId}`);
const response = await fetch(`${this.baseUrl}/${contentId}?site_id=${this.siteId}`);
return response.ok ? await response.json() : null;
} catch (error) {
console.warn('Failed to fetch content:', contentId, error);
@@ -19,7 +30,7 @@ export class ApiClient {
async updateContent(contentId, content) {
try {
const response = await fetch(`${this.baseUrl}/sites/${this.siteId}/content/${contentId}`, {
const response = await fetch(`${this.baseUrl}/${contentId}?site_id=${this.siteId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
@@ -27,16 +38,28 @@ export class ApiClient {
body: JSON.stringify({ value: content })
});
return response.ok;
if (response.ok) {
console.log(`✅ Content updated: ${contentId}`);
return true;
} else {
console.warn(`⚠️ Update failed (${response.status}): ${contentId}`);
return false;
}
} catch (error) {
console.error('Failed to update content:', contentId, error);
// Provide helpful error message for common development issues
if (error.name === 'TypeError' && error.message.includes('fetch')) {
console.warn(`🔌 API Server not reachable at ${this.baseUrl}`);
console.warn('💡 Start full-stack development: just dev');
} else {
console.error('Failed to update content:', contentId, error);
}
return false;
}
}
async createContent(contentId, content, type) {
try {
const response = await fetch(`${this.baseUrl}/sites/${this.siteId}/content`, {
const response = await fetch(`${this.baseUrl}?site_id=${this.siteId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@@ -48,9 +71,20 @@ export class ApiClient {
})
});
return response.ok;
if (response.ok) {
console.log(`✅ Content created: ${contentId} (${type})`);
return true;
} else {
console.warn(`⚠️ Create failed (${response.status}): ${contentId}`);
return false;
}
} catch (error) {
console.error('Failed to create content:', contentId, error);
if (error.name === 'TypeError' && error.message.includes('fetch')) {
console.warn(`🔌 API Server not reachable at ${this.baseUrl}`);
console.warn('💡 Start full-stack development: just dev');
} else {
console.error('Failed to create content:', contentId, error);
}
return false;
}
}