roblox-opencode 1.0.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.
Files changed (248) hide show
  1. package/README.md +122 -0
  2. package/commands/setup-game.md +108 -0
  3. package/commands/sync-check.md +53 -0
  4. package/core/roblox-core.md +93 -0
  5. package/dist/server.js +167 -0
  6. package/package.json +35 -0
  7. package/skills/roblox-analytics/SKILL.md +277 -0
  8. package/skills/roblox-analytics/references/event-batcher.luau +75 -0
  9. package/skills/roblox-animation-vfx/SKILL.md +1325 -0
  10. package/skills/roblox-architecture/SKILL.md +863 -0
  11. package/skills/roblox-architecture/references/combat-systems.md +1381 -0
  12. package/skills/roblox-code-review/SKILL.md +687 -0
  13. package/skills/roblox-data/SKILL.md +889 -0
  14. package/skills/roblox-data/references/inventory-systems.md +1729 -0
  15. package/skills/roblox-debug/SKILL.md +99 -0
  16. package/skills/roblox-gui/SKILL.md +1103 -0
  17. package/skills/roblox-gui-fusion/SKILL.md +150 -0
  18. package/skills/roblox-gui-fusion/references/inventory.luau +427 -0
  19. package/skills/roblox-gui-fusion/references/settings-menu.luau +579 -0
  20. package/skills/roblox-gui-fusion/references/shop.luau +411 -0
  21. package/skills/roblox-luau-mastery/SKILL.md +1519 -0
  22. package/skills/roblox-monetization/SKILL.md +1084 -0
  23. package/skills/roblox-monetization/references/process-receipt.luau +131 -0
  24. package/skills/roblox-networking/SKILL.md +669 -0
  25. package/skills/roblox-networking/references/remote-validator.luau +193 -0
  26. package/skills/roblox-publish-checklist/SKILL.md +128 -0
  27. package/skills/roblox-runtime/SKILL.md +753 -0
  28. package/skills/roblox-sharp-edges/SKILL.md +295 -0
  29. package/skills/roblox-sync/SKILL.md +126 -0
  30. package/skills/roblox-testing/SKILL.md +943 -0
  31. package/skills/roblox-tooling/SKILL.md +150 -0
  32. package/vendor/LICENSES/ProfileStore-LICENSE +201 -0
  33. package/vendor/LICENSES/RbxUtil-LICENSE +7 -0
  34. package/vendor/LICENSES/promise-LICENSE +21 -0
  35. package/vendor/LICENSES/t-LICENSE +21 -0
  36. package/vendor/LICENSES/testez-LICENSE +201 -0
  37. package/vendor/README.md +84 -0
  38. package/vendor/fusion/Animation/ExternalTime.luau +84 -0
  39. package/vendor/fusion/Animation/Spring.luau +322 -0
  40. package/vendor/fusion/Animation/Stopwatch.luau +128 -0
  41. package/vendor/fusion/Animation/Tween.luau +187 -0
  42. package/vendor/fusion/Animation/getTweenDuration.luau +27 -0
  43. package/vendor/fusion/Animation/getTweenRatio.luau +47 -0
  44. package/vendor/fusion/Animation/lerpType.luau +164 -0
  45. package/vendor/fusion/Animation/packType.luau +100 -0
  46. package/vendor/fusion/Animation/springCoefficients.luau +80 -0
  47. package/vendor/fusion/Animation/unpackType.luau +103 -0
  48. package/vendor/fusion/Colour/Oklab.luau +70 -0
  49. package/vendor/fusion/Colour/sRGB.luau +55 -0
  50. package/vendor/fusion/External.luau +168 -0
  51. package/vendor/fusion/ExternalDebug.luau +70 -0
  52. package/vendor/fusion/Graph/Observer.luau +114 -0
  53. package/vendor/fusion/Graph/castToGraph.luau +29 -0
  54. package/vendor/fusion/Graph/change.luau +81 -0
  55. package/vendor/fusion/Graph/depend.luau +33 -0
  56. package/vendor/fusion/Graph/evaluate.luau +56 -0
  57. package/vendor/fusion/Instances/Attribute.luau +58 -0
  58. package/vendor/fusion/Instances/AttributeChange.luau +47 -0
  59. package/vendor/fusion/Instances/AttributeOut.luau +63 -0
  60. package/vendor/fusion/Instances/Child.luau +21 -0
  61. package/vendor/fusion/Instances/Children.luau +148 -0
  62. package/vendor/fusion/Instances/Hydrate.luau +33 -0
  63. package/vendor/fusion/Instances/New.luau +53 -0
  64. package/vendor/fusion/Instances/OnChange.luau +50 -0
  65. package/vendor/fusion/Instances/OnEvent.luau +54 -0
  66. package/vendor/fusion/Instances/Out.luau +69 -0
  67. package/vendor/fusion/Instances/applyInstanceProps.luau +149 -0
  68. package/vendor/fusion/Instances/defaultProps.luau +194 -0
  69. package/vendor/fusion/LICENSE +21 -0
  70. package/vendor/fusion/Logging/formatError.luau +49 -0
  71. package/vendor/fusion/Logging/messages.luau +52 -0
  72. package/vendor/fusion/Logging/parseError.luau +25 -0
  73. package/vendor/fusion/Memory/checkLifetime.luau +134 -0
  74. package/vendor/fusion/Memory/deriveScope.luau +24 -0
  75. package/vendor/fusion/Memory/deriveScopeImpl.luau +45 -0
  76. package/vendor/fusion/Memory/doCleanup.luau +79 -0
  77. package/vendor/fusion/Memory/innerScope.luau +34 -0
  78. package/vendor/fusion/Memory/legacyCleanup.luau +18 -0
  79. package/vendor/fusion/Memory/needsDestruction.luau +17 -0
  80. package/vendor/fusion/Memory/poisonScope.luau +34 -0
  81. package/vendor/fusion/Memory/scopePool.luau +55 -0
  82. package/vendor/fusion/Memory/scoped.luau +27 -0
  83. package/vendor/fusion/Memory/whichLivesLonger.luau +75 -0
  84. package/vendor/fusion/RobloxExternal.luau +98 -0
  85. package/vendor/fusion/State/Computed.luau +139 -0
  86. package/vendor/fusion/State/For/Disassembly.luau +211 -0
  87. package/vendor/fusion/State/For/ForTypes.luau +30 -0
  88. package/vendor/fusion/State/For/init.luau +110 -0
  89. package/vendor/fusion/State/ForKeys.luau +94 -0
  90. package/vendor/fusion/State/ForPairs.luau +97 -0
  91. package/vendor/fusion/State/ForValues.luau +94 -0
  92. package/vendor/fusion/State/Value.luau +88 -0
  93. package/vendor/fusion/State/castToState.luau +26 -0
  94. package/vendor/fusion/State/peek.luau +31 -0
  95. package/vendor/fusion/State/updateAll.luau +1 -0
  96. package/vendor/fusion/Types.luau +314 -0
  97. package/vendor/fusion/Utility/Contextual.luau +91 -0
  98. package/vendor/fusion/Utility/Safe.luau +23 -0
  99. package/vendor/fusion/Utility/isSimilar.luau +29 -0
  100. package/vendor/fusion/Utility/merge.luau +35 -0
  101. package/vendor/fusion/Utility/nameOf.luau +35 -0
  102. package/vendor/fusion/Utility/never.luau +14 -0
  103. package/vendor/fusion/Utility/nicknames.luau +11 -0
  104. package/vendor/fusion/Utility/xtypeof.luau +27 -0
  105. package/vendor/fusion/init.luau +82 -0
  106. package/vendor/profilestore/init.luau +2243 -0
  107. package/vendor/promise/init.luau +1982 -0
  108. package/vendor/rbxutil/buffer-util/Buffer.test.luau +25 -0
  109. package/vendor/rbxutil/buffer-util/BufferReader.luau +228 -0
  110. package/vendor/rbxutil/buffer-util/BufferWriter.luau +269 -0
  111. package/vendor/rbxutil/buffer-util/DataTypeBuffer.luau +223 -0
  112. package/vendor/rbxutil/buffer-util/Types.luau +60 -0
  113. package/vendor/rbxutil/buffer-util/index.d.ts +153 -0
  114. package/vendor/rbxutil/buffer-util/init.luau +41 -0
  115. package/vendor/rbxutil/buffer-util/package.json +16 -0
  116. package/vendor/rbxutil/buffer-util/wally.toml +9 -0
  117. package/vendor/rbxutil/comm/Client/ClientComm.luau +232 -0
  118. package/vendor/rbxutil/comm/Client/ClientRemoteProperty.luau +156 -0
  119. package/vendor/rbxutil/comm/Client/ClientRemoteSignal.luau +109 -0
  120. package/vendor/rbxutil/comm/Client/init.luau +135 -0
  121. package/vendor/rbxutil/comm/Server/RemoteProperty.luau +295 -0
  122. package/vendor/rbxutil/comm/Server/RemoteSignal.luau +211 -0
  123. package/vendor/rbxutil/comm/Server/ServerComm.luau +211 -0
  124. package/vendor/rbxutil/comm/Server/init.luau +140 -0
  125. package/vendor/rbxutil/comm/Types.luau +18 -0
  126. package/vendor/rbxutil/comm/Util.luau +27 -0
  127. package/vendor/rbxutil/comm/init.luau +35 -0
  128. package/vendor/rbxutil/comm/wally.toml +13 -0
  129. package/vendor/rbxutil/component/init.luau +759 -0
  130. package/vendor/rbxutil/component/init.test.luau +311 -0
  131. package/vendor/rbxutil/component/wally.toml +14 -0
  132. package/vendor/rbxutil/concur/init.luau +542 -0
  133. package/vendor/rbxutil/concur/init.test.luau +364 -0
  134. package/vendor/rbxutil/concur/wally.toml +8 -0
  135. package/vendor/rbxutil/enum-list/init.luau +101 -0
  136. package/vendor/rbxutil/enum-list/init.test.luau +91 -0
  137. package/vendor/rbxutil/enum-list/wally.toml +8 -0
  138. package/vendor/rbxutil/find/index.d.ts +20 -0
  139. package/vendor/rbxutil/find/init.luau +44 -0
  140. package/vendor/rbxutil/find/package.json +17 -0
  141. package/vendor/rbxutil/find/wally.toml +8 -0
  142. package/vendor/rbxutil/input/Gamepad.luau +559 -0
  143. package/vendor/rbxutil/input/Keyboard.luau +124 -0
  144. package/vendor/rbxutil/input/Mouse.luau +278 -0
  145. package/vendor/rbxutil/input/PreferredInput.luau +91 -0
  146. package/vendor/rbxutil/input/Touch.luau +120 -0
  147. package/vendor/rbxutil/input/init.luau +33 -0
  148. package/vendor/rbxutil/input/wally.toml +12 -0
  149. package/vendor/rbxutil/loader/index.d.ts +15 -0
  150. package/vendor/rbxutil/loader/init.luau +137 -0
  151. package/vendor/rbxutil/loader/wally.toml +8 -0
  152. package/vendor/rbxutil/log/index.d.ts +38 -0
  153. package/vendor/rbxutil/log/init.luau +746 -0
  154. package/vendor/rbxutil/log/wally.toml +8 -0
  155. package/vendor/rbxutil/net/init.luau +190 -0
  156. package/vendor/rbxutil/net/wally.toml +8 -0
  157. package/vendor/rbxutil/option/index.d.ts +44 -0
  158. package/vendor/rbxutil/option/init.luau +489 -0
  159. package/vendor/rbxutil/option/init.test.luau +342 -0
  160. package/vendor/rbxutil/option/wally.toml +8 -0
  161. package/vendor/rbxutil/pid/index.d.ts +53 -0
  162. package/vendor/rbxutil/pid/init.luau +195 -0
  163. package/vendor/rbxutil/pid/package.json +16 -0
  164. package/vendor/rbxutil/pid/wally.toml +9 -0
  165. package/vendor/rbxutil/quaternion/index.d.ts +117 -0
  166. package/vendor/rbxutil/quaternion/init.luau +570 -0
  167. package/vendor/rbxutil/quaternion/package.json +16 -0
  168. package/vendor/rbxutil/quaternion/wally.toml +9 -0
  169. package/vendor/rbxutil/query/index.d.ts +43 -0
  170. package/vendor/rbxutil/query/init.luau +117 -0
  171. package/vendor/rbxutil/query/package.json +18 -0
  172. package/vendor/rbxutil/query/wally.toml +9 -0
  173. package/vendor/rbxutil/sequent/index.d.ts +28 -0
  174. package/vendor/rbxutil/sequent/init.luau +340 -0
  175. package/vendor/rbxutil/sequent/package.json +16 -0
  176. package/vendor/rbxutil/sequent/wally.toml +9 -0
  177. package/vendor/rbxutil/ser/init.luau +175 -0
  178. package/vendor/rbxutil/ser/init.test.luau +50 -0
  179. package/vendor/rbxutil/ser/wally.toml +11 -0
  180. package/vendor/rbxutil/shake/index.d.ts +36 -0
  181. package/vendor/rbxutil/shake/init.luau +532 -0
  182. package/vendor/rbxutil/shake/init.test.luau +267 -0
  183. package/vendor/rbxutil/shake/package.json +16 -0
  184. package/vendor/rbxutil/shake/wally.toml +9 -0
  185. package/vendor/rbxutil/signal/index.d.ts +100 -0
  186. package/vendor/rbxutil/signal/init.luau +432 -0
  187. package/vendor/rbxutil/signal/init.test.luau +190 -0
  188. package/vendor/rbxutil/signal/package.json +17 -0
  189. package/vendor/rbxutil/signal/wally.toml +9 -0
  190. package/vendor/rbxutil/silo/TableWatcher.luau +65 -0
  191. package/vendor/rbxutil/silo/Util.luau +55 -0
  192. package/vendor/rbxutil/silo/init.luau +338 -0
  193. package/vendor/rbxutil/silo/init.test.luau +215 -0
  194. package/vendor/rbxutil/silo/wally.toml +8 -0
  195. package/vendor/rbxutil/spring/index.d.ts +40 -0
  196. package/vendor/rbxutil/spring/init.luau +97 -0
  197. package/vendor/rbxutil/spring/package.json +17 -0
  198. package/vendor/rbxutil/spring/wally.toml +8 -0
  199. package/vendor/rbxutil/stream/index.d.ts +88 -0
  200. package/vendor/rbxutil/stream/init.luau +597 -0
  201. package/vendor/rbxutil/stream/package.json +18 -0
  202. package/vendor/rbxutil/stream/wally.toml +9 -0
  203. package/vendor/rbxutil/streamable/Streamable.luau +202 -0
  204. package/vendor/rbxutil/streamable/StreamableUtil.luau +80 -0
  205. package/vendor/rbxutil/streamable/init.luau +8 -0
  206. package/vendor/rbxutil/streamable/wally.toml +12 -0
  207. package/vendor/rbxutil/symbol/init.luau +56 -0
  208. package/vendor/rbxutil/symbol/init.test.luau +37 -0
  209. package/vendor/rbxutil/symbol/wally.toml +8 -0
  210. package/vendor/rbxutil/table-util/init.luau +938 -0
  211. package/vendor/rbxutil/table-util/init.test.luau +439 -0
  212. package/vendor/rbxutil/table-util/wally.toml +8 -0
  213. package/vendor/rbxutil/task-queue/index.d.ts +27 -0
  214. package/vendor/rbxutil/task-queue/init.luau +97 -0
  215. package/vendor/rbxutil/task-queue/wally.toml +8 -0
  216. package/vendor/rbxutil/timer/index.d.ts +81 -0
  217. package/vendor/rbxutil/timer/init.luau +249 -0
  218. package/vendor/rbxutil/timer/init.test.luau +73 -0
  219. package/vendor/rbxutil/timer/wally.toml +11 -0
  220. package/vendor/rbxutil/tree/index.d.ts +15 -0
  221. package/vendor/rbxutil/tree/init.luau +137 -0
  222. package/vendor/rbxutil/tree/wally.toml +8 -0
  223. package/vendor/rbxutil/trove/index.d.ts +46 -0
  224. package/vendor/rbxutil/trove/init.luau +787 -0
  225. package/vendor/rbxutil/trove/init.test.luau +203 -0
  226. package/vendor/rbxutil/trove/wally.toml +8 -0
  227. package/vendor/rbxutil/typed-remote/init.luau +196 -0
  228. package/vendor/rbxutil/typed-remote/wally.toml +8 -0
  229. package/vendor/rbxutil/wait-for/index.d.ts +17 -0
  230. package/vendor/rbxutil/wait-for/init.luau +257 -0
  231. package/vendor/rbxutil/wait-for/init.test.luau +182 -0
  232. package/vendor/rbxutil/wait-for/wally.toml +11 -0
  233. package/vendor/t/t.lua +1350 -0
  234. package/vendor/testez/Context.lua +26 -0
  235. package/vendor/testez/Expectation.lua +311 -0
  236. package/vendor/testez/ExpectationContext.lua +38 -0
  237. package/vendor/testez/LifecycleHooks.lua +89 -0
  238. package/vendor/testez/Reporters/TeamCityReporter.lua +102 -0
  239. package/vendor/testez/Reporters/TextReporter.lua +106 -0
  240. package/vendor/testez/Reporters/TextReporterQuiet.lua +97 -0
  241. package/vendor/testez/TestBootstrap.lua +147 -0
  242. package/vendor/testez/TestEnum.lua +28 -0
  243. package/vendor/testez/TestPlan.lua +304 -0
  244. package/vendor/testez/TestPlanner.lua +40 -0
  245. package/vendor/testez/TestResults.lua +112 -0
  246. package/vendor/testez/TestRunner.lua +188 -0
  247. package/vendor/testez/TestSession.lua +243 -0
  248. package/vendor/testez/init.lua +40 -0
