@quenty/loader 5.0.1 → 5.0.2-canary.d7ea97f.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src2/Maid.lua ADDED
@@ -0,0 +1,222 @@
1
+ --[=[
2
+ Manages the cleaning of events and other things. Useful for
3
+ encapsulating state and make deconstructors easy.
4
+
5
+ See the [Five Powerful Code Patterns talk](https://developer.roblox.com/en-us/videos/5-powerful-code-patterns-behind-top-roblox-games)
6
+ for a more in-depth look at Maids in top games.
7
+
8
+ ```lua
9
+ local maid = Maid.new()
10
+
11
+ maid:GiveTask(function()
12
+ print("Cleaning up")
13
+ end)
14
+
15
+ maid:GiveTask(workspace.ChildAdded:Connect(print))
16
+
17
+ -- Disconnects all events, and executes all functions
18
+ maid:DoCleaning()
19
+ ```
20
+
21
+ @class Maid
22
+ ]=]
23
+ -- luacheck: pop
24
+
25
+ local Maid = {}
26
+ Maid.ClassName = "Maid"
27
+
28
+ --[=[
29
+ Constructs a new Maid object
30
+
31
+ ```lua
32
+ local maid = Maid.new()
33
+ ```
34
+
35
+ @return Maid
36
+ ]=]
37
+ function Maid.new()
38
+ return setmetatable({
39
+ _tasks = {}
40
+ }, Maid)
41
+ end
42
+
43
+ --[=[
44
+ Returns true if the class is a maid, and false otherwise.
45
+
46
+ ```lua
47
+ print(Maid.isMaid(Maid.new())) --> true
48
+ print(Maid.isMaid(nil)) --> false
49
+ ```
50
+
51
+ @param value any
52
+ @return boolean
53
+ ]=]
54
+ function Maid.isMaid(value)
55
+ return type(value) == "table" and value.ClassName == "Maid"
56
+ end
57
+
58
+ --[=[
59
+ Returns Maid[key] if not part of Maid metatable
60
+
61
+ ```lua
62
+ local maid = Maid.new()
63
+ maid._current = Instance.new("Part")
64
+ print(maid._current) --> Part
65
+
66
+ maid._current = nil
67
+ print(maid._current) --> nil
68
+ ```
69
+
70
+ @param index any
71
+ @return MaidTask
72
+ ]=]
73
+ function Maid:__index(index)
74
+ if Maid[index] then
75
+ return Maid[index]
76
+ else
77
+ return self._tasks[index]
78
+ end
79
+ end
80
+
81
+ --[=[
82
+ Add a task to clean up. Tasks given to a maid will be cleaned when
83
+ maid[index] is set to a different value.
84
+
85
+ Task cleanup is such that if the task is an event, it is disconnected.
86
+ If it is an object, it is destroyed.
87
+
88
+ ```
89
+ Maid[key] = (function) Adds a task to perform
90
+ Maid[key] = (event connection) Manages an event connection
91
+ Maid[key] = (thread) Manages a thread
92
+ Maid[key] = (Maid) Maids can act as an event connection, allowing a Maid to have other maids to clean up.
93
+ Maid[key] = (Object) Maids can cleanup objects with a `Destroy` method
94
+ Maid[key] = nil Removes a named task.
95
+ ```
96
+
97
+ @param index any
98
+ @param newTask MaidTask
99
+ ]=]
100
+ function Maid:__newindex(index, newTask)
101
+ if Maid[index] ~= nil then
102
+ error(("Cannot use '%s' as a Maid key"):format(tostring(index)), 2)
103
+ end
104
+
105
+ local tasks = self._tasks
106
+ local oldTask = tasks[index]
107
+
108
+ if oldTask == newTask then
109
+ return
110
+ end
111
+
112
+ tasks[index] = newTask
113
+
114
+ if oldTask then
115
+ if type(oldTask) == "function" then
116
+ oldTask()
117
+ elseif type(oldTask) == "thread" then
118
+ task.cancel(oldTask)
119
+ elseif typeof(oldTask) == "RBXScriptConnection" then
120
+ oldTask:Disconnect()
121
+ elseif oldTask.Destroy then
122
+ oldTask:Destroy()
123
+ end
124
+ end
125
+ end
126
+
127
+ --[=[
128
+ Gives a task to the maid for cleanup, but uses an incremented number as a key.
129
+
130
+ @param task MaidTask -- An item to clean
131
+ @return number -- taskId
132
+ ]=]
133
+ function Maid:GiveTask(task)
134
+ if not task then
135
+ error("Task cannot be false or nil", 2)
136
+ end
137
+
138
+ local taskId = #self._tasks+1
139
+ self[taskId] = task
140
+
141
+ if type(task) == "table" and (not task.Destroy) then
142
+ warn("[Maid.GiveTask] - Gave table task without .Destroy\n\n" .. debug.traceback())
143
+ end
144
+
145
+ return taskId
146
+ end
147
+
148
+ --[=[
149
+ Gives a promise to the maid for clean.
150
+
151
+ @param promise Promise<T>
152
+ @return Promise<T>
153
+ ]=]
154
+ function Maid:GivePromise(promise)
155
+ if not promise:IsPending() then
156
+ return promise
157
+ end
158
+
159
+ local newPromise = promise.resolved(promise)
160
+ local id = self:GiveTask(newPromise)
161
+
162
+ -- Ensure GC
163
+ newPromise:Finally(function()
164
+ self[id] = nil
165
+ end)
166
+
167
+ return newPromise
168
+ end
169
+
170
+ --[=[
171
+ Cleans up all tasks and removes them as entries from the Maid.
172
+
173
+ :::note
174
+ Signals that are already connected are always disconnected first. After that
175
+ any signals added during a cleaning phase will be disconnected at random times.
176
+ :::
177
+
178
+ :::tip
179
+ DoCleaning() may be recursively invoked. This allows the you to ensure that
180
+ tasks or other tasks. Each task will be executed once.
181
+
182
+ However, adding tasks while cleaning is not generally a good idea, as if you add a
183
+ function that adds itself, this will loop indefinitely.
184
+ :::
185
+ ]=]
186
+ function Maid:DoCleaning()
187
+ local tasks = self._tasks
188
+
189
+ -- Disconnect all events first as we know this is safe
190
+ for index, job in pairs(tasks) do
191
+ if typeof(job) == "RBXScriptConnection" then
192
+ tasks[index] = nil
193
+ job:Disconnect()
194
+ end
195
+ end
196
+
197
+ -- Clear out tasks table completely, even if clean up tasks add more tasks to the maid
198
+ local index, job = next(tasks)
199
+ while job ~= nil do
200
+ tasks[index] = nil
201
+ if type(job) == "function" then
202
+ job()
203
+ elseif type(job) == "thread" then
204
+ task.cancel(job)
205
+ elseif typeof(job) == "RBXScriptConnection" then
206
+ job:Disconnect()
207
+ elseif job.Destroy then
208
+ job:Destroy()
209
+ end
210
+ index, job = next(tasks)
211
+ end
212
+ end
213
+
214
+ --[=[
215
+ Alias for [Maid.DoCleaning()](/api/Maid#DoCleaning)
216
+
217
+ @function Destroy
218
+ @within Maid
219
+ ]=]
220
+ Maid.Destroy = Maid.DoCleaning
221
+
222
+ return Maid
@@ -0,0 +1,15 @@
1
+ --[=[
2
+ @class DependencyPath
3
+ ]=]
4
+
5
+ local DependencyPath = {}
6
+ DependencyPath.ClassName = "DependencyPath"
7
+ DependencyPath.__index = DependencyPath
8
+
9
+ function DependencyPath.new()
10
+ local self = setmetatable({}, DependencyPath)
11
+
12
+ return self
13
+ end
14
+
15
+ return DependencyPath
@@ -0,0 +1,13 @@
1
+ --[=[
2
+ Different replication types we can be in.
3
+
4
+ @class ReplicationType
5
+ ]=]
6
+
7
+ local Utils = require(script.Parent.Parent.Utils)
8
+
9
+ return Utils.readonly({
10
+ CLIENT = "client";
11
+ SERVER = "server";
12
+ SHARED = "shared";
13
+ })
@@ -0,0 +1,37 @@
1
+ --[=[
2
+ Utility functions involving [ReplicationType]
3
+ @class ReplicationTypeUtils
4
+ ]=]
5
+
6
+ local ReplicationType = require(script.Parent.ReplicationType)
7
+
8
+ local ReplicationTypeUtils = {}
9
+
10
+ --[=[
11
+ Returns true if the data is a replicationType
12
+ @param replicationType any
13
+ @return boolean
14
+ ]=]
15
+ function ReplicationTypeUtils.isReplicationType(replicationType)
16
+ return replicationType == ReplicationType.SHARED
17
+ or replicationType == ReplicationType.CLIENT
18
+ or replicationType == ReplicationType.SERVER
19
+ end
20
+
21
+ function ReplicationTypeUtils.getFolderReplicationType(folderName, ancestorReplicationType)
22
+ assert(type(folderName) == "string", "Bad folderName")
23
+ assert(type(ancestorReplicationType) == "string", "Bad ancestorReplicationType")
24
+
25
+ if folderName == "Shared" then
26
+ return ReplicationType.SHARED
27
+ elseif folderName == "Client" then
28
+ return ReplicationType.CLIENT
29
+ elseif folderName == "Server" then
30
+ return ReplicationType.SERVER
31
+ else
32
+ return ancestorReplicationType
33
+ end
34
+ end
35
+
36
+
37
+ return ReplicationTypeUtils