diff --git a/modules/trove/init.luau b/modules/trove/init.luau index 7bd29174..726e6ca0 100644 --- a/modules/trove/init.luau +++ b/modules/trove/init.luau @@ -6,9 +6,13 @@ export type Trove = { Extend: (self: Trove) -> Trove, Clone: (self: Trove, instance: T & Instance) -> T, Construct: (self: Trove, class: Constructable, A...) -> T, - Connect: (self: Trove, signal: SignalLike | RBXScriptSignal, fn: (...any) -> ...any) -> ConnectionLike, + Connect: ( + self: Trove, + signal: SignalLike | SignalLikeMetatable | RBXScriptSignal, + fn: (...any) -> ...any + ) -> ConnectionLike | ConnectionLikeMetatable, BindToRenderStep: (self: Trove, name: string, priority: number, fn: (dt: number) -> ()) -> (), - AddPromise: (self: Trove, promise: T & PromiseLike) -> T, + AddPromise: (self: Trove, promise: (T & PromiseLike) | (T & PromiseLikeMetatable)) -> T, Add: (self: Trove, object: T & Trackable, cleanupMethod: string?) -> T, Remove: (self: Trove, object: T & Trackable) -> boolean, Clean: (self: Trove) -> (), @@ -25,20 +29,28 @@ type TroveInternal = Trove & { --[=[ @within Trove - @type Trackable Instance | RBXScriptConnection | ConnectionLike | PromiseLike | thread | ((...any) -> ...any) | Destroyable | DestroyableLowercase | Disconnectable | DisconnectableLowercase + @type Trackable Instance | RBXScriptConnection | ConnectionLike | ConnectLikeMetatable | PromiseLike | PromiseLikeMetatable | thread | ((...any) -> ...any) | Destroyable | DestroyableMetatable | DestroyableLowercase | DestroyableLowercaseMetatable | Disconnectable | DisconnectableMetatable | DisconnectableLowercase | DisconnectableLowercaseMetatable | SignalLike | SignalLikeMetatable Represents all trackable objects by Trove. ]=] export type Trackable = Instance | RBXScriptConnection | ConnectionLike + | ConnectionLikeMetatable | PromiseLike + | PromiseLikeMetatable | thread | ((...any) -> ...any) | Destroyable + | DestroyableMetatable | DestroyableLowercase + | DestroyableLowercaseMetatable | Disconnectable + | DisconectableMetatable | DisconnectableLowercase + | DisconnectableLowercaseMetatable + | SignalLike + | SignalLikeMetatable --[=[ @within Trove @@ -51,6 +63,18 @@ type ConnectionLike = { Disconnect: (self: ConnectionLike) -> (), } +--[=[ + @within Trove + @interface ConnectionLikeMetatable + .Connected boolean + .Disconnect (self) -> () + @tag Metatable +]=] +type ConnectionLikeMetatable = typeof(setmetatable( + {}, + {} :: { Connected: boolean, Disconnect: (self: ConnectionLikeMetatable) -> () } +)) + --[=[ @within Trove @interface SignalLike @@ -58,10 +82,25 @@ type ConnectionLike = { .Once (self, callback: (...any) -> ...any) -> ConnectionLike ]=] type SignalLike = { - Connect: (self: SignalLike, callback: (...any) -> ...any) -> ConnectionLike, - Once: (self: SignalLike, callback: (...any) -> ...any) -> ConnectionLike, + Connect: (self: SignalLike, callback: (...any) -> ...any) -> ConnectionLike | ConnectionLikeMetatable, + Once: (self: SignalLike, callback: (...any) -> ...any) -> ConnectionLike | ConnectionLikeMetatable, } +--[=[ + @within Trove + @interface SignalLikeMetatable + .Connect (self, callback: (...any) -> ...any) -> ConnectionLike + .Once (self, callback: (...any) -> ...any) -> ConnectionLike + @tag Metatable +]=] +type SignalLikeMetatable = typeof(setmetatable( + {}, + {} :: { + Connect: (self: SignalLikeMetatable, callback: (...any) -> ...any) -> ConnectionLike | ConnectionLikeMetatable, + Once: (self: SignalLikeMetatable, callback: (...any) -> ...any) -> ConnectionLike | ConnectionLikeMetatable, + } +)) + --[=[ @within Trove @interface PromiseLike @@ -71,10 +110,27 @@ type SignalLike = { ]=] type PromiseLike = { getStatus: (self: PromiseLike) -> string, - finally: (self: PromiseLike, callback: (...any) -> ...any) -> PromiseLike, + finally: (self: PromiseLike, callback: (...any) -> ...any) -> PromiseLike | PromiseLikeMetatable, cancel: (self: PromiseLike) -> (), } +--[=[ + @within Trove + @interface PromiseLikeMetatable + .getStatus (self) -> string + .finally (self, callback: (...any) -> ...any) -> PromiseLike + .cancel (self) -> () + @tag Metatable +]=] +type PromiseLikeMetatable = typeof(setmetatable( + {}, + {} :: { + getStatus: (self: any) -> string, + finally: (self: PromiseLikeMetatable, callback: (...any) -> ...any) -> PromiseLike | PromiseLikeMetatable, + cancel: (self: PromiseLikeMetatable) -> (), + } +)) + --[=[ @within Trove @type Constructable { new: (A...) -> T } | (A...) -> T @@ -84,30 +140,57 @@ type Constructable = { new: (A...) -> T } | (A...) -> T --[=[ @within Trove @interface Destroyable - .disconnect (self) -> () + .Destroy (self) -> () ]=] type Destroyable = { Destroy: (self: Destroyable) -> (), } +--[=[ + @within Trove + @interface DestroyableMetatable + .Destroy (self) -> () + @tag Metatable +]=] +type DestroyableMetatable = typeof(setmetatable({}, {} :: { Destroy: (self: DestroyableMetatable) -> () })) + --[=[ @within Trove @interface DestroyableLowercase - .disconnect (self) -> () + .destroy (self) -> () ]=] type DestroyableLowercase = { destroy: (self: DestroyableLowercase) -> (), } +--[=[ + @within Trove + @interface DestroyableLowercaseMetatable + .destroy (self) -> () + @tag Metatable +]=] +type DestroyableLowercaseMetatable = typeof(setmetatable( + {}, + {} :: { destroy: (self: DestroyableLowercaseMetatable) -> () } +)) + --[=[ @within Trove @interface Disconnectable - .disconnect (self) -> () + .Disconnect (self) -> () ]=] type Disconnectable = { Disconnect: (self: Disconnectable) -> (), } +--[=[ + @within Trove + @interface DisconectableMetatable + .Disconnect (self) -> () + @tag Metatable +]=] +type DisconectableMetatable = typeof(setmetatable({}, {} :: { Disconnect: (self: DisconectableMetatable) -> () })) + --[=[ @within Trove @interface DisconnectableLowercase @@ -117,6 +200,17 @@ type DisconnectableLowercase = { disconnect: (self: DisconnectableLowercase) -> (), } +--[=[ + @within Trove + @interface DisconnectableLowercaseMetatable + .disconnect (self) -> () + @tag Metatable +]=] +type DisconnectableLowercaseMetatable = typeof(setmetatable( + {}, + {} :: { disconnect: (self: DisconnectableLowercaseMetatable) -> () } +)) + local FN_MARKER = newproxy() local THREAD_MARKER = newproxy() local GENERIC_OBJECT_CLEANUP_METHODS = table.freeze({ "Destroy", "Disconnect", "destroy", "disconnect" }) @@ -160,6 +254,12 @@ local function AssertPromiseLike(object: any) end end +local function AssertSignalLike(object: any) + if typeof(object) ~= "table" or typeof(object.Connect) ~= "function" or typeof(object.Once) ~= "function" then + error("did not receive a signal as an argument", 3) + end +end + --[=[ @class Trove A Trove is helpful for tracking any sort of object during @@ -280,7 +380,7 @@ end If a function is given, the function will be called with the given arguments. - + The result from either of the two options will be added to the trove. @@ -333,12 +433,19 @@ end end) ``` ]=] -function Trove.Connect(self: TroveInternal, signal: SignalLike, fn: (...any) -> ...any) +function Trove.Connect( + self: TroveInternal, + signal: SignalLike | SignalLikeMetatable | RBXScriptSignal, + fn: (...any) -> ...any +) if self._cleaning then error("Cannot call trove:Connect() while cleaning", 2) end + AssertSignalLike(signal) + + local confirmedSignal = signal :: SignalLike - return self:Add(signal:Connect(fn)) + return self:Add(confirmedSignal:Connect(fn)) end --[=[ @@ -393,24 +500,25 @@ end This is only compatible with the [roblox-lua-promise](https://eryn.io/roblox-lua-promise/) library, version 4. ::: ]=] -function Trove.AddPromise(self: TroveInternal, promise: PromiseLike) +function Trove.AddPromise(self: TroveInternal, promise: PromiseLike | PromiseLikeMetatable) if self._cleaning then error("cannot call trove:AddPromise() while cleaning", 2) end AssertPromiseLike(promise) + local confirmedPromise = promise :: PromiseLike - if promise:getStatus() == "Started" then - promise:finally(function() + if confirmedPromise:getStatus() == "Started" then + confirmedPromise:finally(function() if self._cleaning then return end - self:_findAndRemoveFromObjects(promise, false) + self:_findAndRemoveFromObjects(confirmedPromise, false) end) - self:Add(promise, "cancel") + self:Add(confirmedPromise, "cancel") end - return promise + return confirmedPromise end --[=[