Hallucinate everything
This commit is contained in:
175
api.go
Normal file
175
api.go
Normal file
@@ -0,0 +1,175 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
// setupAPIRoutes sets up the event store API routes
|
||||
func setupAPIRoutes(app core.App, eventStore *SimpleEventStore) {
|
||||
app.OnServe().BindFunc(func(se *core.ServeEvent) error {
|
||||
// JSON Patch endpoint using PATCH method
|
||||
se.Router.PATCH("/api/collections/{collection}/items/{itemId}", func(e *core.RequestEvent) error {
|
||||
collection := e.Request.PathValue("collection")
|
||||
itemID := e.Request.PathValue("itemId")
|
||||
|
||||
if collection == "" || itemID == "" {
|
||||
return e.BadRequestError("Collection and itemId are required", nil)
|
||||
}
|
||||
|
||||
var patches []PatchOperation
|
||||
if err := e.BindBody(&patches); err != nil {
|
||||
return e.BadRequestError("Failed to parse JSON Patch data", err)
|
||||
}
|
||||
|
||||
// Create event with patches
|
||||
incomingEvent := &Event{
|
||||
ItemID: itemID,
|
||||
Collection: collection,
|
||||
Patches: patches,
|
||||
}
|
||||
|
||||
// Process the event
|
||||
processedEvent, err := eventStore.ProcessEvent(incomingEvent)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to process event", err)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, processedEvent)
|
||||
})
|
||||
|
||||
// Legacy POST endpoint for compatibility
|
||||
se.Router.POST("/api/events", func(e *core.RequestEvent) error {
|
||||
var incomingEvent Event
|
||||
if err := e.BindBody(&incomingEvent); err != nil {
|
||||
return e.BadRequestError("Failed to parse event data", err)
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if incomingEvent.ItemID == "" || incomingEvent.Collection == "" || len(incomingEvent.Patches) == 0 {
|
||||
return e.BadRequestError("Missing required fields: item_id, collection, patches", nil)
|
||||
}
|
||||
|
||||
// Process the event
|
||||
processedEvent, err := eventStore.ProcessEvent(&incomingEvent)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to process event", err)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusCreated, processedEvent)
|
||||
})
|
||||
|
||||
// Sync endpoint for clients
|
||||
se.Router.POST("/api/sync", func(e *core.RequestEvent) error {
|
||||
var syncReq SyncRequest
|
||||
if err := e.BindBody(&syncReq); err != nil {
|
||||
return e.BadRequestError("Failed to parse sync request", err)
|
||||
}
|
||||
|
||||
// Check if client is in sync
|
||||
isValid, err := eventStore.ValidateSync(syncReq.LastSeq, syncReq.LastHash)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to validate sync", err)
|
||||
}
|
||||
|
||||
var response SyncResponse
|
||||
|
||||
if !isValid {
|
||||
// Full sync needed - send all events
|
||||
events, err := eventStore.GetEventsSince(0)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to get events", err)
|
||||
}
|
||||
response.Events = events
|
||||
response.FullSync = true
|
||||
} else {
|
||||
// Incremental sync - send events since last sequence
|
||||
events, err := eventStore.GetEventsSince(syncReq.LastSeq)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to get events", err)
|
||||
}
|
||||
response.Events = events
|
||||
response.FullSync = false
|
||||
}
|
||||
|
||||
// Get current state
|
||||
latestEvent, err := eventStore.GetLatestEvent()
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to get latest event", err)
|
||||
}
|
||||
|
||||
if latestEvent != nil {
|
||||
response.CurrentSeq = latestEvent.Seq
|
||||
response.CurrentHash = latestEvent.Hash
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, response)
|
||||
})
|
||||
|
||||
// Get all items endpoint
|
||||
se.Router.GET("/api/items/{collection}", func(e *core.RequestEvent) error {
|
||||
collection := e.Request.PathValue("collection")
|
||||
if collection == "" {
|
||||
return e.BadRequestError("Collection name required", nil)
|
||||
}
|
||||
|
||||
items, err := eventStore.GetAllItems(collection)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to get items", err)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]interface{}{
|
||||
"items": items,
|
||||
})
|
||||
})
|
||||
|
||||
// Batch events endpoint for client to send multiple events
|
||||
se.Router.POST("/api/events/batch", func(e *core.RequestEvent) error {
|
||||
var events []Event
|
||||
if err := e.BindBody(&events); err != nil {
|
||||
return e.BadRequestError("Failed to parse events data", err)
|
||||
}
|
||||
|
||||
processedEvents := make([]Event, 0, len(events))
|
||||
for _, incomingEvent := range events {
|
||||
// Validate required fields
|
||||
if incomingEvent.ItemID == "" || incomingEvent.Collection == "" || len(incomingEvent.Patches) == 0 {
|
||||
return e.BadRequestError("Missing required fields in event: item_id, collection, patches", nil)
|
||||
}
|
||||
|
||||
processedEvent, err := eventStore.ProcessEvent(&incomingEvent)
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to process event", err)
|
||||
}
|
||||
processedEvents = append(processedEvents, *processedEvent)
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusCreated, map[string]interface{}{
|
||||
"events": processedEvents,
|
||||
})
|
||||
})
|
||||
|
||||
// Get current state endpoint
|
||||
se.Router.GET("/api/state", func(e *core.RequestEvent) error {
|
||||
latestEvent, err := eventStore.GetLatestEvent()
|
||||
if err != nil {
|
||||
return e.InternalServerError("Failed to get latest event", err)
|
||||
}
|
||||
|
||||
response := map[string]interface{}{
|
||||
"seq": 0,
|
||||
"hash": "",
|
||||
}
|
||||
|
||||
if latestEvent != nil {
|
||||
response["seq"] = latestEvent.Seq
|
||||
response["hash"] = latestEvent.Hash
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, response)
|
||||
})
|
||||
|
||||
return se.Next()
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user