local Util = require(script.Parent.Util) local Profile = {} Profile.__index = Profile function Profile.new(store, userId, key, data, sessionId, keyInfo) return setmetatable({ _store = store, UserId = userId, Key = key, Data = data, SessionId = sessionId, KeyInfo = keyInfo, IsActive = true, IsDirty = false, _released = false, _lastSaved = os.clock(), }, Profile) end function Profile:_assertActive() assert(self.IsActive and not self._released, "NexusData profile is not active") end function Profile:Get(path, defaultValue) self:_assertActive() if type(path) == "string" then local value = self.Data[path] if value == nil then return defaultValue end return value end assert(type(path) == "table", "path must be a string or array of keys") local value = self.Data for _, key in ipairs(path) do if type(value) ~= "table" then return defaultValue end value = value[key] if value == nil then return defaultValue end end return value end function Profile:Set(path, value) self:_assertActive() assert(type(path) == "string", "Set currently expects a top-level string key") self.Data[path] = value self.IsDirty = true return value end function Profile:Update(path, callback) self:_assertActive() assert(type(path) == "string", "Update currently expects a top-level string key") assert(type(callback) == "function", "callback must be a function") local result = callback(self.Data[path]) self.Data[path] = result self.IsDirty = true return result end function Profile:Increment(path, amount) amount = amount or 1 assert(type(amount) == "number", "amount must be a number") return self:Update(path, function(current) current = current or 0 assert(type(current) == "number", "value must be a number") return current + amount end) end function Profile:ArrayInsert(path, value) self:_assertActive() local list = self.Data[path] assert(type(list) == "table", "target must be an array table") table.insert(list, value) self.IsDirty = true return #list end function Profile:ArrayRemove(path, index) self:_assertActive() local list = self.Data[path] assert(type(list) == "table", "target must be an array table") local removed = table.remove(list, index) if removed ~= nil then self.IsDirty = true end return removed end function Profile:Reconcile() self:_assertActive() Util.Reconcile(self.Data, self._store.Template) self.Data.SchemaVersion = self.Data.SchemaVersion or self._store.SchemaVersion self.IsDirty = true return self.Data end function Profile:Save() self:_assertActive() return self._store:SaveProfile(self.UserId) end function Profile:Release() if self._released then return true end return self._store:ReleaseProfile(self.UserId) end return Profile