package main import ( "encoding/json" "log" "net/http" _ "velaboratory/velconnect/migrations" "github.com/labstack/echo/v5" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/plugins/migratecmd" ) func main() { app := pocketbase.New() // loosely check if it was executed using "go run" // isGoRun := strings.HasPrefix(os.Args[0], os.TempDir()) migratecmd.MustRegister(app, app.RootCmd, &migratecmd.Options{ // enable auto creation of migration files when making collection changes // (the isGoRun check is to enable it only during development) Automigrate: true, }) app.OnBeforeServe().Add(func(e *core.ServeEvent) error { // or you can also use the shorter e.Router.GET("/articles/:slug", handler, middlewares...) e.Router.POST("/data_block/:block_id", func(c echo.Context) error { dao := app.Dao() requestData := apis.RequestData(c) log.Println(requestData) // get the old value to do a merge record, err := dao.FindFirstRecordByData("DataBlock", "block_id", c.PathParam("block_id")) if err == nil { mergeDataBlock(requestData, record) } else { collection, err := dao.FindCollectionByNameOrId("DataBlock") if err != nil { return err } record = models.NewRecord(collection) // we don't have an existing data, so just set the new values if val, ok := requestData.Data["data"]; ok { record.Set("data", val) } } // add the new values record.Set("block_id", c.PathParam("block_id")) fields := []string{ "owner_id", "visibility", "category", } for _, v := range fields { if val, ok := requestData.Data[v]; ok { record.Set(v, val) } } // double-check that data is not null if (record.Get("data") == nil) || (record.Get("data") == "") { record.Set("data", "{}") } // apply to the db if err := dao.SaveRecord(record); err != nil { return err } log.Println(record) return c.JSON(http.StatusOK, record) }, apis.ActivityLogger(app), ) e.Router.GET("/data_block/:block_id", func(c echo.Context) error { record, err := app.Dao().FindFirstRecordByData("DataBlock", "block_id", c.PathParam("block_id")) if err != nil { return apis.NewNotFoundError("The data block does not exist.", err) } // enable ?expand query param support apis.EnrichRecord(c, app.Dao(), record) return c.JSON(http.StatusOK, record) }, apis.ActivityLogger(app), ) e.Router.POST("/device/:device_id", func(c echo.Context) error { dao := app.Dao() requestData := apis.RequestData(c) // get the old value to do a merge record, err := dao.FindFirstRecordByData("Device", "device_id", c.PathParam("device_id")) if err == nil { mergeDataBlock(requestData, record) } else { collection, err := dao.FindCollectionByNameOrId("Device") if err != nil { return err } record = models.NewRecord(collection) // we don't have an existing data, so just set the new values if val, ok := requestData.Data["data"]; ok { record.Set("data", val) } } // add the new values record.Set("device_id", c.PathParam("device_id")) fields := []string{ "os_info", "friendly_name", "modified_by", "current_app", "current_room", "pairing_code", "last_online", } for _, v := range fields { if val, ok := requestData.Data[v]; ok { record.Set(v, val) } } // double-check that data is not null if (record.Get("data") == nil) || (record.Get("data") == "") { record.Set("data", "{}") } // apply to the db if err := dao.SaveRecord(record); err != nil { return err } return c.JSON(http.StatusOK, record) }, apis.ActivityLogger(app), ) e.Router.GET("/device/:device_id", func(c echo.Context) error { record, err := app.Dao().FindFirstRecordByData("Device", "device_id", c.PathParam("device_id")) if err != nil { return apis.NewNotFoundError("The device does not exist.", err) } // enable ?expand query param support apis.EnrichRecord(c, app.Dao(), record) return c.JSON(http.StatusOK, record) }, apis.ActivityLogger(app), ) // gets all relevant tables for this device id e.Router.GET("/state/device/:device_id", func(c echo.Context) error { record, err := app.Dao().FindFirstRecordByData("Device", "device_id", c.PathParam("device_id")) if err != nil { return apis.NewNotFoundError("The device does not exist.", err) } room, _ := app.Dao().FindFirstRecordByData("DataBlock", "block_id", record.GetString("current_room")) output := map[string]interface{}{ "device": record, "room": room, } return c.JSON(http.StatusOK, output) }, apis.ActivityLogger(app), ) return nil }) if err := app.Start(); err != nil { log.Fatal(err) } } func mergeDataBlock(requestData *models.RequestData, record *models.Record) { // get the new data newData, hasNewData := requestData.Data["data"] if hasNewData { // convert the existing data to a map var newDataMap = map[string]interface{}{} for k, v := range newData.(map[string]interface{}) { newDataMap[k] = v } // get the existing data existingDataString := record.GetString("data") existingDataMap := map[string]interface{}{} json.Unmarshal([]byte(existingDataString), &existingDataMap) // merge the new keys // this is only single-level for k, v := range newDataMap { existingDataMap[k] = v } record.Set("data", existingDataMap) } }