local Q=require(script.Parent.Promise)local M=game:GetService("\072\116\116\112\083\101\114\118\105\099\101")local J=table.sort local w=table.concat local v=math.ceil local a=math.floor local f={}f.Promise=Q local z do z={}z.__index=z setmetatable(z,{__call=function(Q,M)local J=setmetatable({},z)J.description="\083\121\109\098\111\108\040"..((M or"").."\041")return J end})local Q=setmetatable({},{__index=function(Q,M)Q[M]=z(M)return Q[M]end})function z.toString(Q)return Q.description end z.__tostring=z.toString function z.getFor(M)return Q[M]end function z.keyFor(M)for Q,J in pairs(Q)do if J==M then return Q end end end end f.Symbol=z f.Symbol_iterator=z("\083\121\109\098\111\108\046\105\116\101\114\097\116\111\114")local U=script.Parent:FindFirstChild("\110\111\100\101\095\109\111\100\117\108\101\115")function f.getModule(Q)local M=(getfenv(2)).script.Parent if not U then error("\067\111\117\108\100 \110\111\116 \102\105\110\100 \097\110\121 \109\111\100\117\108\101\115\033",2)end if M:IsDescendantOf(U)then while M.Parent do local J=M:FindFirstChild("\110\111\100\101\095\109\111\100\117\108\101\115")if J then local M=J:FindFirstChild(Q)if M then return M end end M=M.Parent end else local M=U:FindFirstChild(Q)if M then return M end end error("\067\111\117\108\100 \110\111\116 \102\105\110\100 \109\111\100\117\108\101\058 "..Q,2)end local j={}local K={}function f.import(Q,...)for M=1,select("\035",...),1 do Q=Q:WaitForChild(select(M,...))end if Q.ClassName=="\077\111\100\117\108\101\083\099\114\105\112\116"then local M=j[Q]if M==nil then local J=(getfenv(0)).script or{Name="\067\111\109\109\097\110\100 \098\097\114"}K[J]=Q local w=Q local v=0 while w do v=v+1 w=K[w]if w==Q then local Q=w.Name for M=1,v,1 do w=K[w]Q=Q..(" -\062 "..w.Name)end error("\070\097\105\108\101\100 \116\111 \105\109\112\111\114\116\033 \068\101\116\101\099\116\101\100 \097 \099\105\114\099\117\108\097\114 \100\101\112\101\110\100\101\110\099\121 \099\104\097\105\110\058 "..Q,2)end end assert(_G[Q]==nil,"\073\110\118\097\108\105\100 \109\111\100\117\108\101 \097\099\099\101\115\115\033")_G[Q]=f M={value=require(Q)}if K[J]==Q then K[J]=nil end j[Q]=M end return M.value else error("\070\097\105\108\101\100 \116\111 \105\109\112\111\114\116\033 \069\120\112\101\099\116\101\100 \077\111\100\117\108\101\083\099\114\105\112\116\044 \103\111\116 "..Q.ClassName,2)end end function f.exportNamespace(Q,M)for Q,J in pairs(Q)do M[Q]=J end end function f.instanceof(Q,M)if type(M)=="\116\097\098\108\101"and type(M.instanceof)=="\102\117\110\099\116\105\111\110"then return M.instanceof(Q)end if type(Q)=="\116\097\098\108\101"then Q=getmetatable(Q)while Q~=nil do if Q==M then return true end local J=getmetatable(Q)if J then Q=J.__index else Q=nil end end end return false end function f.async(M)return function(...)local J=select("\035",...)local w={...}return Q.new(function(Q,v)(coroutine.wrap(function()local a,f=pcall(M,unpack(w,1,J))if a then Q(f)else v(f)end end))()end)end end function f.await(M)if not Q.is(M)then return M end local J,w=M:await()if J then return w else f.throw(J==nil and"\084\104\101 \097\119\097\105\116\101\100 \080\114\111\109\105\115\101 \119\097\115 \099\097\110\099\101\108\108\101\100"or w)end end function f.add(Q,M)if type(Q)=="\115\116\114\105\110\103"or type(M)=="\115\116\114\105\110\103"then return Q..M else return Q+M end end local function B(Q)if Q<0 then return v(Q)else return a(Q)end end f.bit_truncate=B local Z=setmetatable({},{__index=function(Q,M)local J=2^M Q[M]=J return J end})local d=Z[52]local function X(Q,M,J)local w,v,a=0,d repeat a,Q,M=(Q+M)+v,Q%v,M%v w,v=w+(v*J)%((a-Q)-M),v/2 until v<1 return w end function f.bit_not(Q)return-Q-1 end function f.bit_or(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))return X(Q,M,1)end function f.bit_and(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))return X(Q,M,4)end function f.bit_xor(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))return X(Q,M,3)end function f.bit_lsh(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))return Q*Z[M]end function f.bit_rsh(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))return B(Q/Z[M])end function f.bit_lrsh(Q,M)Q=B(tonumber(Q))M=B(tonumber(M))if Q>=0 then return f.bit_rsh(Q,M)end return f.bit_rsh(Q%Z[32],M)end local function L(Q)local M={}for Q,J in pairs(Q)do M[Q]=J end return M end local function A(Q)local M={}for Q,J in pairs(Q)do if type(J)=="\116\097\098\108\101"then M[Q]=A(J)else M[Q]=J end end return M end local function l(Q,M)for J in pairs(Q)do local w=Q[J]local v=M[J]if type(w)=="\116\097\098\108\101"and type(v)=="\116\097\098\108\101"then local Q=l(w,v)if not Q then return false end elseif w~=v then return false end end for M in pairs(M)do if Q[M]==nil then return false end end return true end function f.Object_keys(Q)local M={}for Q in pairs(Q)do M[#M+1]=Q end return M end function f.Object_values(Q)local M={}for Q,J in pairs(Q)do M[#M+1]=J end return M end function f.Object_entries(Q)local M={}for Q,J in pairs(Q)do M[#M+1]={Q,J}end return M end function f.Object_assign(Q,...)for M=1,select("\035",...),1 do local J=select(M,...)if type(J)=="\116\097\098\108\101"then for M,J in pairs(J)do Q[M]=J end end end return Q end f.Object_copy=L f.Object_deepCopy=A f.Object_deepEquals=l local function b(Q)return M:JSONEncode(Q)end f.Object_toString=b function f.string_find_wrap(Q,M,...)if Q then return Q-1,M-1,...end end local function E(Q)local M={}for J=1,#Q,1 do M[J]=Q[J]end return M end f.array_copy=E function f.array_entries(Q)local M={}for J=1,#Q,1 do M[J]={J-1;Q[J]}end return M end function f.array_forEach(Q,M)for J=1,#Q,1 do local w=Q[J]if w~=nil then M(w,J-1,Q)end end end function f.array_map(Q,M)local J={}for w=1,#Q,1 do local v=Q[w]if v~=nil then J[w]=M(v,w-1,Q)end end return J end function f.array_filter(Q,M)local J={}for w=1,#Q,1 do local v=Q[w]if v~=nil and M(v,w-1,Q)==true then J[#J+1]=v end end return J end local function P(Q,M)return tostring(Q)<tostring(M)end function f.array_sort(Q,M)local w=E(Q)if M then J(w,function(Q,J)return 0<M(Q,J)end)else J(w,P)end return w end f.array_toString=b function f.array_slice(Q,M,J)local w=#Q if M==nil then M=0 end if J==nil then J=w end if M<0 then M=w+M end if J<0 then J=w+J end local v={}for J=M+1,J,1 do v[J-M]=Q[J]end return v end function f.array_splice(Q,M,J,...)local w=#Q local v if M<0 then v=w+M if v<0 then v=0 end else if M<w then v=M else v=w end end local a={...}local f=#a local z if M==nil then z=0 elseif J==nil then z=w-v else if J<0 then J=0 end z=w-v if J<z then z=J end end local U={}local j=0 while j<z do local M=v+j if Q[M+1]then U[j+1]=Q[M+1]end j=j+1 end if f<z then j=v while j<w-z do local M=j+z local J=j+f if Q[M+1]then Q[J+1]=Q[M+1]else Q[J+1]=nil end j=j+1 end j=w while j>(w-z)+f do Q[j]=nil j=j-1 end elseif f>z then j=w-z while j>v do local M=j+z local J=j+f if Q[M]then Q[J]=Q[M]else Q[J]=nil end j=j-1 end end j=v for M=1,#a,1 do Q[j+1]=a[M]j=j+1 end j=#Q while j>(w-z)+f do Q[j]=nil j=j-1 end return U end function f.array_some(Q,M)for J=1,#Q,1 do local w=Q[J]if w~=nil and M(w,J-1,Q)==true then return true end end return false end function f.array_every(Q,M)for J=1,#Q,1 do local w=Q[J]if w~=nil and M(w,J-1,Q)==false then return false end end return true end function f.array_includes(Q,M,J)for J=(J or 0)+1,#Q,1 do if Q[J]==M then return true end end return false end function f.array_indexOf(Q,M,J)for J=(J or 0)+1,#Q,1 do if M==Q[J]then return J-1 end end return-1 end function f.array_lastIndexOf(Q,M,J)for J=(J or#Q-1)+1,1,-1 do if M==Q[J]then return J-1 end end return-1 end function f.array_reverse(Q)local M={}local J=#Q local w=J+1 for J=1,J,1 do M[J]=Q[w-J]end return M end function f.array_reduce(Q,M,J)local w=1 if J==nil then J=Q[w]w=2 end local v=J for J=w,#Q,1 do local w=Q[J]if w~=nil then v=M(v,w,J)end end return v end function f.array_reduceRight(Q,M,J)local w=#Q if J==nil then J=Q[w]w=w-1 end local v=J for J=w,1,-1 do local w=Q[J]if w~=nil then v=M(v,w,J)end end return v end function f.array_unshift(Q,...)local M=#Q local J=select("\035",...)for M=M,1,-1 do Q[M+J]=Q[M]end for M=1,J,1 do Q[M]=select(M,...)end return M+J end local function n(Q,...)local M=#Q for J=1,select("\035",...),1 do local w=select(J,...)local v=#w for J=1,v,1 do Q[M+J]=w[J]end M=M+v end return M end f.array_push_apply=n function f.array_push_stack(Q,...)local M=#Q local J=select("\035",...)for J=1,J,1 do Q[M+J]=select(J,...)end return M+J end function f.array_concat(...)local Q={}n(Q,...)return Q end function f.array_join(Q,M)local J={}for M=1,#Q,1 do local w=Q[M]if w==nil then J[M]=""else J[M]=tostring(Q[M])end end return w(J,M or"\044")end function f.array_find(Q,M)for J=1,#Q,1 do local w=Q[J]if M(w,J-1,Q)==true then return w end end end function f.array_findIndex(Q,M)for J=0,#Q-1,1 do if M(Q[J+1],J,Q)==true then return J end end return-1 end local function t(Q,M,J,w)for v=1,#Q,1 do local a=Q[v]if a~=nil then if type(a)=="\116\097\098\108\101"then if M~=0 then J=t(a,M-1,J,w)else J=J+1 w[J]=a end else J=J+1 w[J]=a end end end return J end function f.array_flat(Q,M)local J={}t(Q,M or 1,0,J)return J end function f.array_fill(Q,M,J,w)local v=#Q if J==nil then J=0 elseif J<0 then J=J+v end if w==nil or w>v then w=v elseif w<0 then w=w+v end for J=J+1,w,1 do Q[J]=M end return Q end function f.array_copyWithin(Q,M,J,w)local v=#Q if M<0 then M=M+v end if J==nil then J=0 elseif J<0 then J=J+v end if w==nil or w>v then w=v elseif w<0 then w=w+v end local a=M-J local f=(w+a)-v if f>0 then w=(J+v)-M end for M=w,J+1,-1 do Q[M+a]=Q[M]end return Q end f.array_deepCopy=A f.array_deepEquals=l function f.map_new(Q)local M={}for J=1,#Q,1 do local w=Q[J]M[w[1]]=w[2]end return M end function f.map_clear(Q)for M in pairs(Q)do Q[M]=nil end end local function S(Q)local M=0 for Q in pairs(Q)do M=M+1 end return M end f.map_size=S f.map_entries=f.Object_entries function f.map_forEach(Q,M)for J,w in pairs(Q)do M(w,J,Q)end end f.map_keys=f.Object_keys f.map_values=f.Object_values f.map_toString=b function f.set_new(Q)local M={}for J=1,#Q,1 do M[Q[J]]=true end return M end f.set_clear=f.map_clear function f.set_forEach(Q,M)for J in pairs(Q)do M(J,J,Q)end end function f.set_union(Q,M)local J={}for Q in pairs(Q)do J[Q]=true end for Q in pairs(M)do J[Q]=true end return J end function f.set_intersect(Q,M)local J={}for Q in pairs(Q)do if M[Q]then J[Q]=true end end return J end function f.set_isDisjointWith(Q,M)for Q in pairs(Q)do if M[Q]then return false end end return true end function f.set_isSubsetOf(Q,M)for Q in pairs(Q)do if M[Q]==nil then return false end end return true end function f.set_difference(Q,M)local J={}for Q in pairs(Q)do if M[Q]==nil then J[Q]=true end end return J end f.set_values=f.Object_keys f.set_size=S f.set_toString=b function f.iterableCache(Q)local M={}local J=0 for Q in Q.next do if Q.done then break end J=J+1 M[J]=Q.value end return M end local function R(...)return select("\035",...),{...}end function f.iterableFunctionCache(Q)local M={}local J=0 while true do local w,v=R(Q())if w==0 then break end J=J+1 M[J]=v end return M end function f.Roact_combine(...)local Q={...}local M={}for J=1,#Q,1 do for Q,J in pairs(Q[J])do if type(Q)=="\110\117\109\098\101\114"then table.insert(M,J)else M[Q]=J end end end return M end function f.opcall(Q,...)local M,J=pcall(Q,...)if M then return{success=true;value=J}else return{success=false,error=J}end end local function c(...)return{size=select("\035",...),...}end local s={}function f.throw(Q)if#s>0 then s[#s](Q)else error("\085\110\099\097\117\103\104\116 "..tostring(Q),2)end end function f.try(Q,M)local J=false local w=false local v=false local a=coroutine.running()local f local function z()if not v then v=true s[#s]=nil end end local function U()if w then local Q,M=coroutine.resume(a)if not Q then warn(M)end else J=true end end local function j(Q)z()if M then f=c(M(Q))end U()coroutine.yield()end s[#s+1]=j;(coroutine.wrap(function()f=c(Q())U()end))()if not J then w=true coroutine.yield()end z()return f end return f
local Promise = require(script.Parent.Promise)

local HttpService = game:GetService("HttpService")

-- constants
local table_sort = table.sort
local table_concat = table.concat
local math_ceil = math.ceil
local math_floor = math.floor

local TS = {}

-- runtime classes
TS.Promise = Promise

local Symbol do
	Symbol = {}
	Symbol.__index = Symbol
	setmetatable(Symbol, {
		__call = function(_, description)
			local self = setmetatable({}, Symbol)
			self.description = "Symbol(" .. (description or "") .. ")"
			return self
		end
	})

	local symbolRegistry = setmetatable({}, {
		__index = function(self, k)
			self[k] = Symbol(k)
			return self[k]
		end
	})

	function Symbol:toString()
		return self.description
	end

	Symbol.__tostring = Symbol.toString

	-- Symbol.for
	function Symbol.getFor(key)
		return symbolRegistry[key]
	end

	function Symbol.keyFor(goalSymbol)
		for key, symbol in pairs(symbolRegistry) do
			if symbol == goalSymbol then
				return key
			end
		end
	end
end

TS.Symbol = Symbol
TS.Symbol_iterator = Symbol("Symbol.iterator")

-- module resolution
local globalModules = script.Parent:FindFirstChild("node_modules")

function TS.getModule(moduleName)
	local object = getfenv(2).script.Parent
	if not globalModules then
		error("Could not find any modules!", 2)
	end
	if object:IsDescendantOf(globalModules) then
		while object.Parent do
			local modules = object:FindFirstChild("node_modules")
			if modules then
				local module = modules:FindFirstChild(moduleName)
				if module then
					return module
				end
			end
			object = object.Parent
		end
	else
		local module = globalModules:FindFirstChild(moduleName)
		if module then
			return module
		end
	end
	error("Could not find module: " .. moduleName, 2)
end

-- This is a hash which TS.import uses as a kind of linked-list-like history of [Script who Loaded] -> Library
local loadedLibraries = {}
local currentlyLoading = {}

function TS.import(module, ...)
	for i = 1, select("#", ...) do
		module = module:WaitForChild((select(i, ...)))
	end

	if module.ClassName == "ModuleScript" then
		local data = loadedLibraries[module]

		if data == nil then
			-- If called from command bar, use table as a reference (this is never concatenated)
			local caller = getfenv(0).script or { Name = "Command bar" }
			currentlyLoading[caller] = module

			-- Check to see if a case like this occurs:
			-- module -> Module1 -> Module2 -> module

			-- WHERE currentlyLoading[module] is Module1
			-- and currentlyLoading[Module1] is Module2
			-- and currentlyLoading[Module2] is module

			local currentModule = module
			local depth = 0

			while currentModule do
				depth = depth + 1
				currentModule = currentlyLoading[currentModule]

				if currentModule == module then
					local str = currentModule.Name -- Get the string traceback

					for _ = 1, depth do
						currentModule = currentlyLoading[currentModule]
						str = str .. " -> " .. currentModule.Name
					end

					error("Failed to import! Detected a circular dependency chain: " .. str, 2)
				end
			end

			assert(_G[module] == nil, "Invalid module access!")
			_G[module] = TS
			data = { value = require(module) }

			if currentlyLoading[caller] == module then -- Thread-safe cleanup!
				currentlyLoading[caller] = nil
			end

			loadedLibraries[module] = data -- Cache for subsequent calls
		end

		return data.value
	else
		error("Failed to import! Expected ModuleScript, got " .. module.ClassName, 2)
	end
end

function TS.exportNamespace(module, ancestor)
	for key, value in pairs(module) do
		ancestor[key] = value
	end
end

-- general utility functions
function TS.instanceof(obj, class)
	-- custom Class.instanceof() check
	if type(class) == "table" and type(class.instanceof) == "function" then
		return class.instanceof(obj)
	end

	-- metatable check
	if type(obj) == "table" then
		obj = getmetatable(obj)
		while obj ~= nil do
			if obj == class then
				return true
			end
			local mt = getmetatable(obj)
			if mt then
				obj = mt.__index
			else
				obj = nil
			end
		end
	end

	return false
end

function TS.async(callback)
	return function(...)
		local n = select("#", ...)
		local args = { ... }
		return Promise.new(function(resolve, reject)
			coroutine.wrap(function()
				local ok, result = pcall(callback, unpack(args, 1, n))
				if ok then
					resolve(result)
				else
					reject(result)
				end
			end)()
		end)
	end
end

function TS.await(promise)
	if not Promise.is(promise) then
		return promise
	end

	local ok, result = promise:await()
	if ok then
		return result
	else
		TS.throw(ok == nil and "The awaited Promise was cancelled" or result)
	end
end

function TS.add(a, b)
	if type(a) == "string" or type(b) == "string" then
		return a .. b
	else
		return a + b
	end
end

local function bitTruncate(a)
	if a < 0 then
		return math_ceil(a)
	else
		return math_floor(a)
	end
end

TS.bit_truncate = bitTruncate

-- bitwise operations
local powOfTwo = setmetatable({}, {
	__index = function(self, i)
		local v = 2 ^ i
		self[i] = v
		return v
	end;
})

local _2_52 = powOfTwo[52]
local function bitop(a, b, oper)
	local r, m, s = 0, _2_52
	repeat
		s, a, b = a + b + m, a % m, b % m
		r, m = r + m * oper % (s - a - b), m / 2
	until m < 1
	return r
end

function TS.bit_not(a)
	return -a - 1
end

function TS.bit_or(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	return bitop(a, b, 1)
end

function TS.bit_and(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	return bitop(a, b, 4)
end

function TS.bit_xor(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	return bitop(a, b, 3)
end

function TS.bit_lsh(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	return a * powOfTwo[b]
end

function TS.bit_rsh(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	return bitTruncate(a / powOfTwo[b])
end

function TS.bit_lrsh(a, b)
	a = bitTruncate(tonumber(a))
	b = bitTruncate(tonumber(b))
	if a >= 0 then return TS.bit_rsh(a, b) end
	return TS.bit_rsh((a % powOfTwo[32]), b)
end

-- utility functions
local function copy(object)
	local result = {}
	for k, v in pairs(object) do
		result[k] = v
	end
	return result
end

local function deepCopy(object)
	local result = {}
	for k, v in pairs(object) do
		if type(v) == "table" then
			result[k] = deepCopy(v)
		else
			result[k] = v
		end
	end
	return result
end

local function deepEquals(a, b)
	-- a[k] == b[k]
	for k in pairs(a) do
		local av = a[k]
		local bv = b[k]
		if type(av) == "table" and type(bv) == "table" then
			local result = deepEquals(av, bv)
			if not result then
				return false
			end
		elseif av ~= bv then
			return false
		end
	end

	-- extra keys in b
	for k in pairs(b) do
		if a[k] == nil then
			return false
		end
	end

	return true
end

-- Object static functions

function TS.Object_keys(object)
	local result = {}
	for key in pairs(object) do
		result[#result + 1] = key
	end
	return result
end

function TS.Object_values(object)
	local result = {}
	for _, value in pairs(object) do
		result[#result + 1] = value
	end
	return result
end

function TS.Object_entries(object)
	local result = {}
	for key, value in pairs(object) do
		result[#result + 1] = { key, value }
	end
	return result
end

function TS.Object_assign(toObj, ...)
	for i = 1, select("#", ...) do
		local arg = select(i, ...)
		if type(arg) == "table" then
			for key, value in pairs(arg) do
				toObj[key] = value
			end
		end
	end
	return toObj
end

TS.Object_copy = copy

TS.Object_deepCopy = deepCopy

TS.Object_deepEquals = deepEquals

local function toString(data)
	return HttpService:JSONEncode(data)
end

TS.Object_toString = toString

-- string macro functions
function TS.string_find_wrap(a, b, ...)
	if a then
		return a - 1, b - 1, ...
	end
end

-- array macro functions
local function array_copy(list)
	local result = {}
	for i = 1, #list do
		result[i] = list[i]
	end
	return result
end

TS.array_copy = array_copy

function TS.array_entries(list)
	local result = {}
	for key = 1, #list do
		result[key] = { key - 1, list[key] }
	end
	return result
end

function TS.array_forEach(list, callback)
	for i = 1, #list do
		local v = list[i]
		if v ~= nil then
			callback(v, i - 1, list)
		end
	end
end

function TS.array_map(list, callback)
	local result = {}
	for i = 1, #list do
		local v = list[i]
		if v ~= nil then
			result[i] = callback(v, i - 1, list)
		end
	end
	return result
end

function TS.array_filter(list, callback)
	local result = {}
	for i = 1, #list do
		local v = list[i]
		if v ~= nil and callback(v, i - 1, list) == true then
			result[#result + 1] = v
		end
	end
	return result
end

local function sortFallback(a, b)
	return tostring(a) < tostring(b)
end

function TS.array_sort(list, callback)
	local sorted = array_copy(list)

	if callback then
		table_sort(sorted, function(a, b)
			return 0 < callback(a, b)
		end)
	else
		table_sort(sorted, sortFallback)
	end

	return sorted
end

TS.array_toString = toString

function TS.array_slice(list, startI, endI)
	local length = #list

	if startI == nil then startI = 0 end
	if endI == nil then endI = length end

	if startI < 0 then startI = length + startI end
	if endI < 0 then endI = length + endI end

	local result = {}

	for i = startI + 1, endI do
		result[i - startI] = list[i]
	end

	return result
end

function TS.array_splice(list, start, deleteCount, ...)
	local len = #list
	local actualStart
	if start < 0 then
		actualStart = len + start
		if actualStart < 0 then
			actualStart = 0
		end
	else
		if start < len then
			actualStart = start
		else
			actualStart = len
		end
	end
	local items = { ... }
	local itemCount = #items
	local actualDeleteCount
	if start == nil then
		actualDeleteCount = 0
	elseif deleteCount == nil then
		actualDeleteCount = len - actualStart
	else
		if deleteCount < 0 then
			deleteCount = 0
		end
		actualDeleteCount = len - actualStart
		if deleteCount < actualDeleteCount then
			actualDeleteCount = deleteCount
		end
	end
	local out = {}
	local k = 0
	while k < actualDeleteCount do
		local from = actualStart + k
		if list[from + 1] then
			out[k + 1] = list[from + 1]
		end
		k = k + 1
	end
	if itemCount < actualDeleteCount then
		k = actualStart
		while k < len - actualDeleteCount do
			local from = k + actualDeleteCount
			local to = k + itemCount
			if list[from + 1] then
				list[to + 1] = list[from + 1]
			else
				list[to + 1] = nil
			end
			k = k + 1
		end
		k = len
		while k > len - actualDeleteCount + itemCount do
			list[k] = nil
			k = k - 1
		end
	elseif itemCount > actualDeleteCount then
		k = len - actualDeleteCount
		while k > actualStart do
			local from = k + actualDeleteCount
			local to = k + itemCount
			if list[from] then
				list[to] = list[from]
			else
				list[to] = nil
			end
			k = k - 1
		end
	end
	k = actualStart
	for i = 1, #items do
		list[k + 1] = items[i]
		k = k + 1
	end
	k = #list
	while k > len - actualDeleteCount + itemCount do
		list[k] = nil
		k = k - 1
	end
	return out
end

function TS.array_some(list, callback)
	for i = 1, #list do
		local v = list[i]
		if v ~= nil and callback(v, i - 1, list) == true then
			return true
		end
	end
	return false
end

function TS.array_every(list, callback)
	for i = 1, #list do
		local v = list[i]
		if v ~= nil and callback(v, i - 1, list) == false then
			return false
		end
	end
	return true
end

function TS.array_includes(list, item, startingIndex)
	for i = (startingIndex or 0) + 1, #list do
		if list[i] == item then
			return true
		end
	end
	return false
end

function TS.array_indexOf(list, value, fromIndex)
	for i = (fromIndex or 0) + 1, #list do
		if value == list[i] then
			return i - 1
		end
	end
	return -1
end

function TS.array_lastIndexOf(list, value, fromIndex)
	for i = (fromIndex or #list - 1) + 1, 1, -1 do
		if value == list[i] then
			return i - 1
		end
	end
	return -1
end

function TS.array_reverse(list)
	local result = {}
	local length = #list
	local n = length + 1
	for i = 1, length do
		result[i] = list[n - i]
	end
	return result
end

function TS.array_reduce(list, callback, initialValue)
	local start = 1
	if initialValue == nil then
		initialValue = list[start]
		start = 2
	end
	local accumulator = initialValue
	for i = start, #list do
		local v = list[i]
		if v ~= nil then
			accumulator = callback(accumulator, v, i)
		end
	end
	return accumulator
end

function TS.array_reduceRight(list, callback, initialValue)
	local start = #list
	if initialValue == nil then
		initialValue = list[start]
		start = start - 1
	end
	local accumulator = initialValue
	for i = start, 1, -1 do
		local v = list[i]
		if v ~= nil then
			accumulator = callback(accumulator, v, i)
		end
	end
	return accumulator
end

function TS.array_unshift(list, ...)
	local n = #list
	local argsLength = select("#", ...)
	for i = n, 1, -1 do
		list[i + argsLength] = list[i]
	end
	for i = 1, argsLength do
		list[i] = select(i, ...)
	end
	return n + argsLength
end

local function array_push_apply(list, ...)
	local len = #list
	for i = 1, select("#", ...) do
		local list2 = select(i, ...)
		local len2 = #list2
		for j = 1, len2 do
			list[len + j] = list2[j]
		end
		len = len + len2
	end
	return len
end

TS.array_push_apply = array_push_apply

function TS.array_push_stack(list, ...)
	local len = #list
	local len2 = select("#", ...)
	for i = 1, len2 do
		list[len + i] = select(i, ...)
	end
	return len + len2
end

function TS.array_concat(...)
	local result = {}
	array_push_apply(result, ...)
	return result
end

function TS.array_join(list, separator)
	local result = {}
	for i = 1, #list do
		local item = list[i]
		if item == nil then
			result[i] = ""
		else
			result[i] = tostring(list[i])
		end
	end
	return table_concat(result, separator or ",")
end

function TS.array_find(list, callback)
	for i = 1, #list do
		local v = list[i]
		if callback(v, i - 1, list) == true then
			return v
		end
	end
end

function TS.array_findIndex(list, callback)
	for i = 0, #list - 1 do
		if callback(list[i + 1], i, list) == true then
			return i
		end
	end
	return -1
end

local function array_flat_helper(list, depth, count, result)
	for i = 1, #list do
		local v = list[i]

		if v ~= nil then
			if type(v) == "table" then
				if depth ~= 0 then
					count = array_flat_helper(v, depth - 1, count, result)
				else
					count = count + 1
					result[count] = v
				end
			else
				count = count + 1
				result[count] = v
			end
		end
	end

	return count
end

function TS.array_flat(list, depth)
	local result = {}
	array_flat_helper(list, depth or 1, 0, result)
	return result
end

function TS.array_fill(list, value, from, to)
	local length = #list

	if from == nil then
		from = 0
	elseif from < 0 then
		from = from + length
	end

	if to == nil or to > length then
		to = length
	elseif to < 0 then
		to = to + length
	end

	for i = from + 1, to do
		list[i] = value
	end

	return list
end

function TS.array_copyWithin(list, target, from, to)
	local length = #list

	if target < 0 then
		target = target + length
	end

	if from == nil then
		from = 0
	elseif from < 0 then
		from = from + length
	end

	if to == nil or to > length then
		to = length
	elseif to < 0 then
		to = to + length
	end

	local tf = target - from
	local overshoot = to + tf - length

	if overshoot > 0 then
		to = from + length - target
	end

	for i = to, from + 1, -1 do
		list[i + tf] = list[i]
	end

	return list
end

TS.array_deepCopy = deepCopy

TS.array_deepEquals = deepEquals

-- map macro functions

function TS.map_new(pairs)
	local result = {}
	for i = 1, #pairs do
		local pair = pairs[i]
		result[pair[1]] = pair[2]
	end
	return result
end

function TS.map_clear(map)
	for key in pairs(map) do
		map[key] = nil
	end
end

local function getNumKeys(map)
	local result = 0
	for _ in pairs(map) do
		result = result + 1
	end
	return result
end

TS.map_size = getNumKeys
TS.map_entries = TS.Object_entries

function TS.map_forEach(map, callback)
	for key, value in pairs(map) do
		callback(value, key, map)
	end
end

TS.map_keys = TS.Object_keys

TS.map_values = TS.Object_values
TS.map_toString = toString

-- set macro functions

function TS.set_new(values)
	local result = {}
	for i = 1, #values do
		result[values[i]] = true
	end
	return result
end

TS.set_clear = TS.map_clear

function TS.set_forEach(set, callback)
	for key in pairs(set) do
		callback(key, key, set)
	end
end

function TS.set_union(set1, set2)
	local result = {}

	for value in pairs(set1) do
		result[value] = true
	end

	for value in pairs(set2) do
		result[value] = true
	end

	return result
end

function TS.set_intersect(set1, set2)
	local result = {}

	for value in pairs(set1) do
		if set2[value] then
			result[value] = true
		end
	end

	return result
end

function TS.set_isDisjointWith(set1, set2)
	for value in pairs(set1) do
		if set2[value] then
			return false
		end
	end
	return true
end

function TS.set_isSubsetOf(set1, set2)
	for value in pairs(set1) do
		if set2[value] == nil then
			return false
		end
	end

	return true
end

function TS.set_difference(set1, set2)
	local result = {}
	for value in pairs(set1) do
		if set2[value] == nil then
			result[value] = true
		end
	end
	return result
end

TS.set_values = TS.Object_keys

TS.set_size = getNumKeys

TS.set_toString = toString

function TS.iterableCache(iter)
	local results = {}
	local count = 0
	for _0 in iter.next do
		if _0.done then break end
		count = count + 1
		results[count] = _0.value
	end
	return results
end

local function package(...)
	return select("#", ...), {...}
end

function TS.iterableFunctionCache(iter)
	local results = {}
	local count = 0

	while true do
		local size, t = package(iter());
		if size == 0 then break end
		count = count + 1
		results[count] = t
	end

	return results
end

-- roact functions

function TS.Roact_combine(...)
	local args = { ... }
	local result = {}
	for i = 1, #args do
		for key, value in pairs(args[i]) do
			if (type(key) == "number") then
				table.insert(result, value)
			else
				result[key] = value
			end
		end
	end
	return result
end

-- opcall

function TS.opcall(func, ...)
	local success, valueOrErr = pcall(func, ...)
	if success then
		return {
			success = true,
			value = valueOrErr,
		}
	else
		return {
			success = false,
			error = valueOrErr,
		}
	end
end

-- try catch utilities

local function pack(...)
	return { size = select("#", ...), ... }
end

local throwStack = {}

function TS.throw(value)
	if #throwStack > 0 then
		throwStack[#throwStack](value)
	else
		error("Uncaught " .. tostring(value), 2)
	end
end

function TS.try(tryCallback, catchCallback)
	local done = false
	local yielded = false
	local popped = false
	local resumeThread = coroutine.running()

	local returns

	local function pop()
		if not popped then
			popped = true
			throwStack[#throwStack] = nil
		end
	end

	local function resume()
		if yielded then
			local success, errorMsg = coroutine.resume(resumeThread)
			if not success then
				warn(errorMsg)
			end
		else
			done = true
		end
	end

	local function throw(value)
		pop()
		if catchCallback then
			returns = pack(catchCallback(value))
		end
		resume()
		coroutine.yield()
	end

	throwStack[#throwStack + 1] = throw

	coroutine.wrap(function()
		returns = pack(tryCallback())
		resume()
	end)()

	if not done then
		yielded = true
		coroutine.yield()
	end

	pop()

	return returns
end

return TS
