feat: implement unified editor with content persistence and server-side upsert

- Replace dual update systems with single markdown-first editor architecture
- Add server-side upsert to eliminate 404 errors on PUT operations
- Fix content persistence race condition between preview and save operations
- Remove legacy updateElementContent system entirely
- Add comprehensive authentication with JWT scaffolding and dev mode
- Implement EditContext.updateOriginalContent() for proper baseline management
- Enable markdown formatting in all text elements (h1-h6, p, div, etc)
- Clean terminology: remove 'unified' references from codebase

Technical changes:
* core/editor.js: Remove legacy update system, unify content types as markdown
* ui/Editor.js: Add updateOriginalContent() method to fix save persistence
* ui/Previewer.js: Clean live preview system for all content types
* api/handlers.go: Implement UpsertContent for idempotent PUT operations
* auth/*: Complete authentication service with OAuth scaffolding
* db/queries/content.sql: Add upsert query with ON CONFLICT handling
* Schema: Remove type constraints, rely on server-side validation

Result: Clean content editing with persistent saves, no 404 errors, markdown support in all text elements
This commit is contained in:
2025-09-10 20:19:54 +02:00
parent c572428e45
commit b0c4a33a7c
23 changed files with 1658 additions and 3585 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/spf13/viper"
"github.com/insertr/insertr/internal/api"
"github.com/insertr/insertr/internal/auth"
"github.com/insertr/insertr/internal/db"
)
@@ -51,8 +52,24 @@ func runServe(cmd *cobra.Command, args []string) {
}
defer database.Close()
// Initialize authentication service
authConfig := &auth.AuthConfig{
DevMode: viper.GetBool("dev_mode"),
JWTSecret: viper.GetString("jwt_secret"),
}
// Set default JWT secret if not configured
if authConfig.JWTSecret == "" {
authConfig.JWTSecret = "dev-secret-change-in-production"
if authConfig.DevMode {
log.Printf("🔑 Using default JWT secret for development")
}
}
authService := auth.NewAuthService(authConfig)
// Initialize handlers
contentHandler := api.NewContentHandler(database)
contentHandler := api.NewContentHandler(database, authService)
// Setup router
router := mux.NewRouter()