@trioforge/crucible 0.0.0-stage → 0.2.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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/client/package.json +4 -0
  3. package/emit/package.json +4 -0
  4. package/out/all.d.ts +7 -0
  5. package/out/all.luau +2 -0
  6. package/out/attribute.d.ts +7 -0
  7. package/out/attribute.luau +7 -0
  8. package/out/client/index.d.ts +10 -0
  9. package/out/client/init.luau +55 -0
  10. package/out/configs.d.ts +37 -0
  11. package/out/configs.luau +46 -0
  12. package/out/crucible-behaviour.d.ts +16 -0
  13. package/out/crucible-behaviour.luau +78 -0
  14. package/out/crucible-object.d.ts +10 -0
  15. package/out/crucible-object.luau +69 -0
  16. package/out/data.d.ts +224 -0
  17. package/out/data.luau +97 -0
  18. package/out/emit/configs.d.ts +4 -0
  19. package/out/emit/configs.luau +22 -0
  20. package/out/emit/data.d.ts +6 -0
  21. package/out/emit/data.luau +19 -0
  22. package/out/emit/index.d.ts +45 -0
  23. package/out/emit/init.luau +101 -0
  24. package/out/emit/network.d.ts +6 -0
  25. package/out/emit/network.luau +36 -0
  26. package/out/emit/replicated.d.ts +4 -0
  27. package/out/emit/replicated.luau +13 -0
  28. package/out/index.d.ts +20 -0
  29. package/out/init.luau +34 -0
  30. package/out/inject.d.ts +1 -0
  31. package/out/inject.luau +7 -0
  32. package/out/internal/binding.d.ts +1 -0
  33. package/out/internal/binding.luau +615 -0
  34. package/out/internal/boot.d.ts +1 -0
  35. package/out/internal/boot.luau +562 -0
  36. package/out/internal/configs/limits.d.ts +10 -0
  37. package/out/internal/configs/limits.luau +25 -0
  38. package/out/internal/configs/port.d.ts +29 -0
  39. package/out/internal/configs/port.luau +99 -0
  40. package/out/internal/configs/runtime.d.ts +21 -0
  41. package/out/internal/configs/runtime.luau +981 -0
  42. package/out/internal/construction-claim.d.ts +1 -0
  43. package/out/internal/construction-claim.luau +26 -0
  44. package/out/internal/data/admission.d.ts +1 -0
  45. package/out/internal/data/admission.luau +673 -0
  46. package/out/internal/data/declarations.d.ts +1 -0
  47. package/out/internal/data/declarations.luau +384 -0
  48. package/out/internal/data/envelope.d.ts +1 -0
  49. package/out/internal/data/envelope.luau +318 -0
  50. package/out/internal/data/handles.d.ts +1 -0
  51. package/out/internal/data/handles.luau +255 -0
  52. package/out/internal/data/inbox-transforms.d.ts +1 -0
  53. package/out/internal/data/inbox-transforms.luau +458 -0
  54. package/out/internal/data/inbox.d.ts +1 -0
  55. package/out/internal/data/inbox.luau +437 -0
  56. package/out/internal/data/lease.d.ts +1 -0
  57. package/out/internal/data/lease.luau +304 -0
  58. package/out/internal/data/limits.d.ts +1 -0
  59. package/out/internal/data/limits.luau +234 -0
  60. package/out/internal/data/messages.d.ts +1 -0
  61. package/out/internal/data/messages.luau +69 -0
  62. package/out/internal/data/operation-id.d.ts +1 -0
  63. package/out/internal/data/operation-id.luau +61 -0
  64. package/out/internal/data/paths.d.ts +2 -0
  65. package/out/internal/data/paths.luau +323 -0
  66. package/out/internal/data/port.d.ts +1 -0
  67. package/out/internal/data/port.luau +290 -0
  68. package/out/internal/data/profiles.d.ts +1 -0
  69. package/out/internal/data/profiles.luau +862 -0
  70. package/out/internal/data/receipts.d.ts +1 -0
  71. package/out/internal/data/receipts.luau +190 -0
  72. package/out/internal/data/record-bindings.d.ts +1 -0
  73. package/out/internal/data/record-bindings.luau +92 -0
  74. package/out/internal/data/record-declarations.d.ts +1 -0
  75. package/out/internal/data/record-declarations.luau +140 -0
  76. package/out/internal/data/records.d.ts +1 -0
  77. package/out/internal/data/records.luau +400 -0
  78. package/out/internal/data/runtime.d.ts +1 -0
  79. package/out/internal/data/runtime.luau +918 -0
  80. package/out/internal/data/scheduler.d.ts +1 -0
  81. package/out/internal/data/scheduler.luau +507 -0
  82. package/out/internal/data/session.d.ts +1 -0
  83. package/out/internal/data/session.luau +234 -0
  84. package/out/internal/data/shutdown.d.ts +1 -0
  85. package/out/internal/data/shutdown.luau +91 -0
  86. package/out/internal/data/waiters.d.ts +1 -0
  87. package/out/internal/data/waiters.luau +65 -0
  88. package/out/internal/dense-list.d.ts +1 -0
  89. package/out/internal/dense-list.luau +155 -0
  90. package/out/internal/diagnostics.d.ts +1 -0
  91. package/out/internal/diagnostics.luau +29 -0
  92. package/out/internal/hooks.d.ts +1 -0
  93. package/out/internal/hooks.luau +53 -0
  94. package/out/internal/implementers.d.ts +1 -0
  95. package/out/internal/implementers.luau +119 -0
  96. package/out/internal/lifecycle.d.ts +1 -0
  97. package/out/internal/lifecycle.luau +912 -0
  98. package/out/internal/log-output.d.ts +1 -0
  99. package/out/internal/log-output.luau +106 -0
  100. package/out/internal/network/catalog.d.ts +26 -0
  101. package/out/internal/network/catalog.luau +182 -0
  102. package/out/internal/network/claims.d.ts +1 -0
  103. package/out/internal/network/claims.luau +154 -0
  104. package/out/internal/network/client-session.d.ts +1 -0
  105. package/out/internal/network/client-session.luau +403 -0
  106. package/out/internal/network/codec.d.ts +63 -0
  107. package/out/internal/network/codec.luau +1183 -0
  108. package/out/internal/network/envelope.d.ts +1 -0
  109. package/out/internal/network/envelope.luau +247 -0
  110. package/out/internal/network/limits.d.ts +26 -0
  111. package/out/internal/network/limits.luau +55 -0
  112. package/out/internal/network/port.d.ts +1 -0
  113. package/out/internal/network/port.luau +19 -0
  114. package/out/internal/network/roblox-network-port.d.ts +1 -0
  115. package/out/internal/network/roblox-network-port.luau +105 -0
  116. package/out/internal/network/schema.d.ts +72 -0
  117. package/out/internal/network/schema.luau +386 -0
  118. package/out/internal/network/server-session.d.ts +1 -0
  119. package/out/internal/network/server-session.luau +393 -0
  120. package/out/internal/network/session.d.ts +1 -0
  121. package/out/internal/network/session.luau +266 -0
  122. package/out/internal/port.d.ts +1 -0
  123. package/out/internal/port.luau +12 -0
  124. package/out/internal/reactive/context.d.ts +1 -0
  125. package/out/internal/reactive/context.luau +149 -0
  126. package/out/internal/reactive/flush.d.ts +1 -0
  127. package/out/internal/reactive/flush.luau +355 -0
  128. package/out/internal/reactive/graph.d.ts +1 -0
  129. package/out/internal/reactive/graph.luau +626 -0
  130. package/out/internal/reactive/limits.d.ts +1 -0
  131. package/out/internal/reactive/limits.luau +54 -0
  132. package/out/internal/reactive/ownership.d.ts +1 -0
  133. package/out/internal/reactive/ownership.luau +626 -0
  134. package/out/internal/registry.d.ts +1 -0
  135. package/out/internal/registry.luau +455 -0
  136. package/out/internal/roblox-port.d.ts +1 -0
  137. package/out/internal/roblox-port.luau +117 -0
  138. package/out/internal/runner.d.ts +1 -0
  139. package/out/internal/runner.luau +86 -0
  140. package/out/internal/scheduler.d.ts +1 -0
  141. package/out/internal/scheduler.luau +207 -0
  142. package/out/internal/state.d.ts +1 -0
  143. package/out/internal/state.luau +41 -0
  144. package/out/internal/sync/client-sync.d.ts +1 -0
  145. package/out/internal/sync/client-sync.luau +157 -0
  146. package/out/internal/sync/declarations.d.ts +1 -0
  147. package/out/internal/sync/declarations.luau +276 -0
  148. package/out/internal/sync/frame.d.ts +1 -0
  149. package/out/internal/sync/frame.luau +91 -0
  150. package/out/internal/sync/server-sync.d.ts +1 -0
  151. package/out/internal/sync/server-sync.luau +502 -0
  152. package/out/internal/sync/values.d.ts +1 -0
  153. package/out/internal/sync/values.luau +930 -0
  154. package/out/log-level.d.ts +7 -0
  155. package/out/log-level.luau +21 -0
  156. package/out/logging.d.ts +34 -0
  157. package/out/logging.luau +233 -0
  158. package/out/network.d.ts +66 -0
  159. package/out/network.luau +24 -0
  160. package/out/reactive.d.ts +76 -0
  161. package/out/reactive.luau +136 -0
  162. package/out/replicated.d.ts +38 -0
  163. package/out/replicated.luau +45 -0
  164. package/out/server/data.d.ts +54 -0
  165. package/out/server/data.luau +44 -0
  166. package/out/server/index.d.ts +18 -0
  167. package/out/server/init.luau +62 -0
  168. package/out/server/publish.d.ts +20 -0
  169. package/out/server/publish.luau +24 -0
  170. package/out/subsystem.d.ts +4 -0
  171. package/out/subsystem.luau +30 -0
  172. package/out/vide/index.d.ts +7 -0
  173. package/out/vide/init.luau +50 -0
  174. package/package.json +52 -5
  175. package/server/package.json +4 -0
  176. package/transformer/data.cjs +72 -0
  177. package/transformer/declarations.cjs +153 -0
  178. package/transformer/diagnostics.cjs +19 -0
  179. package/transformer/index.js +741 -0
  180. package/transformer/network.cjs +961 -0
  181. package/transformer/type-id.cjs +80 -0
  182. package/vide/package.json +4 -0
  183. package/README.md +0 -3
