You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
6.0 KiB
179 lines
6.0 KiB
-- ------------------------------------------------------------------------------ --
|
|
-- TradeSkillMaster --
|
|
-- https://tradeskillmaster.com --
|
|
-- All Rights Reserved - Detailed license information included with addon. --
|
|
-- ------------------------------------------------------------------------------ --
|
|
|
|
local TSM = select(2, ...) ---@type TSM
|
|
local StateSchema = TSM.Init("Util.ReactiveClasses.StateSchema") ---@class Util.ReactiveClasses.StateSchema
|
|
local State = TSM.Include("Util.ReactiveClasses.State")
|
|
local ReactiveStateSchema = TSM.Include("LibTSMClass").DefineClass("ReactiveStateSchema") ---@class ReactiveStateSchema
|
|
local VALID_TYPES = {
|
|
number = true,
|
|
string = true,
|
|
boolean = true,
|
|
table = true,
|
|
}
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- Module Functions
|
|
-- ============================================================================
|
|
|
|
---Creates a new state schema object.
|
|
---@return ReactiveStateSchema
|
|
function StateSchema.Create()
|
|
return ReactiveStateSchema()
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- ReactiveStateSchema - Class Meta Methods
|
|
-- ============================================================================
|
|
|
|
function ReactiveStateSchema:__init()
|
|
self._committed = false
|
|
self._fieldType = {}
|
|
self._default = {}
|
|
self._isOptional = {}
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- ReactiveStateSchema - Public Class Methods
|
|
-- ============================================================================
|
|
|
|
---Defines a string field as part of the schema.
|
|
---@param key string The key of the new field
|
|
---@param default string The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddStringField(key, default)
|
|
return self:_AddField(key, "string", default, false)
|
|
end
|
|
|
|
---Defines a string field as part of the schema which can be nil.
|
|
---@param key string The key of the new field
|
|
---@param default? string The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddOptionalStringField(key, default)
|
|
return self:_AddField(key, "string", default, true)
|
|
end
|
|
|
|
---Defines a number field as part of the schema.
|
|
---@param key string The key of the new field
|
|
---@param default number The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddNumberField(key, default)
|
|
return self:_AddField(key, "number", default, false)
|
|
end
|
|
|
|
---Defines a number field as part of the schema which can be nil.
|
|
---@param key string The key of the new field
|
|
---@param default? number The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddOptionalNumberField(key, default)
|
|
return self:_AddField(key, "number", default, true)
|
|
end
|
|
|
|
---Defines a boolean field as part of the schema.
|
|
---@param key string The key of the new field
|
|
---@param default boolean The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddBooleanField(key, default)
|
|
return self:_AddField(key, "boolean", default, false)
|
|
end
|
|
|
|
---Defines a boolean field as part of the schema which can be nil.
|
|
---@param key string The key of the new field
|
|
---@param default? boolean The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddOptionalBooleanField(key, default)
|
|
return self:_AddField(key, "boolean", default, true)
|
|
end
|
|
|
|
---Defines a table field as part of the schema which can be nil (and is by default).
|
|
---@param key string The key of the new field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:AddOptionalTableField(key)
|
|
return self:_AddField(key, "table", nil, true)
|
|
end
|
|
|
|
---Updates the default value of an existing field.
|
|
---@param key string The key of the field
|
|
---@param default? boolean The default value of the field
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:UpdateFieldDefault(key, default)
|
|
assert(not self._committed)
|
|
self:_ValidateValueForKey(key, default)
|
|
self._default[key] = default
|
|
return self
|
|
end
|
|
|
|
---Commits the schema and prevents further changes.
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:Commit()
|
|
self._committed = true
|
|
return self
|
|
end
|
|
|
|
---Creates a state object based on the schema.
|
|
---@return ReactiveState
|
|
function ReactiveStateSchema:CreateState()
|
|
assert(self._committed)
|
|
return State.Create(self)
|
|
end
|
|
|
|
---Returns a new state schema which extends the existing one
|
|
---@return ReactiveStateSchema
|
|
function ReactiveStateSchema:Extend()
|
|
assert(self._committed)
|
|
local newSchema = ReactiveStateSchema()
|
|
for key, fieldType in self:_FieldIterator() do
|
|
newSchema:_AddField(key, fieldType, self._default[key], self._isOptional[key])
|
|
end
|
|
return newSchema
|
|
end
|
|
|
|
|
|
|
|
-- ============================================================================
|
|
-- ReactiveStateSchema - Private Class Methods
|
|
-- ============================================================================
|
|
|
|
function ReactiveStateSchema:_AddField(key, fieldType, default, isOptional)
|
|
assert(not self._committed)
|
|
assert(not self._fieldType[key])
|
|
self._fieldType[key] = fieldType
|
|
self._default[key] = default
|
|
self._isOptional[key] = isOptional
|
|
self:_ValidateValueForKey(key, default)
|
|
return self
|
|
end
|
|
|
|
function ReactiveStateSchema:_ApplyDefaults(data)
|
|
for key in self:_FieldIterator() do
|
|
data[key] = self._default[key]
|
|
end
|
|
end
|
|
|
|
function ReactiveStateSchema:_ValidateValueForKey(key, value)
|
|
local fieldType = self._fieldType[key]
|
|
if not fieldType then
|
|
error("Invalid state key: "..tostring(key), 2)
|
|
elseif not VALID_TYPES[fieldType] then
|
|
error("Unexpected fieldType: "..tostring(fieldType))
|
|
elseif type(value) ~= fieldType and (value ~= nil or not self._isOptional[key]) then
|
|
error("Invalid type for state key ("..tostring(key).."): "..tostring(value))
|
|
end
|
|
end
|
|
|
|
function ReactiveStateSchema:_HasKey(key)
|
|
return self._fieldType[key] ~= nil
|
|
end
|
|
|
|
function ReactiveStateSchema:_FieldIterator()
|
|
return pairs(self._fieldType)
|
|
end
|
|
|