package/vendor/t/t.lua ADDED
@@ -0,0 +1,1350 @@
1
+ -- t: a runtime typechecker for Roblox
2
+
3
+ local t = {}
4
+
5
+ function t.type(typeName)
6
+ return function(value)
7
+ local valueType = type(value)
8
+ if valueType == typeName then
9
+ return true
10
+ else
11
+ return false, string.format("%s expected, got %s", typeName, valueType)
12
+ end
13
+ end
14
+ end
15
+
16
+ function t.typeof(typeName)
17
+ return function(value)
18
+ local valueType = typeof(value)
19
+ if valueType == typeName then
20
+ return true
21
+ else
22
+ return false, string.format("%s expected, got %s", typeName, valueType)
23
+ end
24
+ end
25
+ end
26
+
27
+ --[[**
28
+ matches any type except nil
29
+
30
+ @param value The value to check against
31
+
32
+ @returns True iff the condition is satisfied, false otherwise
33
+ **--]]
34
+ function t.any(value)
35
+ if value ~= nil then
36
+ return true
37
+ else
38
+ return false, "any expected, got nil"
39
+ end
40
+ end
41
+
42
+ --Lua primitives
43
+
44
+ --[[**
45
+ ensures Lua primitive boolean type
46
+
47
+ @param value The value to check against
48
+
49
+ @returns True iff the condition is satisfied, false otherwise
50
+ **--]]
51
+ t.boolean = t.typeof("boolean")
52
+
53
+ --[[**
54
+ ensures Lua primitive buffer type
55
+
56
+ @param value The value to check against
57
+
58
+ @returns True iff the condition is satisfied, false otherwise
59
+ **--]]
60
+ t.buffer = t.typeof("buffer")
61
+
62
+ --[[**
63
+ ensures Lua primitive thread type
64
+
65
+ @param value The value to check against
66
+
67
+ @returns True iff the condition is satisfied, false otherwise
68
+ **--]]
69
+ t.thread = t.typeof("thread")
70
+
71
+ --[[**
72
+ ensures Lua primitive callback type
73
+
74
+ @param value The value to check against
75
+
76
+ @returns True iff the condition is satisfied, false otherwise
77
+ **--]]
78
+ t.callback = t.typeof("function")
79
+ t["function"] = t.callback
80
+
81
+ --[[**
82
+ ensures Lua primitive none type
83
+
84
+ @param value The value to check against
85
+
86
+ @returns True iff the condition is satisfied, false otherwise
87
+ **--]]
88
+ t.none = t.typeof("nil")
89
+ t["nil"] = t.none
90
+
91
+ --[[**
92
+ ensures Lua primitive string type
93
+
94
+ @param value The value to check against
95
+
96
+ @returns True iff the condition is satisfied, false otherwise
97
+ **--]]
98
+ t.string = t.typeof("string")
99
+
100
+ --[[**
101
+ ensures Lua primitive table type
102
+
103
+ @param value The value to check against
104
+
105
+ @returns True iff the condition is satisfied, false otherwise
106
+ **--]]
107
+ t.table = t.typeof("table")
108
+
109
+ --[[**
110
+ ensures Lua primitive userdata type
111
+
112
+ @param value The value to check against
113
+
114
+ @returns True iff the condition is satisfied, false otherwise
115
+ **--]]
116
+ t.userdata = t.type("userdata")
117
+
118
+ --[[**
119
+ ensures Lua primitive vector type
120
+
121
+ @param value The value to check against
122
+
123
+ @returns True iff the condition is satisfied, false otherwise
124
+ **--]]
125
+ t.vector = t.type("vector")
126
+
127
+ --[[**
128
+ ensures value is a number and non-NaN
129
+
130
+ @param value The value to check against
131
+
132
+ @returns True iff the condition is satisfied, false otherwise
133
+ **--]]
134
+ function t.number(value)
135
+ local valueType = typeof(value)
136
+ if valueType == "number" then
137
+ if value == value then
138
+ return true
139
+ else
140
+ return false, "unexpected NaN value"
141
+ end
142
+ else
143
+ return false, string.format("number expected, got %s", valueType)
144
+ end
145
+ end
146
+
147
+ --[[**
148
+ ensures value is NaN
149
+
150
+ @param value The value to check against
151
+
152
+ @returns True iff the condition is satisfied, false otherwise
153
+ **--]]
154
+ function t.nan(value)
155
+ local valueType = typeof(value)
156
+ if valueType == "number" then
157
+ if value ~= value then
158
+ return true
159
+ else
160
+ return false, "unexpected non-NaN value"
161
+ end
162
+ else
163
+ return false, string.format("number expected, got %s", valueType)
164
+ end
165
+ end
166
+
167
+ -- roblox types
168
+
169
+ --[[**
170
+ ensures Roblox Axes type
171
+
172
+ @param value The value to check against
173
+
174
+ @returns True iff the condition is satisfied, false otherwise
175
+ **--]]
176
+ t.Axes = t.typeof("Axes")
177
+
178
+ --[[**
179
+ ensures Roblox BrickColor type
180
+
181
+ @param value The value to check against
182
+
183
+ @returns True iff the condition is satisfied, false otherwise
184
+ **--]]
185
+ t.BrickColor = t.typeof("BrickColor")
186
+
187
+ --[[**
188
+ ensures Roblox CatalogSearchParams type
189
+
190
+ @param value The value to check against
191
+
192
+ @returns True iff the condition is satisfied, false otherwise
193
+ **--]]
194
+ t.CatalogSearchParams = t.typeof("CatalogSearchParams")
195
+
196
+ --[[**
197
+ ensures Roblox CFrame type
198
+
199
+ @param value The value to check against
200
+
201
+ @returns True iff the condition is satisfied, false otherwise
202
+ **--]]
203
+ t.CFrame = t.typeof("CFrame")
204
+
205
+ --[[**
206
+ ensures Roblox Content type
207
+
208
+ @param value The value to check against
209
+
210
+ @returns True iff the condition is satisfied, false otherwise
211
+ **--]]
212
+ t.Content = t.typeof("Content")
213
+
214
+ --[[**
215
+ ensures Roblox Color3 type
216
+
217
+ @param value The value to check against
218
+
219
+ @returns True iff the condition is satisfied, false otherwise
220
+ **--]]
221
+ t.Color3 = t.typeof("Color3")
222
+
223
+ --[[**
224
+ ensures Roblox ColorSequence type
225
+
226
+ @param value The value to check against
227
+
228
+ @returns True iff the condition is satisfied, false otherwise
229
+ **--]]
230
+ t.ColorSequence = t.typeof("ColorSequence")
231
+
232
+ --[[**
233
+ ensures Roblox ColorSequenceKeypoint type
234
+
235
+ @param value The value to check against
236
+
237
+ @returns True iff the condition is satisfied, false otherwise
238
+ **--]]
239
+ t.ColorSequenceKeypoint = t.typeof("ColorSequenceKeypoint")
240
+
241
+ --[[**
242
+ ensures Roblox DateTime type
243
+
244
+ @param value The value to check against
245
+
246
+ @returns True iff the condition is satisfied, false otherwise
247
+ **--]]
248
+ t.DateTime = t.typeof("DateTime")
249
+
250
+ --[[**
251
+ ensures Roblox DockWidgetPluginGuiInfo type
252
+
253
+ @param value The value to check against
254
+
255
+ @returns True iff the condition is satisfied, false otherwise
256
+ **--]]
257
+ t.DockWidgetPluginGuiInfo = t.typeof("DockWidgetPluginGuiInfo")
258
+
259
+ --[[**
260
+ ensures Roblox Enum type
261
+
262
+ @param value The value to check against
263
+
264
+ @returns True iff the condition is satisfied, false otherwise
265
+ **--]]
266
+ t.Enum = t.typeof("Enum")
267
+
268
+ --[[**
269
+ ensures Roblox EnumItem type
270
+
271
+ @param value The value to check against
272
+
273
+ @returns True iff the condition is satisfied, false otherwise
274
+ **--]]
275
+ t.EnumItem = t.typeof("EnumItem")
276
+
277
+ --[[**
278
+ ensures Roblox Enums type
279
+
280
+ @param value The value to check against
281
+
282
+ @returns True iff the condition is satisfied, false otherwise
283
+ **--]]
284
+ t.Enums = t.typeof("Enums")
285
+
286
+ --[[**
287
+ ensures Roblox Faces type
288
+
289
+ @param value The value to check against
290
+
291
+ @returns True iff the condition is satisfied, false otherwise
292
+ **--]]
293
+ t.Faces = t.typeof("Faces")
294
+
295
+ --[[**
296
+ ensures Roblox FloatCurveKey type
297
+
298
+ @param value The value to check against
299
+
300
+ @returns True iff the condition is satisfied, false otherwise
301
+ **--]]
302
+ t.FloatCurveKey = t.typeof("FloatCurveKey")
303
+
304
+ --[[**
305
+ ensures Roblox Font type
306
+
307
+ @param value The value to check against
308
+
309
+ @returns True iff the condition is satisfied, false otherwise
310
+ **--]]
311
+ t.Font = t.typeof("Font")
312
+
313
+ --[[**
314
+ ensures Roblox Instance type
315
+
316
+ @param value The value to check against
317
+
318
+ @returns True iff the condition is satisfied, false otherwise
319
+ **--]]
320
+ t.Instance = t.typeof("Instance")
321
+
322
+ --[[**
323
+ ensures Roblox NumberRange type
324
+
325
+ @param value The value to check against
326
+
327
+ @returns True iff the condition is satisfied, false otherwise
328
+ **--]]
329
+ t.NumberRange = t.typeof("NumberRange")
330
+
331
+ --[[**
332
+ ensures Roblox NumberSequence type
333
+
334
+ @param value The value to check against
335
+
336
+ @returns True iff the condition is satisfied, false otherwise
337
+ **--]]
338
+ t.NumberSequence = t.typeof("NumberSequence")
339
+
340
+ --[[**
341
+ ensures Roblox NumberSequenceKeypoint type
342
+
343
+ @param value The value to check against
344
+
345
+ @returns True iff the condition is satisfied, false otherwise
346
+ **--]]
347
+ t.NumberSequenceKeypoint = t.typeof("NumberSequenceKeypoint")
348
+
349
+ --[[**
350
+ ensures Roblox OverlapParams type
351
+
352
+ @param value The value to check against
353
+
354
+ @returns True iff the condition is satisfied, false otherwise
355
+ **--]]
356
+ t.OverlapParams = t.typeof("OverlapParams")
357
+
358
+ --[[**
359
+ ensures Roblox PathWaypoint type
360
+
361
+ @param value The value to check against
362
+
363
+ @returns True iff the condition is satisfied, false otherwise
364
+ **--]]
365
+ t.PathWaypoint = t.typeof("PathWaypoint")
366
+
367
+ --[[**
368
+ ensures Roblox PhysicalProperties type
369
+
370
+ @param value The value to check against
371
+
372
+ @returns True iff the condition is satisfied, false otherwise
373
+ **--]]
374
+ t.PhysicalProperties = t.typeof("PhysicalProperties")
375
+
376
+ --[[**
377
+ ensures Roblox Random type
378
+
379
+ @param value The value to check against
380
+
381
+ @returns True iff the condition is satisfied, false otherwise
382
+ **--]]
383
+ t.Random = t.typeof("Random")
384
+
385
+ --[[**
386
+ ensures Roblox Ray type
387
+
388
+ @param value The value to check against
389
+
390
+ @returns True iff the condition is satisfied, false otherwise
391
+ **--]]
392
+ t.Ray = t.typeof("Ray")
393
+
394
+ --[[**
395
+ ensures Roblox RaycastParams type
396
+
397
+ @param value The value to check against
398
+
399
+ @returns True iff the condition is satisfied, false otherwise
400
+ **--]]
401
+ t.RaycastParams = t.typeof("RaycastParams")
402
+
403
+ --[[**
404
+ ensures Roblox RaycastResult type
405
+
406
+ @param value The value to check against
407
+
408
+ @returns True iff the condition is satisfied, false otherwise
409
+ **--]]
410
+ t.RaycastResult = t.typeof("RaycastResult")
411
+
412
+ --[[**
413
+ ensures Roblox RBXScriptConnection type
414
+
415
+ @param value The value to check against
416
+
417
+ @returns True iff the condition is satisfied, false otherwise
418
+ **--]]
419
+ t.RBXScriptConnection = t.typeof("RBXScriptConnection")
420
+
421
+ --[[**
422
+ ensures Roblox RBXScriptSignal type
423
+
424
+ @param value The value to check against
425
+
426
+ @returns True iff the condition is satisfied, false otherwise
427
+ **--]]
428
+ t.RBXScriptSignal = t.typeof("RBXScriptSignal")
429
+
430
+ --[[**
431
+ ensures Roblox Rect type
432
+
433
+ @param value The value to check against
434
+
435
+ @returns True iff the condition is satisfied, false otherwise
436
+ **--]]
437
+ t.Rect = t.typeof("Rect")
438
+
439
+ --[[**
440
+ ensures Roblox Region3 type
441
+
442
+ @param value The value to check against
443
+
444
+ @returns True iff the condition is satisfied, false otherwise
445
+ **--]]
446
+ t.Region3 = t.typeof("Region3")
447
+
448
+ --[[**
449
+ ensures Roblox Region3int16 type
450
+
451
+ @param value The value to check against
452
+
453
+ @returns True iff the condition is satisfied, false otherwise
454
+ **--]]
455
+ t.Region3int16 = t.typeof("Region3int16")
456
+
457
+ --[[**
458
+ ensures Roblox TweenInfo type
459
+
460
+ @param value The value to check against
461
+
462
+ @returns True iff the condition is satisfied, false otherwise
463
+ **--]]
464
+ t.TweenInfo = t.typeof("TweenInfo")
465
+
466
+ --[[**
467
+ ensures Roblox UDim type
468
+
469
+ @param value The value to check against
470
+
471
+ @returns True iff the condition is satisfied, false otherwise
472
+ **--]]
473
+ t.UDim = t.typeof("UDim")
474
+
475
+ --[[**
476
+ ensures Roblox UDim2 type
477
+
478
+ @param value The value to check against
479
+
480
+ @returns True iff the condition is satisfied, false otherwise
481
+ **--]]
482
+ t.UDim2 = t.typeof("UDim2")
483
+
484
+ --[[**
485
+ ensures Roblox Vector2 type
486
+
487
+ @param value The value to check against
488
+
489
+ @returns True iff the condition is satisfied, false otherwise
490
+ **--]]
491
+ t.Vector2 = t.typeof("Vector2")
492
+
493
+ --[[**
494
+ ensures Roblox Vector2int16 type
495
+
496
+ @param value The value to check against
497
+
498
+ @returns True iff the condition is satisfied, false otherwise
499
+ **--]]
500
+ t.Vector2int16 = t.typeof("Vector2int16")
501
+
502
+ --[[**
503
+ ensures Roblox Vector3 type
504
+
505
+ @param value The value to check against
506
+
507
+ @returns True iff the condition is satisfied, false otherwise
508
+ **--]]
509
+ t.Vector3 = t.typeof("Vector3")
510
+
511
+ --[[**
512
+ ensures Roblox Vector3int16 type
513
+
514
+ @param value The value to check against
515
+
516
+ @returns True iff the condition is satisfied, false otherwise
517
+ **--]]
518
+ t.Vector3int16 = t.typeof("Vector3int16")
519
+
520
+ --[[**
521
+ ensures value is any of the given literal values
522
+
523
+ @param literals The literals to check against
524
+
525
+ @returns A function that will return true if the condition is passed
526
+ **--]]
527
+ function t.literalList(literals)
528
+ -- optimization for primitive types
529
+ local set = {}
530
+ for _, literal in ipairs(literals) do
531
+ set[literal] = true
532
+ end
533
+ return function(value)
534
+ if set[value] then
535
+ return true
536
+ end
537
+ for _, literal in ipairs(literals) do
538
+ if literal == value then
539
+ return true
540
+ end
541
+ end
542
+
543
+ return false, "bad type for literal list"
544
+ end
545
+ end
546
+
547
+ --[[**
548
+ ensures value is a given literal value
549
+
550
+ @param literal The literal to use
551
+
552
+ @returns A function that will return true iff the condition is passed
553
+ **--]]
554
+ function t.literal(...)
555
+ local size = select("#", ...)
556
+ if size == 1 then
557
+ local literal = ...
558
+ return function(value)
559
+ if value ~= literal then
560
+ return false, string.format("expected %s, got %s", tostring(literal), tostring(value))
561
+ end
562
+
563
+ return true
564
+ end
565
+ else
566
+ local literals = {}
567
+ for i = 1, size do
568
+ local value = select(i, ...)
569
+ literals[i] = t.literal(value)
570
+ end
571
+
572
+ return t.unionList(literals)
573
+ end
574
+ end
575
+
576
+ --[[**
577
+ DEPRECATED
578
+ Please use t.literal
579
+ **--]]
580
+ t.exactly = t.literal
581
+
582
+ --[[**
583
+ Returns a t.union of each key in the table as a t.literal
584
+
585
+ @param keyTable The table to get keys from
586
+
587
+ @returns True iff the condition is satisfied, false otherwise
588
+ **--]]
589
+ function t.keyOf(keyTable)
590
+ local keys = {}
591
+ local length = 0
592
+ for key in pairs(keyTable) do
593
+ length = length + 1
594
+ keys[length] = key
595
+ end
596
+
597
+ return t.literal(table.unpack(keys, 1, length))
598
+ end
599
+
600
+ --[[**
601
+ Returns a t.union of each value in the table as a t.literal
602
+
603
+ @param valueTable The table to get values from
604
+
605
+ @returns True iff the condition is satisfied, false otherwise
606
+ **--]]
607
+ function t.valueOf(valueTable)
608
+ local values = {}
609
+ local length = 0
610
+ for _, value in pairs(valueTable) do
611
+ length = length + 1
612
+ values[length] = value
613
+ end
614
+
615
+ return t.literal(table.unpack(values, 1, length))
616
+ end
617
+
618
+ --[[**
619
+ ensures value is an integer
620
+
621
+ @param value The value to check against
622
+
623
+ @returns True iff the condition is satisfied, false otherwise
624
+ **--]]
625
+ function t.integer(value)
626
+ local success, errMsg = t.number(value)
627
+ if not success then
628
+ return false, errMsg or ""
629
+ end
630
+
631
+ if value % 1 == 0 then
632
+ return true
633
+ else
634
+ return false, string.format("integer expected, got %s", value)
635
+ end
636
+ end
637
+
638
+ --[[**
639
+ ensures value is a number where min <= value
640
+
641
+ @param min The minimum to use
642
+
643
+ @returns A function that will return true iff the condition is passed
644
+ **--]]
645
+ function t.numberMin(min)
646
+ return function(value)
647
+ local success, errMsg = t.number(value)
648
+ if not success then
649
+ return false, errMsg or ""
650
+ end
651
+
652
+ if value >= min then
653
+ return true
654
+ else
655
+ return false, string.format("number >= %s expected, got %s", min, value)
656
+ end
657
+ end
658
+ end
659
+
660
+ --[[**
661
+ ensures value is a number where value <= max
662
+
663
+ @param max The maximum to use
664
+
665
+ @returns A function that will return true iff the condition is passed
666
+ **--]]
667
+ function t.numberMax(max)
668
+ return function(value)
669
+ local success, errMsg = t.number(value)
670
+ if not success then
671
+ return false, errMsg
672
+ end
673
+
674
+ if value <= max then
675
+ return true
676
+ else
677
+ return false, string.format("number <= %s expected, got %s", max, value)
678
+ end
679
+ end
680
+ end
681
+
682
+ --[[**
683
+ ensures value is a number where min < value
684
+
685
+ @param min The minimum to use
686
+
687
+ @returns A function that will return true iff the condition is passed
688
+ **--]]
689
+ function t.numberMinExclusive(min)
690
+ return function(value)
691
+ local success, errMsg = t.number(value)
692
+ if not success then
693
+ return false, errMsg or ""
694
+ end
695
+
696
+ if min < value then
697
+ return true
698
+ else
699
+ return false, string.format("number > %s expected, got %s", min, value)
700
+ end
701
+ end
702
+ end
703
+
704
+ --[[**
705
+ ensures value is a number where value < max
706
+
707
+ @param max The maximum to use
708
+
709
+ @returns A function that will return true iff the condition is passed
710
+ **--]]
711
+ function t.numberMaxExclusive(max)
712
+ return function(value)
713
+ local success, errMsg = t.number(value)
714
+ if not success then
715
+ return false, errMsg or ""
716
+ end
717
+
718
+ if value < max then
719
+ return true
720
+ else
721
+ return false, string.format("number < %s expected, got %s", max, value)
722
+ end
723
+ end
724
+ end
725
+
726
+ --[[**
727
+ ensures value is a number where value > 0
728
+
729
+ @returns A function that will return true iff the condition is passed
730
+ **--]]
731
+ t.numberPositive = t.numberMinExclusive(0)
732
+
733
+ --[[**
734
+ ensures value is a number where value < 0
735
+
736
+ @returns A function that will return true iff the condition is passed
737
+ **--]]
738
+ t.numberNegative = t.numberMaxExclusive(0)
739
+
740
+ --[[**
741
+ ensures value is a number where min <= value <= max
742
+
743
+ @param min The minimum to use
744
+ @param max The maximum to use
745
+
746
+ @returns A function that will return true iff the condition is passed
747
+ **--]]
748
+ function t.numberConstrained(min, max)
749
+ assert(t.number(min))
750
+ assert(t.number(max))
751
+ local minCheck = t.numberMin(min)
752
+ local maxCheck = t.numberMax(max)
753
+
754
+ return function(value)
755
+ local minSuccess, minErrMsg = minCheck(value)
756
+ if not minSuccess then
757
+ return false, minErrMsg or ""
758
+ end
759
+
760
+ local maxSuccess, maxErrMsg = maxCheck(value)
761
+ if not maxSuccess then
762
+ return false, maxErrMsg or ""
763
+ end
764
+
765
+ return true
766
+ end
767
+ end
768
+
769
+ --[[**
770
+ ensures value is a number where min < value < max
771
+
772
+ @param min The minimum to use
773
+ @param max The maximum to use
774
+
775
+ @returns A function that will return true iff the condition is passed
776
+ **--]]
777
+ function t.numberConstrainedExclusive(min, max)
778
+ assert(t.number(min))
779
+ assert(t.number(max))
780
+ local minCheck = t.numberMinExclusive(min)
781
+ local maxCheck = t.numberMaxExclusive(max)
782
+
783
+ return function(value)
784
+ local minSuccess, minErrMsg = minCheck(value)
785
+ if not minSuccess then
786
+ return false, minErrMsg or ""
787
+ end
788
+
789
+ local maxSuccess, maxErrMsg = maxCheck(value)
790
+ if not maxSuccess then
791
+ return false, maxErrMsg or ""
792
+ end
793
+
794
+ return true
795
+ end
796
+ end
797
+
798
+ --[[**
799
+ ensures value matches string pattern
800
+
801
+ @param string pattern to check against
802
+
803
+ @returns A function that will return true iff the condition is passed
804
+ **--]]
805
+ function t.match(pattern)
806
+ assert(t.string(pattern))
807
+ return function(value)
808
+ local stringSuccess, stringErrMsg = t.string(value)
809
+ if not stringSuccess then
810
+ return false, stringErrMsg
811
+ end
812
+
813
+ if string.match(value, pattern) == nil then
814
+ return false, string.format("%q failed to match pattern %q", value, pattern)
815
+ end
816
+
817
+ return true
818
+ end
819
+ end
820
+
821
+ --[[**
822
+ ensures value is either nil or passes check
823
+
824
+ @param check The check to use
825
+
826
+ @returns A function that will return true iff the condition is passed
827
+ **--]]
828
+ function t.optional(check)
829
+ assert(t.callback(check))
830
+ return function(value)
831
+ if value == nil then
832
+ return true
833
+ end
834
+
835
+ local success, errMsg = check(value)
836
+ if success then
837
+ return true
838
+ else
839
+ return false, string.format("(optional) %s", errMsg or "")
840
+ end
841
+ end
842
+ end
843
+
844
+ --[[**
845
+ matches given tuple against tuple type definition
846
+
847
+ @param ... The type definition for the tuples
848
+
849
+ @returns A function that will return true iff the condition is passed
850
+ **--]]
851
+ function t.tuple(...)
852
+ local checks = { ... }
853
+ return function(...)
854
+ local args = { ... }
855
+ for i, check in ipairs(checks) do
856
+ local success, errMsg = check(args[i])
857
+ if success == false then
858
+ return false, string.format("Bad tuple index #%s:\n\t%s", i, errMsg or "")
859
+ end
860
+ end
861
+
862
+ return true
863
+ end
864
+ end
865
+
866
+ --[[**
867
+ ensures all keys in given table pass check
868
+
869
+ @param check The function to use to check the keys
870
+
871
+ @returns A function that will return true iff the condition is passed
872
+ **--]]
873
+ function t.keys(check)
874
+ assert(t.callback(check))
875
+ return function(value)
876
+ local tableSuccess, tableErrMsg = t.table(value)
877
+ if tableSuccess == false then
878
+ return false, tableErrMsg or ""
879
+ end
880
+
881
+ for key in pairs(value) do
882
+ local success, errMsg = check(key)
883
+ if success == false then
884
+ return false, string.format("bad key %s:\n\t%s", tostring(key), errMsg or "")
885
+ end
886
+ end
887
+
888
+ return true
889
+ end
890
+ end
891
+
892
+ --[[**
893
+ ensures all values in given table pass check
894
+
895
+ @param check The function to use to check the values
896
+
897
+ @returns A function that will return true iff the condition is passed
898
+ **--]]
899
+ function t.values(check)
900
+ assert(t.callback(check))
901
+ return function(value)
902
+ local tableSuccess, tableErrMsg = t.table(value)
903
+ if tableSuccess == false then
904
+ return false, tableErrMsg or ""
905
+ end
906
+
907
+ for key, val in pairs(value) do
908
+ local success, errMsg = check(val)
909
+ if success == false then
910
+ return false, string.format("bad value for key %s:\n\t%s", tostring(key), errMsg or "")
911
+ end
912
+ end
913
+
914
+ return true
915
+ end
916
+ end
917
+
918
+ --[[**
919
+ ensures value is a table and all keys pass keyCheck and all values pass valueCheck
920
+
921
+ @param keyCheck The function to use to check the keys
922
+ @param valueCheck The function to use to check the values
923
+
924
+ @returns A function that will return true iff the condition is passed
925
+ **--]]
926
+ function t.map(keyCheck, valueCheck)
927
+ assert(t.callback(keyCheck))
928
+ assert(t.callback(valueCheck))
929
+ local keyChecker = t.keys(keyCheck)
930
+ local valueChecker = t.values(valueCheck)
931
+
932
+ return function(value)
933
+ local keySuccess, keyErr = keyChecker(value)
934
+ if not keySuccess then
935
+ return false, keyErr or ""
936
+ end
937
+
938
+ local valueSuccess, valueErr = valueChecker(value)
939
+ if not valueSuccess then
940
+ return false, valueErr or ""
941
+ end
942
+
943
+ return true
944
+ end
945
+ end
946
+
947
+ --[[**
948
+ ensures value is a table and all keys pass valueCheck and all values are true
949
+
950
+ @param valueCheck The function to use to check the values
951
+
952
+ @returns A function that will return true iff the condition is passed
953
+ **--]]
954
+ function t.set(valueCheck)
955
+ return t.map(valueCheck, t.literal(true))
956
+ end
957
+
958
+ do
959
+ local arrayKeysCheck = t.keys(t.integer)
960
+ --[[**
961
+ ensures value is an array and all values of the array match check
962
+
963
+ @param check The check to compare all values with
964
+
965
+ @returns A function that will return true iff the condition is passed
966
+ **--]]
967
+ function t.array(check)
968
+ assert(t.callback(check))
969
+ local valuesCheck = t.values(check)
970
+
971
+ return function(value)
972
+ local keySuccess, keyErrMsg = arrayKeysCheck(value)
973
+ if keySuccess == false then
974
+ return false, string.format("[array] %s", keyErrMsg or "")
975
+ end
976
+
977
+ -- # is unreliable for sparse arrays
978
+ -- Count upwards using ipairs to avoid false positives from the behavior of #
979
+ local arraySize = 0
980
+
981
+ for _ in ipairs(value) do
982
+ arraySize = arraySize + 1
983
+ end
984
+
985
+ for key in pairs(value) do
986
+ if key < 1 or key > arraySize then
987
+ return false, string.format("[array] key %s must be sequential", tostring(key))
988
+ end
989
+ end
990
+
991
+ local valueSuccess, valueErrMsg = valuesCheck(value)
992
+ if not valueSuccess then
993
+ return false, string.format("[array] %s", valueErrMsg or "")
994
+ end
995
+
996
+ return true
997
+ end
998
+ end
999
+
1000
+ --[[**
1001
+ ensures value is an array of a strict makeup and size
1002
+
1003
+ @param check The check to compare all values with
1004
+
1005
+ @returns A function that will return true iff the condition is passed
1006
+ **--]]
1007
+ function t.strictArray(...)
1008
+ local valueTypes = { ... }
1009
+ assert(t.array(t.callback)(valueTypes))
1010
+
1011
+ return function(value)
1012
+ local keySuccess, keyErrMsg = arrayKeysCheck(value)
1013
+ if keySuccess == false then
1014
+ return false, string.format("[strictArray] %s", keyErrMsg or "")
1015
+ end
1016
+
1017
+ -- If there's more than the set array size, disallow
1018
+ if #valueTypes < #value then
1019
+ return false, string.format("[strictArray] Array size exceeds limit of %d", #valueTypes)
1020
+ end
1021
+
1022
+ for idx, typeFn in pairs(valueTypes) do
1023
+ local typeSuccess, typeErrMsg = typeFn(value[idx])
1024
+ if not typeSuccess then
1025
+ return false, string.format("[strictArray] Array index #%d - %s", idx, typeErrMsg)
1026
+ end
1027
+ end
1028
+
1029
+ return true
1030
+ end
1031
+ end
1032
+ end
1033
+
1034
+ do
1035
+ local callbackArray = t.array(t.callback)
1036
+ --[[**
1037
+ creates a union type
1038
+
1039
+ @param checks The checks to union
1040
+
1041
+ @returns A function that will return true iff the condition is passed
1042
+ **--]]
1043
+ function t.unionList(checks)
1044
+ assert(callbackArray(checks))
1045
+
1046
+ return function(value)
1047
+ for _, check in ipairs(checks) do
1048
+ if check(value) then
1049
+ return true
1050
+ end
1051
+ end
1052
+
1053
+ return false, "bad type for union"
1054
+ end
1055
+ end
1056
+
1057
+ --[[**
1058
+ creates a union type
1059
+
1060
+ @param ... The checks to union
1061
+
1062
+ @returns A function that will return true iff the condition is passed
1063
+ **--]]
1064
+ function t.union(...)
1065
+ return t.unionList({ ... })
1066
+ end
1067
+
1068
+ --[[**
1069
+ Alias for t.union
1070
+ **--]]
1071
+ t.some = t.union
1072
+
1073
+ --[[**
1074
+ creates an intersection type
1075
+
1076
+ @param checks The checks to intersect
1077
+
1078
+ @returns A function that will return true iff the condition is passed
1079
+ **--]]
1080
+ function t.intersectionList(checks)
1081
+ assert(callbackArray(checks))
1082
+
1083
+ return function(value)
1084
+ for _, check in ipairs(checks) do
1085
+ local success, errMsg = check(value)
1086
+ if not success then
1087
+ return false, errMsg or ""
1088
+ end
1089
+ end
1090
+
1091
+ return true
1092
+ end
1093
+ end
1094
+
1095
+ --[[**
1096
+ creates an intersection type
1097
+
1098
+ @param ... The checks to intersect
1099
+
1100
+ @returns A function that will return true iff the condition is passed
1101
+ **--]]
1102
+ function t.intersection(...)
1103
+ return t.intersectionList({ ... })
1104
+ end
1105
+
1106
+ --[[**
1107
+ Alias for t.intersection
1108
+ **--]]
1109
+ t.every = t.intersection
1110
+ end
1111
+
1112
+ do
1113
+ local checkInterface = t.map(t.any, t.callback)
1114
+ --[[**
1115
+ ensures value matches given interface definition
1116
+
1117
+ @param checkTable The interface definition
1118
+
1119
+ @returns A function that will return true iff the condition is passed
1120
+ **--]]
1121
+ function t.interface(checkTable)
1122
+ assert(checkInterface(checkTable))
1123
+ return function(value)
1124
+ local tableSuccess, tableErrMsg = t.table(value)
1125
+ if tableSuccess == false then
1126
+ return false, tableErrMsg or ""
1127
+ end
1128
+
1129
+ for key, check in pairs(checkTable) do
1130
+ local success, errMsg = check(value[key])
1131
+ if success == false then
1132
+ return false, string.format("[interface] bad value for %s:\n\t%s", tostring(key), errMsg or "")
1133
+ end
1134
+ end
1135
+
1136
+ return true
1137
+ end
1138
+ end
1139
+
1140
+ --[[**
1141
+ ensures value matches given interface definition strictly
1142
+
1143
+ @param checkTable The interface definition
1144
+
1145
+ @returns A function that will return true iff the condition is passed
1146
+ **--]]
1147
+ function t.strictInterface(checkTable)
1148
+ assert(checkInterface(checkTable))
1149
+ return function(value)
1150
+ local tableSuccess, tableErrMsg = t.table(value)
1151
+ if tableSuccess == false then
1152
+ return false, tableErrMsg or ""
1153
+ end
1154
+
1155
+ for key, check in pairs(checkTable) do
1156
+ local success, errMsg = check(value[key])
1157
+ if success == false then
1158
+ return false, string.format("[interface] bad value for %s:\n\t%s", tostring(key), errMsg or "")
1159
+ end
1160
+ end
1161
+
1162
+ for key in pairs(value) do
1163
+ if not checkTable[key] then
1164
+ return false, string.format("[interface] unexpected field %q", tostring(key))
1165
+ end
1166
+ end
1167
+
1168
+ return true
1169
+ end
1170
+ end
1171
+ end
1172
+
1173
+ --[[**
1174
+ ensure value is an Instance and it's ClassName matches the given ClassName
1175
+
1176
+ @param className The class name to check for
1177
+
1178
+ @returns A function that will return true iff the condition is passed
1179
+ **--]]
1180
+ function t.instanceOf(className, childTable)
1181
+ assert(t.string(className))
1182
+
1183
+ local childrenCheck
1184
+ if childTable ~= nil then
1185
+ childrenCheck = t.children(childTable)
1186
+ end
1187
+
1188
+ return function(value)
1189
+ local instanceSuccess, instanceErrMsg = t.Instance(value)
1190
+ if not instanceSuccess then
1191
+ return false, instanceErrMsg or ""
1192
+ end
1193
+
1194
+ if value.ClassName ~= className then
1195
+ return false, string.format("%s expected, got %s", className, value.ClassName)
1196
+ end
1197
+
1198
+ if childrenCheck then
1199
+ local childrenSuccess, childrenErrMsg = childrenCheck(value)
1200
+ if not childrenSuccess then
1201
+ return false, childrenErrMsg
1202
+ end
1203
+ end
1204
+
1205
+ return true
1206
+ end
1207
+ end
1208
+
1209
+ t.instance = t.instanceOf
1210
+
1211
+ --[[**
1212
+ ensure value is an Instance and it's ClassName matches the given ClassName by an IsA comparison
1213
+
1214
+ @param className The class name to check for
1215
+
1216
+ @returns A function that will return true iff the condition is passed
1217
+ **--]]
1218
+ function t.instanceIsA(className, childTable)
1219
+ assert(t.string(className))
1220
+
1221
+ local childrenCheck
1222
+ if childTable ~= nil then
1223
+ childrenCheck = t.children(childTable)
1224
+ end
1225
+
1226
+ return function(value)
1227
+ local instanceSuccess, instanceErrMsg = t.Instance(value)
1228
+ if not instanceSuccess then
1229
+ return false, instanceErrMsg or ""
1230
+ end
1231
+
1232
+ if not value:IsA(className) then
1233
+ return false, string.format("%s expected, got %s", className, value.ClassName)
1234
+ end
1235
+
1236
+ if childrenCheck then
1237
+ local childrenSuccess, childrenErrMsg = childrenCheck(value)
1238
+ if not childrenSuccess then
1239
+ return false, childrenErrMsg
1240
+ end
1241
+ end
1242
+
1243
+ return true
1244
+ end
1245
+ end
1246
+
1247
+ --[[**
1248
+ ensures value is an enum of the correct type
1249
+
1250
+ @param enum The enum to check
1251
+
1252
+ @returns A function that will return true iff the condition is passed
1253
+ **--]]
1254
+ function t.enum(enum)
1255
+ assert(t.Enum(enum))
1256
+ return function(value)
1257
+ local enumItemSuccess, enumItemErrMsg = t.EnumItem(value)
1258
+ if not enumItemSuccess then
1259
+ return false, enumItemErrMsg
1260
+ end
1261
+
1262
+ if value.EnumType == enum then
1263
+ return true
1264
+ else
1265
+ return false, string.format("enum of %s expected, got enum of %s", tostring(enum), tostring(value.EnumType))
1266
+ end
1267
+ end
1268
+ end
1269
+
1270
+ do
1271
+ local checkWrap = t.tuple(t.callback, t.callback)
1272
+
1273
+ --[[**
1274
+ wraps a callback in an assert with checkArgs
1275
+
1276
+ @param callback The function to wrap
1277
+ @param checkArgs The function to use to check arguments in the assert
1278
+
1279
+ @returns A function that first asserts using checkArgs and then calls callback
1280
+ **--]]
1281
+ function t.wrap(callback, checkArgs)
1282
+ assert(checkWrap(callback, checkArgs))
1283
+ return function(...)
1284
+ assert(checkArgs(...))
1285
+ return callback(...)
1286
+ end
1287
+ end
1288
+ end
1289
+
1290
+ --[[**
1291
+ asserts a given check
1292
+
1293
+ @param check The function to wrap with an assert
1294
+
1295
+ @returns A function that simply wraps the given check in an assert
1296
+ **--]]
1297
+ function t.strict(check)
1298
+ return function(...)
1299
+ assert(check(...))
1300
+ end
1301
+ end
1302
+
1303
+ do
1304
+ local checkChildren = t.map(t.string, t.callback)
1305
+
1306
+ --[[**
1307
+ Takes a table where keys are child names and values are functions to check the children against.
1308
+ Pass an instance tree into the function.
1309
+ If at least one child passes each check, the overall check passes.
1310
+
1311
+ Warning! If you pass in a tree with more than one child of the same name, this function will always return false
1312
+
1313
+ @param checkTable The table to check against
1314
+
1315
+ @returns A function that checks an instance tree
1316
+ **--]]
1317
+ function t.children(checkTable)
1318
+ assert(checkChildren(checkTable))
1319
+
1320
+ return function(value)
1321
+ local instanceSuccess, instanceErrMsg = t.Instance(value)
1322
+ if not instanceSuccess then
1323
+ return false, instanceErrMsg or ""
1324
+ end
1325
+
1326
+ local childrenByName = {}
1327
+ for _, child in ipairs(value:GetChildren()) do
1328
+ local name = child.Name
1329
+ if checkTable[name] then
1330
+ if childrenByName[name] then
1331
+ return false, string.format("Cannot process multiple children with the same name %q", name)
1332
+ end
1333
+
1334
+ childrenByName[name] = child
1335
+ end
1336
+ end
1337
+
1338
+ for name, check in pairs(checkTable) do
1339
+ local success, errMsg = check(childrenByName[name])
1340
+ if not success then
1341
+ return false, string.format("[%s.%s] %s", value:GetFullName(), name, errMsg or "")
1342
+ end
1343
+ end
1344
+
1345
+ return true
1346
+ end
1347
+ end
1348
+ end
1349
+
1350
+ return t