@@ -0,0 +1,562 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local runtimeDiagnostic = TS.import(script, script.Parent, "diagnostics").runtimeDiagnostic
4
+ local Subsystem = TS.import(script, script.Parent.Parent, "subsystem").Subsystem
5
+ local CrucibleBehaviour = TS.import(script, script.Parent.Parent, "crucible-behaviour").CrucibleBehaviour
6
+ local _binding = TS.import(script, script.Parent, "binding")
7
+ local construct = _binding.construct
8
+ local forget = _binding.forget
9
+ local reconcile = _binding.reconcile
10
+ local useEngine = _binding.useEngine
11
+ local watch = _binding.watch
12
+ local _hooks = TS.import(script, script.Parent, "hooks")
13
+ local hooks = _hooks.hooks
14
+ local lifecycleHooks = _hooks.lifecycleHooks
15
+ local shutdownHooks = _hooks.shutdownHooks
16
+ local useImplementerPort = TS.import(script, script.Parent, "implementers").useImplementerPort
17
+ local _lifecycle = TS.import(script, script.Parent, "lifecycle")
18
+ local admit = _lifecycle.admit
19
+ local drain = _lifecycle.drain
20
+ local hasEnded = _lifecycle.hasEnded
21
+ local request = _lifecycle.request
22
+ local track = _lifecycle.track
23
+ local useEffects = _lifecycle.useEffects
24
+ local _registry = TS.import(script, script.Parent, "registry")
25
+ local records = _registry.records
26
+ local seal = _registry.seal
27
+ local robloxPort = TS.import(script, script.Parent, "roblox-port").robloxPort
28
+ local Scheduler = TS.import(script, script.Parent, "scheduler").Scheduler
29
+ local _flush = TS.import(script, script.Parent, "reactive", "flush")
30
+ local holdBarrier = _flush.holdBarrier
31
+ local releaseBarrier = _flush.releaseBarrier
32
+ local useReactivePort = _flush.useReactivePort
33
+ local endInterval = TS.import(script, script.Parent, "reactive", "ownership").endInterval
34
+ local _declarations = TS.import(script, script.Parent, "sync", "declarations")
35
+ local rollbackDeclarations = _declarations.rollbackDeclarations
36
+ local sealDeclarations = _declarations.sealDeclarations
37
+ --* @internal
38
+ local BOOT_CLASSES = { Subsystem, CrucibleBehaviour }
39
+ --* @internal
40
+ --* @internal
41
+ local PATTERN_PREFIX = "crucible-path:"
42
+ --* @internal
43
+ local SHUTDOWN_DEADLINE_SECONDS = 25
44
+ --* @internal
45
+ local SHUTDOWN_TIMEOUT_SECONDS = 28
46
+ local clock
47
+ local sweep
48
+ --* @internal
49
+ --* @internal The one monotonic clock, core's and data's (data rules 25, 105).
50
+ local function bootClock()
51
+ return (clock or os.clock)()
52
+ end
53
+ --* @internal Undefined until the sweep has begun.
54
+ local function shutdownProgress(subsystem)
55
+ if sweep == nil then
56
+ return nil
57
+ end
58
+ local pending = 0
59
+ local notStarted = 0
60
+ for _, record in sweep.order do
61
+ local _condition = sweep.finished[record] ~= nil
62
+ if not _condition then
63
+ local _result = record.state
64
+ if _result ~= nil then
65
+ _result = _result.object
66
+ end
67
+ _condition = _result == subsystem
68
+ end
69
+ if _condition then
70
+ continue
71
+ end
72
+ pending += 1
73
+ if not (sweep.started[record] ~= nil) then
74
+ notStarted += 1
75
+ end
76
+ end
77
+ return {
78
+ startedAt = sweep.startTime,
79
+ forceStartAt = sweep.startTime + SHUTDOWN_DEADLINE_SECONDS,
80
+ deadline = sweep.startTime + SHUTDOWN_TIMEOUT_SECONDS,
81
+ pending = pending,
82
+ notStarted = notStarted,
83
+ }
84
+ end
85
+ --* @internal
86
+ local function parsePattern(pattern)
87
+ local _pattern = pattern
88
+ local _arg1 = #PATTERN_PREFIX
89
+ if string.sub(_pattern, 1, _arg1) ~= PATTERN_PREFIX then
90
+ error(`Crucible load needs the transformer: {pattern}`)
91
+ end
92
+ local _pattern_1 = pattern
93
+ local _arg0 = #PATTERN_PREFIX + 1
94
+ local segments = string.split(string.sub(_pattern_1, _arg0), "/")
95
+ -- ▼ ReadonlyArray.some ▼
96
+ local _result = false
97
+ local _callback = function(s)
98
+ return s == "" or s == "." or s == ".."
99
+ end
100
+ for _k, _v in segments do
101
+ if _callback(_v, _k - 1, segments) then
102
+ _result = true
103
+ break
104
+ end
105
+ end
106
+ -- ▲ ReadonlyArray.some ▲
107
+ if _result then
108
+ error(`Invalid Crucible load pattern: {pattern}`)
109
+ end
110
+ return segments
111
+ end
112
+ local function matches(name, pattern)
113
+ local open = string.find(pattern, "{", 1, true)
114
+ if open ~= nil then
115
+ local close = string.find(pattern, "}", open, true)
116
+ if close == nil then
117
+ error(`Invalid Crucible name pattern: {pattern}`)
118
+ end
119
+ local _pattern = pattern
120
+ local _arg0 = open + 1
121
+ local _arg1 = close - 1
122
+ local _exp = string.split(string.sub(_pattern, _arg0, _arg1), ",")
123
+ -- ▼ ReadonlyArray.some ▼
124
+ local _result = false
125
+ local _callback = function(part)
126
+ local _exp_1 = name
127
+ local _pattern_1 = pattern
128
+ local _arg1_1 = open - 1
129
+ local _exp_2 = string.sub(_pattern_1, 1, _arg1_1) .. part
130
+ local _pattern_2 = pattern
131
+ local _arg0_1 = close + 1
132
+ return matches(_exp_1, _exp_2 .. string.sub(_pattern_2, _arg0_1))
133
+ end
134
+ for _k, _v in _exp do
135
+ if _callback(_v, _k - 1, _exp) then
136
+ _result = true
137
+ break
138
+ end
139
+ end
140
+ -- ▲ ReadonlyArray.some ▲
141
+ return _result
142
+ end
143
+ local star = string.find(pattern, "*", 1, true)
144
+ if star == nil then
145
+ return name == pattern
146
+ end
147
+ local _pattern = pattern
148
+ local _arg1 = star - 1
149
+ local prefix = string.sub(_pattern, 1, _arg1)
150
+ local _name = name
151
+ local _arg1_1 = #prefix
152
+ if string.sub(_name, 1, _arg1_1) ~= prefix then
153
+ return false
154
+ end
155
+ for i = #prefix, #name do
156
+ local _name_1 = name
157
+ local _arg0 = i + 1
158
+ local _exp = string.sub(_name_1, _arg0)
159
+ local _pattern_1 = pattern
160
+ local _arg0_1 = star + 1
161
+ if matches(_exp, string.sub(_pattern_1, _arg0_1)) then
162
+ return true
163
+ end
164
+ end
165
+ return false
166
+ end
167
+ --* @internal
168
+ local function load(patterns)
169
+ local found = {}
170
+ local function walk(node, segments, index)
171
+ if index == #segments then
172
+ if node:IsA("ModuleScript") then
173
+ local _node = node
174
+ found[_node] = true
175
+ end
176
+ return nil
177
+ end
178
+ local segment = segments[index + 1]
179
+ if segment == "**" then
180
+ walk(node, segments, index + 1)
181
+ end
182
+ for _, child in node:GetChildren() do
183
+ if segment == "**" then
184
+ walk(child, segments, index)
185
+ elseif matches(child.Name, segment) then
186
+ walk(child, segments, index + 1)
187
+ end
188
+ end
189
+ end
190
+ for _, pattern in patterns do
191
+ local segments = parsePattern(pattern)
192
+ walk(game:GetService(segments[1]), segments, 1)
193
+ end
194
+ local _array = {}
195
+ local _length = #_array
196
+ for _v in found do
197
+ _length += 1
198
+ _array[_length] = _v
199
+ end
200
+ local modules = _array
201
+ table.sort(modules, function(a, b)
202
+ return a:GetFullName() < b:GetFullName()
203
+ end)
204
+ for _, module in modules do
205
+ require(module)
206
+ end
207
+ end
208
+ local HOOK_NAMES = { "constructor", "awake", "onEnable", "start", "onDisable", "onDestroy", "a frame hook", "accepts", "an All<T> callback", "settle", "cancel", "internal" }
209
+ local function where(port, s)
210
+ local id = (s.record).id
211
+ return if s.instance == nil then id else `{id} on {port.describe(s.instance)}`
212
+ end
213
+ local function describeFault(port, s)
214
+ local fault = s.fault
215
+ local message = `{where(port, s)} faulted in {HOOK_NAMES[fault.hook + 1]}: {tostring(fault.error)}`
216
+ for _, later in fault.cleanup do
217
+ message ..= `\n then {HOOK_NAMES[later.hook + 1]} failed: {tostring(later.error)}`
218
+ end
219
+ return message
220
+ end
221
+ local function hookCaller(s, hook)
222
+ if hook == 1 then
223
+ return function(s)
224
+ return hooks().awake(s.object, 0)
225
+ end
226
+ end
227
+ if s.record.kind ~= 1 then
228
+ return nil
229
+ end
230
+ if hook == 2 then
231
+ return function(s)
232
+ return lifecycleHooks().onEnable(s.object, 0)
233
+ end
234
+ end
235
+ if hook == 4 then
236
+ return function(s)
237
+ return lifecycleHooks().onDisable(s.object, 0)
238
+ end
239
+ end
240
+ if hook == 5 then
241
+ return function(s)
242
+ return lifecycleHooks().onDestroy(s.object, 0)
243
+ end
244
+ end
245
+ return nil
246
+ end
247
+ local function shutdown(port, order)
248
+ local started = {}
249
+ local finished = {}
250
+ local dependents = {}
251
+ for _, record in order do
252
+ dependents[record] = {}
253
+ end
254
+ for _, record in order do
255
+ for _1, dep in record.resolved do
256
+ if not dep.all then
257
+ local _record = dep.record
258
+ local _exp = dependents[_record]
259
+ table.insert(_exp, record)
260
+ end
261
+ end
262
+ end
263
+ local startTime = port.clock()
264
+ sweep = {
265
+ startTime = startTime,
266
+ order = order,
267
+ started = started,
268
+ finished = finished,
269
+ }
270
+ while true do
271
+ -- ▼ ReadonlySet.size ▼
272
+ local _size = 0
273
+ for _ in finished do
274
+ _size += 1
275
+ end
276
+ -- ▲ ReadonlySet.size ▲
277
+ if not (_size < #order) then
278
+ break
279
+ end
280
+ local expired = port.clock() - startTime >= SHUTDOWN_DEADLINE_SECONDS
281
+ for _, record in order do
282
+ local _condition = started[record] ~= nil
283
+ if not _condition then
284
+ local _condition_1 = not expired
285
+ if _condition_1 then
286
+ local _exp = dependents[record]
287
+ -- ▼ ReadonlyArray.every ▼
288
+ local _result = true
289
+ local _callback = function(r)
290
+ local _r = r
291
+ return finished[_r] ~= nil
292
+ end
293
+ for _k, _v in _exp do
294
+ if not _callback(_v, _k - 1, _exp) then
295
+ _result = false
296
+ break
297
+ end
298
+ end
299
+ -- ▲ ReadonlyArray.every ▲
300
+ _condition_1 = not _result
301
+ end
302
+ _condition = _condition_1
303
+ end
304
+ if _condition then
305
+ continue
306
+ end
307
+ started[record] = true
308
+ port.spawn(function()
309
+ local _object = record.state
310
+ if _object ~= nil then
311
+ _object = _object.object
312
+ end
313
+ local object = _object
314
+ if object ~= nil then
315
+ local ok, err = xpcall(function()
316
+ return shutdownHooks().onShutdown(object)
317
+ end, function(err)
318
+ return debug.traceback(tostring(err), 2)
319
+ end)
320
+ if not ok then
321
+ runtimeDiagnostic("error", `{record.id} onShutdown failed: {err}`)
322
+ end
323
+ end
324
+ finished[record] = true
325
+ end)
326
+ end
327
+ if port.clock() - startTime >= SHUTDOWN_TIMEOUT_SECONDS then
328
+ return nil
329
+ end
330
+ -- ▼ ReadonlySet.size ▼
331
+ local _size_1 = 0
332
+ for _ in finished do
333
+ _size_1 += 1
334
+ end
335
+ -- ▲ ReadonlySet.size ▲
336
+ if _size_1 < #order then
337
+ port.wait()
338
+ end
339
+ end
340
+ end
341
+ --* @internal
342
+ local function ignite(port, side, options)
343
+ clock = port.clock
344
+ sweep = nil
345
+ local singletons = seal({
346
+ renders = side.renders,
347
+ })
348
+ local frame = hooks().frame
349
+ local _exp = port
350
+ local _object = {}
351
+ local _left = "fixedRate"
352
+ local _condition = options.fixedRate
353
+ if _condition == nil then
354
+ _condition = 60
355
+ end
356
+ _object[_left] = _condition
357
+ _object.renders = side.renders
358
+ local scheduler = Scheduler.new(_exp, _object, {
359
+ [0] = function(o, dt)
360
+ return frame[0](o, dt)
361
+ end,
362
+ [1] = function(o, dt)
363
+ return frame[1](o, dt)
364
+ end,
365
+ [2] = function(o, dt)
366
+ return frame[2](o, dt)
367
+ end,
368
+ [3] = function(o, dt)
369
+ return frame[3](o, dt)
370
+ end,
371
+ })
372
+ local owned = {}
373
+ local stage = "booting"
374
+ local failure
375
+ local stop = function() end
376
+ local function reject(message)
377
+ if stage ~= "booting" then
378
+ return nil
379
+ end
380
+ failure = message
381
+ stage = "rollback"
382
+ stop()
383
+ for state in owned do
384
+ request(state, 2)
385
+ end
386
+ end
387
+ useEngine(port)
388
+ holdBarrier()
389
+ useReactivePort(port)
390
+ useImplementerPort(port)
391
+ useEffects({
392
+ construct = function(s)
393
+ if stage == "booting" then
394
+ local _s = s
395
+ owned[_s] = true
396
+ end
397
+ return construct(s)
398
+ end,
399
+ hook = hookCaller,
400
+ start = function(s)
401
+ return hooks().start(s.object, 0)
402
+ end,
403
+ join = function(s)
404
+ for _, set in (s.record).memberOf do
405
+ set:join(s.object)
406
+ end
407
+ end,
408
+ leave = function(s)
409
+ for _, set in (s.record).memberOf do
410
+ set:leave(s.object)
411
+ end
412
+ end,
413
+ tick = function(s)
414
+ return scheduler:add(s)
415
+ end,
416
+ untick = function(s)
417
+ return scheduler:remove(s)
418
+ end,
419
+ reconcile = function()
420
+ if stage == "rollback" then
421
+ return {}
422
+ end
423
+ local created = reconcile()
424
+ if stage == "booting" then
425
+ for _, s in created do
426
+ owned[s] = true
427
+ end
428
+ end
429
+ return created
430
+ end,
431
+ ended = function(s)
432
+ forget(s)
433
+ if s.fault == nil then
434
+ return nil
435
+ end
436
+ local message = describeFault(port, s)
437
+ runtimeDiagnostic("error", message)
438
+ if s.record.kind == 0 then
439
+ reject(message)
440
+ end
441
+ end,
442
+ defer = port.defer,
443
+ cancel = port.cancel,
444
+ failed = function(message)
445
+ runtimeDiagnostic("error", message)
446
+ reject(message)
447
+ end,
448
+ diagnose = function(s, hook, err)
449
+ return runtimeDiagnostic("error", `{where(port, s)} {HOOK_NAMES[hook + 1]} failed: {tostring(err)}`)
450
+ end,
451
+ disabled = endInterval,
452
+ })
453
+ local ok, err = pcall(function()
454
+ local _exp_1 = records()
455
+ -- ▼ ReadonlyArray.filter ▼
456
+ local _newValue = {}
457
+ local _callback = function(r)
458
+ return r.kind == 1
459
+ end
460
+ local _length = 0
461
+ for _k, _v in _exp_1 do
462
+ if _callback(_v, _k - 1, _exp_1) == true then
463
+ _length += 1
464
+ _newValue[_length] = _v
465
+ end
466
+ end
467
+ -- ▲ ReadonlyArray.filter ▲
468
+ stop = watch(_newValue)
469
+ -- ▼ ReadonlyArray.map ▼
470
+ local _newValue_1 = table.create(#singletons)
471
+ local _callback_1 = function(r)
472
+ local s = track(r)
473
+ r.state = s
474
+ owned[s] = true
475
+ return s
476
+ end
477
+ for _k, _v in singletons do
478
+ _newValue_1[_k] = _callback_1(_v, _k - 1, singletons)
479
+ end
480
+ -- ▲ ReadonlyArray.map ▲
481
+ local initial = _newValue_1
482
+ admit(initial)
483
+ drain()
484
+ end)
485
+ if not ok then
486
+ reject(tostring(err))
487
+ end
488
+ if failure == nil then
489
+ local unbooted = nil
490
+ local finalized, finalizeErr = pcall(function()
491
+ -- Roblox cannot unbind BindToClose, so the callback checks that this boot committed.
492
+ if side.name == "server" then
493
+ port.bindToClose(function()
494
+ if stage ~= "committed" then
495
+ return nil
496
+ end
497
+ shutdown(port, singletons)
498
+ side.network:close()
499
+ end)
500
+ end
501
+ unbooted = side.booted()
502
+ if side.name == "client" then
503
+ sealDeclarations()
504
+ end
505
+ side.network:commit()
506
+ end)
507
+ if not finalized then
508
+ local undo = unbooted
509
+ if undo ~= nil then
510
+ local undone, undoErr = pcall(undo)
511
+ if not undone then
512
+ runtimeDiagnostic("error", `Crucible: undoing booted failed: {tostring(undoErr)}`)
513
+ end
514
+ end
515
+ reject(`boot finalization failed: {tostring(finalizeErr)}`)
516
+ end
517
+ end
518
+ if failure ~= nil then
519
+ for s in owned do
520
+ if not hasEnded(s) then
521
+ request(s, 2)
522
+ end
523
+ end
524
+ drain()
525
+ table.clear(owned)
526
+ releaseBarrier()
527
+ error(`Crucible boot failed: {failure}`, 0)
528
+ end
529
+ stage = "committed"
530
+ table.clear(owned)
531
+ releaseBarrier()
532
+ end
533
+ --* @internal
534
+ local function boot(side, options)
535
+ local ok, err = pcall(function()
536
+ side.network:open()
537
+ load(options.load)
538
+ side.network:loaded()
539
+ if side.name == "server" then
540
+ sealDeclarations()
541
+ end
542
+ ignite(robloxPort(), side, options)
543
+ end)
544
+ if ok then
545
+ return nil
546
+ end
547
+ side.network:close()
548
+ rollbackDeclarations()
549
+ error(err, 0)
550
+ end
551
+ return {
552
+ bootClock = bootClock,
553
+ shutdownProgress = shutdownProgress,
554
+ parsePattern = parsePattern,
555
+ load = load,
556
+ ignite = ignite,
557
+ boot = boot,
558
+ BOOT_CLASSES = BOOT_CLASSES,
559
+ PATTERN_PREFIX = PATTERN_PREFIX,
560
+ SHUTDOWN_DEADLINE_SECONDS = SHUTDOWN_DEADLINE_SECONDS,
561
+ SHUTDOWN_TIMEOUT_SECONDS = SHUTDOWN_TIMEOUT_SECONDS,
562
+ }
@@ -0,0 +1,10 @@
1
+ export declare const MAX_CONFIG_DECLARATIONS = 1000;
2
+ export declare const CONFIG_NAME_MAX_BYTES = 64;
3
+ export declare const CONFIG_VALUE_MAX_BYTES = 100000;
4
+ export declare const CONFIG_ADMISSION_VISITS = 100000;
5
+ export declare const CONFIG_REQUEST_CONCURRENCY = 4;
6
+ export declare const CONFIG_FETCH_RETRY_BASE_SECONDS = 1;
7
+ export declare const CONFIG_FETCH_RETRY_CAP_SECONDS = 30;
8
+ export declare const CONFIG_REFRESH_TIMEOUT_SECONDS = 10;
9
+ export declare const CONFIG_VALUE_DEPTH = 28;
10
+ export declare const CONFIG_STRING_MAX_BYTES = 65536;
@@ -0,0 +1,25 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local MAX_CONFIG_DECLARATIONS = 1_000
3
+ local CONFIG_NAME_MAX_BYTES = 64
4
+ local CONFIG_VALUE_MAX_BYTES = 100_000
5
+ local CONFIG_ADMISSION_VISITS = 100_000
6
+ local CONFIG_REQUEST_CONCURRENCY = 4
7
+ local CONFIG_FETCH_RETRY_BASE_SECONDS = 1
8
+ local CONFIG_FETCH_RETRY_CAP_SECONDS = 30
9
+ local CONFIG_REFRESH_TIMEOUT_SECONDS = 10
10
+ -- Rule 97 admits configs by rule 76's walk, whose depth and string bounds are data's PERSIST_DEPTH and
11
+ -- PERSIST_STRING_BYTES. Data's limits module is not under configs yet, so the values are restated here.
12
+ local CONFIG_VALUE_DEPTH = 28
13
+ local CONFIG_STRING_MAX_BYTES = 65_536
14
+ return {
15
+ MAX_CONFIG_DECLARATIONS = MAX_CONFIG_DECLARATIONS,
16
+ CONFIG_NAME_MAX_BYTES = CONFIG_NAME_MAX_BYTES,
17
+ CONFIG_VALUE_MAX_BYTES = CONFIG_VALUE_MAX_BYTES,
18
+ CONFIG_ADMISSION_VISITS = CONFIG_ADMISSION_VISITS,
19
+ CONFIG_REQUEST_CONCURRENCY = CONFIG_REQUEST_CONCURRENCY,
20
+ CONFIG_FETCH_RETRY_BASE_SECONDS = CONFIG_FETCH_RETRY_BASE_SECONDS,
21
+ CONFIG_FETCH_RETRY_CAP_SECONDS = CONFIG_FETCH_RETRY_CAP_SECONDS,
22
+ CONFIG_REFRESH_TIMEOUT_SECONDS = CONFIG_REFRESH_TIMEOUT_SECONDS,
23
+ CONFIG_VALUE_DEPTH = CONFIG_VALUE_DEPTH,
24
+ CONFIG_STRING_MAX_BYTES = CONFIG_STRING_MAX_BYTES,
25
+ }
@@ -0,0 +1,29 @@
1
+ import type { Disconnect } from "../port";
2
+ export interface ConfigSnapshotPort {
3
+ /** `GetValue`: nil for a missing key. A JSON config may arrive as a table or as its text. */
4
+ readonly get: (key: string) => unknown;
5
+ /** `Refresh`. Yields and may throw. */
6
+ readonly refresh: () => void;
7
+ /** Unmeasured in Studio: whether this turns true without `UpdateAvailable`. Runtime treats the two as independent. */
8
+ readonly outdated: () => boolean;
9
+ /** `Error` is `LoadFailed`. */
10
+ readonly failed: () => boolean;
11
+ readonly onUpdateAvailable: (listener: () => void) => Disconnect;
12
+ }
13
+ /** What configs ask of the engine. Requests yield and may throw. */
14
+ export interface ConfigPort {
15
+ readonly global: () => ConfigSnapshotPort;
16
+ readonly forPlayer: (player: Player) => ConfigSnapshotPort;
17
+ readonly players: () => readonly Player[];
18
+ readonly onPlayerAdded: (listener: (player: Player) => void) => Disconnect;
19
+ readonly onPlayerRemoving: (listener: (player: Player) => void) => Disconnect;
20
+ readonly wait: (seconds: number) => void;
21
+ /** Uniform in [0, 1). */
22
+ readonly random: () => number;
23
+ readonly decodeJson: (text: string) => unknown;
24
+ /** The JSON text length of a decoded value. Throws for a value JSON cannot hold. */
25
+ readonly jsonBytes: (value: object) => number;
26
+ }
27
+ export declare function installConfigPort(value: ConfigPort): void;
28
+ export declare function configPort(): ConfigPort;
29
+ export declare function createRobloxConfigPort(): ConfigPort;