Compare commits
No commits in common. "48e55550c3d6761eb8a3145bae2522e4e4ab1974" and "a68d12aab5a0a2e1d1322aae7f3e98de8e4cf937" have entirely different histories.
48e55550c3
...
a68d12aab5
|
|
@ -91,34 +91,6 @@ namespace VELConnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PersistObject
|
|
||||||
{
|
|
||||||
public string id;
|
|
||||||
public readonly DateTime created;
|
|
||||||
public readonly DateTime updated;
|
|
||||||
public string app;
|
|
||||||
public string room;
|
|
||||||
public string network_id;
|
|
||||||
public bool spawned;
|
|
||||||
public string name;
|
|
||||||
public string data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RecordList<T>
|
|
||||||
{
|
|
||||||
public int page;
|
|
||||||
public int perPage;
|
|
||||||
public int totalPages;
|
|
||||||
public int totalItems;
|
|
||||||
public List<T> items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ComponentState
|
|
||||||
{
|
|
||||||
public int componentIdx;
|
|
||||||
public string state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UserCount
|
public class UserCount
|
||||||
{
|
{
|
||||||
[CanBeNull] public readonly string id;
|
[CanBeNull] public readonly string id;
|
||||||
|
|
@ -912,24 +884,19 @@ namespace VELConnect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PostRequestCallback(
|
public static void PostRequestCallback(string url, string postData, Dictionary<string, string> headers = null,
|
||||||
string url,
|
|
||||||
string postData,
|
|
||||||
Dictionary<string, string> headers = null,
|
|
||||||
Action<string> successCallback = null,
|
Action<string> successCallback = null,
|
||||||
Action<string> failureCallback = null,
|
Action<string> failureCallback = null)
|
||||||
string method = "POST"
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
instance.StartCoroutine(PostRequestCallbackCo(url, postData, headers, successCallback, failureCallback, method));
|
instance.StartCoroutine(PostRequestCallbackCo(url, postData, headers, successCallback, failureCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static IEnumerator PostRequestCallbackCo(string url, string postData,
|
private static IEnumerator PostRequestCallbackCo(string url, string postData,
|
||||||
Dictionary<string, string> headers = null, Action<string> successCallback = null,
|
Dictionary<string, string> headers = null, Action<string> successCallback = null,
|
||||||
Action<string> failureCallback = null, string method="POST")
|
Action<string> failureCallback = null)
|
||||||
{
|
{
|
||||||
UnityWebRequest webRequest = new UnityWebRequest(url, method);
|
UnityWebRequest webRequest = new UnityWebRequest(url, "POST");
|
||||||
byte[] bodyRaw = Encoding.UTF8.GetBytes(postData);
|
byte[] bodyRaw = Encoding.UTF8.GetBytes(postData);
|
||||||
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
|
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
webRequest.uploadHandler = uploadHandler;
|
webRequest.uploadHandler = uploadHandler;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using VELConnect;
|
||||||
using VelNet;
|
using VelNet;
|
||||||
|
|
||||||
namespace VELConnect
|
namespace VELConnect
|
||||||
|
|
@ -10,6 +14,14 @@ namespace VELConnect
|
||||||
{
|
{
|
||||||
public static VelConnectPersistenceManager instance;
|
public static VelConnectPersistenceManager instance;
|
||||||
|
|
||||||
|
public class SpawnedObjectData
|
||||||
|
{
|
||||||
|
public string prefabName;
|
||||||
|
public string base64ObjectData;
|
||||||
|
public string networkId;
|
||||||
|
public int componentIdx;
|
||||||
|
}
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
@ -27,50 +39,70 @@ namespace VELConnect
|
||||||
|
|
||||||
private void OnJoinedRoom(string roomName)
|
private void OnJoinedRoom(string roomName)
|
||||||
{
|
{
|
||||||
// if we're the first to join this room
|
if (VelNetManager.Players.Count == 0)
|
||||||
if (VelNetManager.Players.Count == 1)
|
|
||||||
{
|
{
|
||||||
VELConnectManager.GetRequestCallback(
|
string spawnedObjects = VELConnectManager.GetRoomData("spawned_objects", "[]");
|
||||||
VELConnectManager.VelConnectUrl +
|
List<string> spawnedObjectList = JsonConvert.DeserializeObject<List<string>>(spawnedObjects);
|
||||||
$"/api/collections/PersistObject/records?filter=(app='{Application.productName}')",
|
List<NetworkObject> spawnedNetworkObjects = new List<NetworkObject>();
|
||||||
s =>
|
GetSpawnedObjectData(spawnedObjectList, (list) =>
|
||||||
{
|
{
|
||||||
VELConnectManager.RecordList<VELConnectManager.PersistObject> obj =
|
foreach (SpawnedObjectData obj in list)
|
||||||
JsonConvert.DeserializeObject<VELConnectManager.RecordList<VELConnectManager.PersistObject>>(s);
|
|
||||||
obj.items = obj.items.Where(i => i.spawned && i.room == VelNetManager.Room).ToList();
|
|
||||||
|
|
||||||
foreach (VELConnectManager.PersistObject persistObject in obj.items)
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(persistObject.data))
|
NetworkObject spawnedObj = spawnedNetworkObjects.Find(i => i.networkId == obj.networkId);
|
||||||
|
if (spawnedObj == null)
|
||||||
{
|
{
|
||||||
Debug.LogError("Persisted object has no data");
|
spawnedObj = VelNetManager.NetworkInstantiate(obj.prefabName);
|
||||||
continue;
|
spawnedNetworkObjects.Add(spawnedObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkObject spawnedObj = VelNetManager.NetworkInstantiate(persistObject.name, Convert.FromBase64String(persistObject.data));
|
spawnedObj.syncedComponents[obj.componentIdx].ReceiveBytes(Convert.FromBase64String(obj.base64ObjectData));
|
||||||
VelNetPersist persist = spawnedObj.GetComponent<VelNetPersist>();
|
|
||||||
|
|
||||||
persist.persistId = persistObject.id;
|
|
||||||
persist.LoadData(persistObject);
|
|
||||||
}
|
}
|
||||||
}, s => { Debug.LogError("Failed to get persisted spawned objects", this); });
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't need to register objects, because they will do that automatically when they spawn if they have the VelNetPersist component
|
private class DataBlocksResponse
|
||||||
// We need to unregister objects when they are destroyed because destroying could happen because we left the scene
|
|
||||||
public static void UnregisterObject(NetworkObject obj)
|
|
||||||
{
|
{
|
||||||
|
public List<VELConnectManager.State.DataBlock> items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GetSpawnedObjectData(List<string> spawnedObjectList, Action<List<SpawnedObjectData>> callback)
|
||||||
|
{
|
||||||
|
VELConnectManager.GetRequestCallback($"/api/collections/DataBlock/records?filter=({string.Join(" || ", "id=\"" + spawnedObjectList + "\"")})", (response) =>
|
||||||
|
{
|
||||||
|
DataBlocksResponse parsedResponse = JsonConvert.DeserializeObject<DataBlocksResponse>(response);
|
||||||
|
callback(parsedResponse.items.Select(i => new SpawnedObjectData()
|
||||||
|
{
|
||||||
|
networkId = i.block_id.Split("_")[-1],
|
||||||
|
componentIdx = int.Parse(i.block_id.Split("_").Last()),
|
||||||
|
prefabName = i.TryGetData("name"),
|
||||||
|
base64ObjectData = i.TryGetData("state")
|
||||||
|
}).ToList());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RegisterObject(NetworkObject obj)
|
||||||
|
{
|
||||||
|
instance.StartCoroutine(instance.RegisterObjectCo(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator RegisterObjectCo(NetworkObject obj)
|
||||||
|
{
|
||||||
|
// upload all the persisted components, then add those components to the room data
|
||||||
VelNetPersist[] persistedComponents = obj.GetComponents<VelNetPersist>();
|
VelNetPersist[] persistedComponents = obj.GetComponents<VelNetPersist>();
|
||||||
if (persistedComponents.Length > 1)
|
List<VELConnectManager.State.DataBlock> responses = new List<VELConnectManager.State.DataBlock>();
|
||||||
{
|
double startTime = Time.timeAsDouble;
|
||||||
Debug.LogError("NetworkObject has more than one VelNetPersist component");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (VelNetPersist velNetPersist in persistedComponents)
|
foreach (VelNetPersist velNetPersist in persistedComponents)
|
||||||
{
|
{
|
||||||
velNetPersist.Delete();
|
velNetPersist.Save(s => { responses.Add(s); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (responses.Count < persistedComponents.Length && Time.timeAsDouble - startTime < 5)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
VELConnectManager.SetRoomData("spawned_objects", JsonConvert.SerializeObject(responses.Select(i => i.block_id).ToList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -8,20 +7,29 @@ using VelNet;
|
||||||
|
|
||||||
namespace VELConnect
|
namespace VELConnect
|
||||||
{
|
{
|
||||||
public class VelNetPersist : NetworkComponent
|
public class VelNetPersist : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
private class ComponentState
|
||||||
|
{
|
||||||
|
public int componentIdx;
|
||||||
|
public string state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncState[] syncStateComponents;
|
||||||
|
|
||||||
|
private string Id => $"{Application.productName}_{VelNetManager.Room}_{syncStateComponents.FirstOrDefault()?.networkObject.sceneNetworkId}";
|
||||||
|
|
||||||
private const float interval = 5f;
|
private const float interval = 5f;
|
||||||
private double nextUpdate;
|
private double nextUpdate;
|
||||||
private bool loading;
|
private bool loading;
|
||||||
private const bool debugLogs = false;
|
private const bool debugLogs = false;
|
||||||
public string persistId;
|
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (Time.timeAsDouble > nextUpdate && VelNetManager.InRoom && !loading)
|
if (Time.timeAsDouble > nextUpdate && VelNetManager.InRoom && !loading)
|
||||||
{
|
{
|
||||||
nextUpdate = Time.timeAsDouble + interval + UnityEngine.Random.Range(0, interval);
|
nextUpdate = Time.timeAsDouble + interval + UnityEngine.Random.Range(0, interval);
|
||||||
if (networkObject.IsMine)
|
if (syncStateComponents.FirstOrDefault()?.networkObject.IsMine == true)
|
||||||
{
|
{
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
@ -46,140 +54,78 @@ namespace VELConnect
|
||||||
private void Load()
|
private void Load()
|
||||||
{
|
{
|
||||||
loading = true;
|
loading = true;
|
||||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loading {name}");
|
if (debugLogs) Debug.Log($"[VelNetPersist] Loading {Id}");
|
||||||
|
VELConnectManager.GetDataBlock(Id, data =>
|
||||||
if (networkObject.isSceneObject)
|
|
||||||
{
|
{
|
||||||
// It looks like a PocketBase bug is preventing full filtering from happening:
|
if (!data.data.TryGetValue("components", out string d))
|
||||||
// $"/api/collections/PersistObject/records?filter=(app='{Application.productName}' && room='{VelNetManager.Room}' && network_id='{networkObject.sceneNetworkId}')",
|
|
||||||
VELConnectManager.GetRequestCallback(
|
|
||||||
VELConnectManager.VelConnectUrl +
|
|
||||||
$"/api/collections/PersistObject/records?filter=(app='{Application.productName}')",
|
|
||||||
s =>
|
|
||||||
{
|
{
|
||||||
VELConnectManager.RecordList<VELConnectManager.PersistObject> obj =
|
Debug.LogError($"[VelNetPersist] Failed to parse {Id}");
|
||||||
JsonConvert.DeserializeObject<VELConnectManager.RecordList<VELConnectManager.PersistObject>>(s);
|
|
||||||
obj.items = obj.items.Where(i => i.network_id == networkObject.sceneNetworkId.ToString() && i.room == VelNetManager.Room).ToList();
|
|
||||||
if (obj.items.Count < 1)
|
|
||||||
{
|
|
||||||
Debug.LogError("[VelNetPersist] No data found for " + name);
|
|
||||||
loading = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (obj.items.Count > 1)
|
|
||||||
|
|
||||||
|
List<ComponentState> componentData = JsonConvert.DeserializeObject<List<ComponentState>>(d);
|
||||||
|
|
||||||
|
if (componentData.Count != syncStateComponents.Length)
|
||||||
{
|
{
|
||||||
Debug.LogError(
|
Debug.LogError($"[VelNetPersist] Different number of components");
|
||||||
$"[VelNetPersist] Multiple records found for app='{Application.productName}' && room='{VelNetManager.Room}' && network_id='{networkObject.sceneNetworkId}'. Using the first one.");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadData(obj.items.FirstOrDefault());
|
for (int i = 0; i < syncStateComponents.Length; i++)
|
||||||
|
{
|
||||||
|
syncStateComponents[i].UnpackState(Convert.FromBase64String(componentData[i].state));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debugLogs) Debug.Log($"[VelNetPersist] Loaded {Id}");
|
||||||
|
loading = false;
|
||||||
}, s => { loading = false; });
|
}, s => { loading = false; });
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
VELConnectManager.GetRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, s =>
|
|
||||||
{
|
|
||||||
VELConnectManager.PersistObject obj = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
|
||||||
LoadData(obj);
|
|
||||||
},
|
|
||||||
s => { loading = false; });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadData(VELConnectManager.PersistObject obj)
|
|
||||||
|
public void Save(Action<VELConnectManager.State.DataBlock> successCallback = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(obj.data))
|
if (debugLogs) Debug.Log($"[VelNetPersist] Saving {Id}");
|
||||||
|
|
||||||
|
if (syncStateComponents.FirstOrDefault()?.networkObject == null)
|
||||||
{
|
{
|
||||||
Debug.LogError($"[VelNetPersist] No data found for {name}");
|
Debug.LogError("First SyncState doesn't have a NetworkObject", this);
|
||||||
loading = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
persistId = obj.id;
|
List<ComponentState> componentData = new List<ComponentState>();
|
||||||
|
foreach (SyncState syncState in syncStateComponents)
|
||||||
using BinaryReader reader = new BinaryReader(new MemoryStream(Convert.FromBase64String(obj.data)));
|
|
||||||
networkObject.UnpackState(reader);
|
|
||||||
|
|
||||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loaded {name}");
|
|
||||||
loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Save(Action<VELConnectManager.PersistObject> successCallback = null)
|
|
||||||
{
|
{
|
||||||
if (debugLogs) Debug.Log($"[VelNetPersist] Saving {name}");
|
if (syncState == null)
|
||||||
|
|
||||||
List<SyncState> syncStateComponents = networkObject.syncedComponents.OfType<SyncState>().ToList();
|
|
||||||
|
|
||||||
if (networkObject == null)
|
|
||||||
{
|
{
|
||||||
Debug.LogError("NetworkObject is null on SyncState", this);
|
Debug.LogError("SyncState is null for Persist", this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
if (syncState.networkObject == null)
|
||||||
networkObject.PackState(writer);
|
{
|
||||||
string data = Convert.ToBase64String(((MemoryStream)writer.BaseStream).ToArray());
|
Debug.LogError("Network Object is null for SyncState", syncState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if we have a persistId, update the record, otherwise create a new one
|
componentData.Add(new ComponentState()
|
||||||
if (string.IsNullOrEmpty(persistId))
|
|
||||||
{
|
{
|
||||||
Debug.LogWarning($"We don't have an existing persistId, so we are creating a new record for {networkObject.name}");
|
componentIdx = syncState.networkObject.syncedComponents.IndexOf(syncState),
|
||||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records", JsonConvert.SerializeObject(
|
state = Convert.ToBase64String(syncState.PackState())
|
||||||
new VELConnectManager.PersistObject()
|
|
||||||
{
|
|
||||||
app = Application.productName,
|
|
||||||
room = VelNetManager.Room,
|
|
||||||
network_id = networkObject.sceneNetworkId.ToString(),
|
|
||||||
spawned = !networkObject.isSceneObject,
|
|
||||||
name = networkObject.isSceneObject ? networkObject.name : networkObject.prefabName,
|
|
||||||
data = data,
|
|
||||||
}), null, s =>
|
|
||||||
{
|
|
||||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
|
||||||
persistId = resp.id;
|
|
||||||
successCallback?.Invoke(resp);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, JsonConvert.SerializeObject(
|
|
||||||
new VELConnectManager.PersistObject()
|
|
||||||
{
|
|
||||||
app = Application.productName,
|
|
||||||
room = VelNetManager.Room,
|
|
||||||
network_id = networkObject.sceneNetworkId.ToString(),
|
|
||||||
spawned = !networkObject.isSceneObject,
|
|
||||||
name = networkObject.prefabName,
|
|
||||||
data = data,
|
|
||||||
}), null, s =>
|
|
||||||
{
|
|
||||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
|
||||||
successCallback?.Invoke(resp);
|
|
||||||
}, method: "PATCH");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Delete(Action<VELConnectManager.PersistObject> successCallback = null)
|
VELConnectManager.SetDataBlock(Id, new VELConnectManager.State.DataBlock()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(persistId))
|
id = Id,
|
||||||
|
block_id = Id,
|
||||||
|
category = "object_persist",
|
||||||
|
data = new Dictionary<string, string>
|
||||||
{
|
{
|
||||||
Debug.LogError("We can't delete an object that doesn't have a persistId");
|
{ "name", syncStateComponents.FirstOrDefault()?.networkObject.name },
|
||||||
return;
|
{ "components", JsonConvert.SerializeObject(componentData) }
|
||||||
}
|
}
|
||||||
|
}, s => { successCallback?.Invoke(s); });
|
||||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, null, null,
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
|
||||||
successCallback?.Invoke(resp);
|
|
||||||
}, Debug.LogError,
|
|
||||||
method: "DELETE");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReceiveBytes(byte[] message)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "edu.uga.engr.vel.vel-connect",
|
"name": "edu.uga.engr.vel.vel-connect",
|
||||||
"displayName": "VEL-Connect",
|
"displayName": "VEL-Connect",
|
||||||
"version": "4.0.9",
|
"version": "4.0.8",
|
||||||
"unity": "2019.1",
|
"unity": "2019.1",
|
||||||
"description": "Web-based configuration for VR applications",
|
"description": "Web-based configuration for VR applications",
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
|
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
package migrations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/pocketbase/dbx"
|
|
||||||
"github.com/pocketbase/pocketbase/daos"
|
|
||||||
m "github.com/pocketbase/pocketbase/migrations"
|
|
||||||
"github.com/pocketbase/pocketbase/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
m.Register(func(db dbx.Builder) error {
|
|
||||||
jsonData := `{
|
|
||||||
"id": "zo5oymw0d6evw80",
|
|
||||||
"created": "2024-03-14 20:19:38.622Z",
|
|
||||||
"updated": "2024-03-14 20:19:38.622Z",
|
|
||||||
"name": "PersistObject",
|
|
||||||
"type": "base",
|
|
||||||
"system": false,
|
|
||||||
"schema": [
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "tvwuy2xt",
|
|
||||||
"name": "app",
|
|
||||||
"type": "text",
|
|
||||||
"required": true,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"min": null,
|
|
||||||
"max": null,
|
|
||||||
"pattern": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "mj06ihfs",
|
|
||||||
"name": "room",
|
|
||||||
"type": "text",
|
|
||||||
"required": true,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"min": null,
|
|
||||||
"max": null,
|
|
||||||
"pattern": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "mqw640xp",
|
|
||||||
"name": "network_id",
|
|
||||||
"type": "text",
|
|
||||||
"required": false,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"min": null,
|
|
||||||
"max": null,
|
|
||||||
"pattern": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "f0wynbda",
|
|
||||||
"name": "data",
|
|
||||||
"type": "json",
|
|
||||||
"required": true,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"maxSize": 2000000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "tqei9ccu",
|
|
||||||
"name": "spawned",
|
|
||||||
"type": "bool",
|
|
||||||
"required": false,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"system": false,
|
|
||||||
"id": "sgkbflei",
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"required": false,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"min": null,
|
|
||||||
"max": null,
|
|
||||||
"pattern": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [],
|
|
||||||
"listRule": "",
|
|
||||||
"viewRule": "",
|
|
||||||
"createRule": "",
|
|
||||||
"updateRule": "",
|
|
||||||
"deleteRule": null,
|
|
||||||
"options": {}
|
|
||||||
}`
|
|
||||||
|
|
||||||
collection := &models.Collection{}
|
|
||||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return daos.New(db).SaveCollection(collection)
|
|
||||||
}, func(db dbx.Builder) error {
|
|
||||||
dao := daos.New(db);
|
|
||||||
|
|
||||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dao.DeleteCollection(collection)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package migrations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
"github.com/pocketbase/dbx"
|
|
||||||
"github.com/pocketbase/pocketbase/daos"
|
|
||||||
m "github.com/pocketbase/pocketbase/migrations"
|
|
||||||
"github.com/pocketbase/pocketbase/models/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
m.Register(func(db dbx.Builder) error {
|
|
||||||
dao := daos.New(db);
|
|
||||||
|
|
||||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove
|
|
||||||
collection.Schema.RemoveField("f0wynbda")
|
|
||||||
|
|
||||||
// add
|
|
||||||
new_data := &schema.SchemaField{}
|
|
||||||
if err := json.Unmarshal([]byte(`{
|
|
||||||
"system": false,
|
|
||||||
"id": "9bremliu",
|
|
||||||
"name": "data",
|
|
||||||
"type": "text",
|
|
||||||
"required": true,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"min": null,
|
|
||||||
"max": null,
|
|
||||||
"pattern": ""
|
|
||||||
}
|
|
||||||
}`), new_data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
collection.Schema.AddField(new_data)
|
|
||||||
|
|
||||||
return dao.SaveCollection(collection)
|
|
||||||
}, func(db dbx.Builder) error {
|
|
||||||
dao := daos.New(db);
|
|
||||||
|
|
||||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// add
|
|
||||||
del_data := &schema.SchemaField{}
|
|
||||||
if err := json.Unmarshal([]byte(`{
|
|
||||||
"system": false,
|
|
||||||
"id": "f0wynbda",
|
|
||||||
"name": "data",
|
|
||||||
"type": "json",
|
|
||||||
"required": true,
|
|
||||||
"presentable": false,
|
|
||||||
"unique": false,
|
|
||||||
"options": {
|
|
||||||
"maxSize": 2000000
|
|
||||||
}
|
|
||||||
}`), del_data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
collection.Schema.AddField(del_data)
|
|
||||||
|
|
||||||
// remove
|
|
||||||
collection.Schema.RemoveField("9bremliu")
|
|
||||||
|
|
||||||
return dao.SaveCollection(collection)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue