mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Add live syncback functionality and optimize service encoding
- Introduced a new endpoint `/api/syncback` for one-click full sync from Roblox Studio to the filesystem, eliminating the need for an active WebSocket connection. - Implemented `SyncbackRequest` and `ServiceChunk` structures to handle service-level properties and child instances during syncback. - Enhanced `encodeService` to include ObjectValue carriers for accurate reference handling and prevent data loss. - Updated the syncback process to utilize Luau-style relative paths for reference attributes, improving path management and consistency. - Integrated session caching in the matching algorithm to optimize performance during syncback operations. These changes significantly improve the live syncback experience, ensuring reliable data synchronization and enhanced performance during development.
This commit is contained in:
parent
7f4b5c4941
commit
b47eef1173
165 changed files with 5205 additions and 206 deletions
|
|
@ -221,7 +221,9 @@ encodeInstance = function(instance, parentId, _skipPathCheck)
|
|||
-- Only encode properties that:
|
||||
-- 1. Are readable (ReadWrite or Read scriptability)
|
||||
-- 2. Actually serialize (not "DoesNotSerialize")
|
||||
local isReadable = propertyMeta.scriptability == "ReadWrite" or propertyMeta.scriptability == "Read"
|
||||
local isReadable = propertyMeta.scriptability == "ReadWrite"
|
||||
or propertyMeta.scriptability == "Read"
|
||||
or propertyMeta.scriptability == "Custom"
|
||||
local doesSerialize = propertyMeta.serialization ~= "DoesNotSerialize"
|
||||
|
||||
if isReadable and doesSerialize then
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ return function(service: Instance)
|
|||
continue
|
||||
end
|
||||
|
||||
local isReadable = propertyMeta.scriptability == "ReadWrite" or propertyMeta.scriptability == "Read"
|
||||
local isReadable = propertyMeta.scriptability == "ReadWrite"
|
||||
or propertyMeta.scriptability == "Read"
|
||||
or propertyMeta.scriptability == "Custom"
|
||||
local doesSerialize = propertyMeta.serialization ~= "DoesNotSerialize"
|
||||
|
||||
if isReadable and doesSerialize then
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
]]
|
||||
|
||||
local HttpService = game:GetService("HttpService")
|
||||
local ScriptEditorService = game:GetService("ScriptEditorService")
|
||||
|
||||
local Rojo = script:FindFirstAncestor("Rojo")
|
||||
local Plugin = Rojo.Plugin
|
||||
|
|
@ -367,6 +368,20 @@ function PatchTree.build(patch, instanceMap, changeListHeaders, gitMetadata)
|
|||
break
|
||||
end
|
||||
end
|
||||
|
||||
if defaultSelection == nil then
|
||||
local ok, draft = pcall(ScriptEditorService.GetEditorSource, ScriptEditorService, instance)
|
||||
if ok and draft ~= source then
|
||||
local draftBlob = "blob " .. tostring(#draft) .. "\0" .. draft
|
||||
local draftHash = SHA1(buffer.fromstring(draftBlob))
|
||||
for _, hash in hashes do
|
||||
if draftHash == hash then
|
||||
defaultSelection = "push"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,6 +10,41 @@
|
|||
|
||||
local HttpService = game:GetService("HttpService")
|
||||
|
||||
local MockPromise = {}
|
||||
MockPromise.__index = MockPromise
|
||||
|
||||
function MockPromise.resolve(value)
|
||||
return setmetatable({ _value = value, _rejected = false }, MockPromise)
|
||||
end
|
||||
|
||||
function MockPromise.reject(err)
|
||||
return setmetatable({ _value = err, _rejected = true }, MockPromise)
|
||||
end
|
||||
|
||||
function MockPromise:andThen(callback)
|
||||
if not self._rejected then
|
||||
local ok, result = pcall(callback, self._value)
|
||||
if ok then
|
||||
return MockPromise.resolve(result)
|
||||
else
|
||||
return MockPromise.reject(result)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
function MockPromise:catch(callback)
|
||||
if self._rejected then
|
||||
local ok, result = pcall(callback, self._value)
|
||||
if ok then
|
||||
return MockPromise.resolve(result)
|
||||
else
|
||||
return MockPromise.reject(result)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
local MockApiContext = {}
|
||||
MockApiContext.__index = MockApiContext
|
||||
|
||||
|
|
@ -155,22 +190,15 @@ function MockApiContext:write(patch)
|
|||
self:_maybeDelay()
|
||||
|
||||
if self.failOnWrite then
|
||||
return false, "Mock write failure"
|
||||
return MockPromise.reject("Mock write failure")
|
||||
end
|
||||
|
||||
if self.onWrite then
|
||||
local result = self.onWrite(self, patch)
|
||||
if result ~= nil then
|
||||
return result
|
||||
end
|
||||
self.onWrite(self, patch)
|
||||
end
|
||||
|
||||
if self.writeResponse then
|
||||
return true, self.writeResponse
|
||||
end
|
||||
|
||||
-- Default success response
|
||||
return true, { success = true }
|
||||
local response = self.writeResponse or { success = true }
|
||||
return MockPromise.resolve(response)
|
||||
end
|
||||
|
||||
--[[
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue