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
@@ -0,0 +1,489 @@
1
+ -- Option
2
+ -- Stephen Leitnick
3
+ -- August 28, 2020
4
+
5
+ --[[
6
+
7
+ MatchTable {
8
+ Some: (value: any) -> any
9
+ None: () -> any
10
+ }
11
+
12
+ CONSTRUCTORS:
13
+
14
+ Option.Some(anyNonNilValue): Option<any>
15
+ Option.Wrap(anyValue): Option<any>
16
+
17
+
18
+ STATIC FIELDS:
19
+
20
+ Option.None: Option<None>
21
+
22
+
23
+ STATIC METHODS:
24
+
25
+ Option.Is(obj): boolean
26
+
27
+
28
+ METHODS:
29
+
30
+ opt:Match(): (matches: MatchTable) -> any
31
+ opt:IsSome(): boolean
32
+ opt:IsNone(): boolean
33
+ opt:Unwrap(): any
34
+ opt:Expect(errMsg: string): any
35
+ opt:ExpectNone(errMsg: string): void
36
+ opt:UnwrapOr(default: any): any
37
+ opt:UnwrapOrElse(default: () -> any): any
38
+ opt:And(opt2: Option<any>): Option<any>
39
+ opt:AndThen(predicate: (unwrapped: any) -> Option<any>): Option<any>
40
+ opt:Or(opt2: Option<any>): Option<any>
41
+ opt:OrElse(orElseFunc: () -> Option<any>): Option<any>
42
+ opt:XOr(opt2: Option<any>): Option<any>
43
+ opt:Contains(value: any): boolean
44
+
45
+ --------------------------------------------------------------------
46
+
47
+ Options are useful for handling nil-value cases. Any time that an
48
+ operation might return nil, it is useful to instead return an
49
+ Option, which will indicate that the value might be nil, and should
50
+ be explicitly checked before using the value. This will help
51
+ prevent common bugs caused by nil values that can fail silently.
52
+
53
+
54
+ Example:
55
+
56
+ local result1 = Option.Some(32)
57
+ local result2 = Option.Some(nil)
58
+ local result3 = Option.Some("Hi")
59
+ local result4 = Option.Some(nil)
60
+ local result5 = Option.None
61
+
62
+ -- Use 'Match' to match if the value is Some or None:
63
+ result1:Match {
64
+ Some = function(value) print(value) end;
65
+ None = function() print("No value") end;
66
+ }
67
+
68
+ -- Raw check:
69
+ if result2:IsSome() then
70
+ local value = result2:Unwrap() -- Explicitly call Unwrap
71
+ print("Value of result2:", value)
72
+ end
73
+
74
+ if result3:IsNone() then
75
+ print("No result for result3")
76
+ end
77
+
78
+ -- Bad, will throw error bc result4 is none:
79
+ local value = result4:Unwrap()
80
+
81
+ --]]
82
+
83
+ export type MatchTable<T> = {
84
+ Some: (value: T) -> any,
85
+ None: () -> any,
86
+ }
87
+
88
+ export type MatchFn<T> = (matches: MatchTable<T>) -> any
89
+
90
+ export type DefaultFn<T> = () -> T
91
+
92
+ export type AndThenFn<T> = (value: T) -> Option<T>
93
+
94
+ export type OrElseFn<T> = () -> Option<T>
95
+
96
+ export type Option<T> = typeof(setmetatable(
97
+ {} :: {
98
+ Match: (self: Option<T>) -> MatchFn<T>,
99
+ IsSome: (self: Option<T>) -> boolean,
100
+ IsNone: (self: Option<T>) -> boolean,
101
+ Contains: (self: Option<T>, value: T) -> boolean,
102
+ Unwrap: (self: Option<T>) -> T,
103
+ Expect: (self: Option<T>, errMsg: string) -> T,
104
+ ExpectNone: (self: Option<T>, errMsg: string) -> nil,
105
+ UnwrapOr: (self: Option<T>, default: T) -> T,
106
+ UnwrapOrElse: (self: Option<T>, defaultFn: DefaultFn<T>) -> T,
107
+ And: (self: Option<T>, opt2: Option<T>) -> Option<T>,
108
+ AndThen: (self: Option<T>, predicate: AndThenFn<T>) -> Option<T>,
109
+ Or: (self: Option<T>, opt2: Option<T>) -> Option<T>,
110
+ OrElse: (self: Option<T>, orElseFunc: OrElseFn<T>) -> Option<T>,
111
+ XOr: (self: Option<T>, opt2: Option<T>) -> Option<T>,
112
+ },
113
+ {} :: {
114
+ __index: Option<T>,
115
+ }
116
+ ))
117
+
118
+ local CLASSNAME = "Option"
119
+
120
+ --[=[
121
+ @class Option
122
+
123
+ Represents an optional value in Lua. This is useful to avoid `nil` bugs, which can
124
+ go silently undetected within code and cause hidden or hard-to-find bugs.
125
+ ]=]
126
+ local Option = {}
127
+ Option.__index = Option
128
+
129
+ function Option._new(value)
130
+ local self = setmetatable({
131
+ ClassName = CLASSNAME,
132
+ _v = value,
133
+ _s = (value ~= nil),
134
+ }, Option)
135
+ return self
136
+ end
137
+
138
+ --[=[
139
+ @param value T
140
+ @return Option<T>
141
+
142
+ Creates an Option instance with the given value. Throws an error
143
+ if the given value is `nil`.
144
+ ]=]
145
+ function Option.Some(value)
146
+ assert(value ~= nil, "Option.Some() value cannot be nil")
147
+ return Option._new(value)
148
+ end
149
+
150
+ --[=[
151
+ @param value T
152
+ @return Option<T> | Option<None>
153
+
154
+ Safely wraps the given value as an option. If the
155
+ value is `nil`, returns `Option.None`, otherwise
156
+ returns `Option.Some(value)`.
157
+ ]=]
158
+ function Option.Wrap(value)
159
+ if value == nil then
160
+ return Option.None
161
+ else
162
+ return Option.Some(value)
163
+ end
164
+ end
165
+
166
+ --[=[
167
+ @param obj any
168
+ @return boolean
169
+ Returns `true` if `obj` is an Option.
170
+ ]=]
171
+ function Option.Is(obj)
172
+ return type(obj) == "table" and getmetatable(obj) == Option
173
+ end
174
+
175
+ --[=[
176
+ @param obj any
177
+ Throws an error if `obj` is not an Option.
178
+ ]=]
179
+ function Option.Assert(obj)
180
+ assert(Option.Is(obj), "Result was not of type Option")
181
+ end
182
+
183
+ --[=[
184
+ @param data table
185
+ @return Option
186
+ Deserializes the data into an Option. This data should have come from
187
+ the `option:Serialize()` method.
188
+ ]=]
189
+ function Option.Deserialize(data) -- type data = {ClassName: string, Value: any}
190
+ assert(type(data) == "table" and data.ClassName == CLASSNAME, "Invalid data for deserializing Option")
191
+ return data.Value == nil and Option.None or Option.Some(data.Value)
192
+ end
193
+
194
+ --[=[
195
+ @return table
196
+ Returns a serialized version of the option.
197
+ ]=]
198
+ function Option:Serialize()
199
+ return {
200
+ ClassName = self.ClassName,
201
+ Value = self._v,
202
+ }
203
+ end
204
+
205
+ --[=[
206
+ @param matches {Some: (value: any) -> any, None: () -> any}
207
+ @return any
208
+
209
+ Matches against the option.
210
+
211
+ ```lua
212
+ local opt = Option.Some(32)
213
+ opt:Match {
214
+ Some = function(num) print("Number", num) end,
215
+ None = function() print("No value") end,
216
+ }
217
+ ```
218
+ ]=]
219
+ function Option:Match(matches)
220
+ local onSome = matches.Some
221
+ local onNone = matches.None
222
+ assert(type(onSome) == "function", "Missing 'Some' match")
223
+ assert(type(onNone) == "function", "Missing 'None' match")
224
+ if self:IsSome() then
225
+ return onSome(self:Unwrap())
226
+ else
227
+ return onNone()
228
+ end
229
+ end
230
+
231
+ --[=[
232
+ @return boolean
233
+ Returns `true` if the option has a value.
234
+ ]=]
235
+ function Option:IsSome()
236
+ return self._s
237
+ end
238
+
239
+ --[=[
240
+ @return boolean
241
+ Returns `true` if the option is None.
242
+ ]=]
243
+ function Option:IsNone()
244
+ return not self._s
245
+ end
246
+
247
+ --[=[
248
+ @param msg string
249
+ @return value: any
250
+ Unwraps the value in the option, otherwise throws an error with `msg` as the error message.
251
+ ```lua
252
+ local opt = Option.Some(10)
253
+ print(opt:Expect("No number")) -> 10
254
+ print(Option.None:Expect("No number")) -- Throws an error "No number"
255
+ ```
256
+ ]=]
257
+ function Option:Expect(msg)
258
+ assert(self:IsSome(), msg)
259
+ return self._v
260
+ end
261
+
262
+ --[=[
263
+ @param msg string
264
+ Throws an error with `msg` as the error message if the value is _not_ None.
265
+ ]=]
266
+ function Option:ExpectNone(msg)
267
+ assert(self:IsNone(), msg)
268
+ end
269
+
270
+ --[=[
271
+ @return value: any
272
+ Returns the value in the option, or throws an error if the option is None.
273
+ ]=]
274
+ function Option:Unwrap()
275
+ return self:Expect("Cannot unwrap option of None type")
276
+ end
277
+
278
+ --[=[
279
+ @param default any
280
+ @return value: any
281
+ If the option holds a value, returns the value. Otherwise, returns `default`.
282
+ ]=]
283
+ function Option:UnwrapOr(default)
284
+ if self:IsSome() then
285
+ return self:Unwrap()
286
+ else
287
+ return default
288
+ end
289
+ end
290
+
291
+ --[=[
292
+ @param defaultFn () -> any
293
+ @return value: any
294
+ If the option holds a value, returns the value. Otherwise, returns the
295
+ result of the `defaultFn` function.
296
+ ]=]
297
+ function Option:UnwrapOrElse(defaultFn)
298
+ if self:IsSome() then
299
+ return self:Unwrap()
300
+ else
301
+ return defaultFn()
302
+ end
303
+ end
304
+
305
+ --[=[
306
+ @param optionB Option
307
+ @return Option
308
+ Returns `optionB` if the calling option has a value,
309
+ otherwise returns None.
310
+
311
+ ```lua
312
+ local optionA = Option.Some(32)
313
+ local optionB = Option.Some(64)
314
+ local opt = optionA:And(optionB)
315
+ -- opt == optionB
316
+
317
+ local optionA = Option.None
318
+ local optionB = Option.Some(64)
319
+ local opt = optionA:And(optionB)
320
+ -- opt == Option.None
321
+ ```
322
+ ]=]
323
+ function Option:And(optionB)
324
+ if self:IsSome() then
325
+ return optionB
326
+ else
327
+ return Option.None
328
+ end
329
+ end
330
+
331
+ --[=[
332
+ @param andThenFn (value: any) -> Option
333
+ @return value: Option
334
+ If the option holds a value, then the `andThenFn`
335
+ function is called with the held value of the option,
336
+ and then the resultant Option returned by the `andThenFn`
337
+ is returned. Otherwise, None is returned.
338
+
339
+ ```lua
340
+ local optA = Option.Some(32)
341
+ local optB = optA:AndThen(function(num)
342
+ return Option.Some(num * 2)
343
+ end)
344
+ print(optB:Expect("Expected number")) --> 64
345
+ ```
346
+ ]=]
347
+ function Option:AndThen(andThenFn)
348
+ if self:IsSome() then
349
+ local result = andThenFn(self:Unwrap())
350
+ Option.Assert(result)
351
+ return result
352
+ else
353
+ return Option.None
354
+ end
355
+ end
356
+
357
+ --[=[
358
+ @param optionB Option
359
+ @return Option
360
+ If caller has a value, returns itself. Otherwise, returns `optionB`.
361
+ ]=]
362
+ function Option:Or(optionB)
363
+ if self:IsSome() then
364
+ return self
365
+ else
366
+ return optionB
367
+ end
368
+ end
369
+
370
+ --[=[
371
+ @param orElseFn () -> Option
372
+ @return Option
373
+ If caller has a value, returns itself. Otherwise, returns the
374
+ option generated by the `orElseFn` function.
375
+ ]=]
376
+ function Option:OrElse(orElseFn)
377
+ if self:IsSome() then
378
+ return self
379
+ else
380
+ local result = orElseFn()
381
+ Option.Assert(result)
382
+ return result
383
+ end
384
+ end
385
+
386
+ --[=[
387
+ @param optionB Option
388
+ @return Option
389
+ If both `self` and `optionB` have values _or_ both don't have a value,
390
+ then this returns None. Otherwise, it returns the option that does have
391
+ a value.
392
+ ]=]
393
+ function Option:XOr(optionB)
394
+ local someOptA = self:IsSome()
395
+ local someOptB = optionB:IsSome()
396
+ if someOptA == someOptB then
397
+ return Option.None
398
+ elseif someOptA then
399
+ return self
400
+ else
401
+ return optionB
402
+ end
403
+ end
404
+
405
+ --[=[
406
+ @param predicate (value: any) -> boolean
407
+ @return Option
408
+ Returns `self` if this option has a value and the predicate returns `true.
409
+ Otherwise, returns None.
410
+ ]=]
411
+ function Option:Filter(predicate)
412
+ if self:IsNone() or not predicate(self._v) then
413
+ return Option.None
414
+ else
415
+ return self
416
+ end
417
+ end
418
+
419
+ --[=[
420
+ @param value any
421
+ @return boolean
422
+ Returns `true` if this option contains `value`.
423
+ ]=]
424
+ function Option:Contains(value)
425
+ return self:IsSome() and self._v == value
426
+ end
427
+
428
+ --[=[
429
+ @return string
430
+ Metamethod to transform the option into a string.
431
+ ```lua
432
+ local optA = Option.Some(64)
433
+ local optB = Option.None
434
+ print(optA) --> Option<number>
435
+ print(optB) --> Option<None>
436
+ ```
437
+ ]=]
438
+ function Option:__tostring()
439
+ if self:IsSome() then
440
+ return ("Option<" .. typeof(self._v) .. ">")
441
+ else
442
+ return "Option<None>"
443
+ end
444
+ end
445
+
446
+ --[=[
447
+ @return boolean
448
+ @param opt Option
449
+ Metamethod to check equality between two options. Returns `true` if both
450
+ options hold the same value _or_ both options are None.
451
+ ```lua
452
+ local o1 = Option.Some(32)
453
+ local o2 = Option.Some(32)
454
+ local o3 = Option.Some(64)
455
+ local o4 = Option.None
456
+ local o5 = Option.None
457
+
458
+ print(o1 == o2) --> true
459
+ print(o1 == o3) --> false
460
+ print(o1 == o4) --> false
461
+ print(o4 == o5) --> true
462
+ ```
463
+ ]=]
464
+ function Option:__eq(opt)
465
+ if Option.Is(opt) then
466
+ if self:IsSome() and opt:IsSome() then
467
+ return (self:Unwrap() == opt:Unwrap())
468
+ elseif self:IsNone() and opt:IsNone() then
469
+ return true
470
+ end
471
+ end
472
+ return false
473
+ end
474
+
475
+ --[=[
476
+ @prop None Option<None>
477
+ @within Option
478
+ Represents no value.
479
+ ]=]
480
+ Option.None = Option._new()
481
+
482
+ return (Option :: any) :: {
483
+ Some: <T>(value: T) -> Option<T>,
484
+ Wrap: <T>(value: T?) -> Option<T>,
485
+
486
+ Is: (obj: any) -> boolean,
487
+
488
+ None: Option<any>,
489
+ }