@flamework-experimental/core 2.0.0-alpha.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 (65) hide show
  1. package/README.md +66 -0
  2. package/flamework.build +17 -0
  3. package/out/dependency.d.ts +18 -0
  4. package/out/dependency.luau +32 -0
  5. package/out/flamework.d.ts +78 -0
  6. package/out/flamework.luau +138 -0
  7. package/out/index.d.ts +28 -0
  8. package/out/init.luau +40 -0
  9. package/out/injectable.d.ts +13 -0
  10. package/out/injectable.luau +23 -0
  11. package/out/lifecycle/lifecycleInterfaces.d.ts +94 -0
  12. package/out/lifecycle/lifecycleInterfaces.luau +55 -0
  13. package/out/lifecycle/lifecyclePlugin.d.ts +85 -0
  14. package/out/lifecycle/lifecyclePlugin.luau +424 -0
  15. package/out/modding.d.ts +171 -0
  16. package/out/modding.luau +66 -0
  17. package/out/module/defaultModule.d.ts +5 -0
  18. package/out/module/defaultModule.luau +28 -0
  19. package/out/module/module.d.ts +78 -0
  20. package/out/module/module.luau +811 -0
  21. package/out/module/moduleBuilder.d.ts +88 -0
  22. package/out/module/moduleBuilder.luau +169 -0
  23. package/out/module/moduleDefinition.d.ts +105 -0
  24. package/out/module/moduleDefinition.luau +79 -0
  25. package/out/module/moduleHooks.d.ts +23 -0
  26. package/out/module/moduleHooks.luau +19 -0
  27. package/out/module/providerRegistration.d.ts +22 -0
  28. package/out/module/providerRegistration.luau +80 -0
  29. package/out/module/scopes.d.ts +40 -0
  30. package/out/module/scopes.luau +159 -0
  31. package/out/plugin/pluginDefinition.d.ts +128 -0
  32. package/out/plugin/pluginDefinition.luau +61 -0
  33. package/out/prelude.d.ts +8 -0
  34. package/out/prelude.luau +14 -0
  35. package/out/provider.d.ts +27 -0
  36. package/out/provider.luau +26 -0
  37. package/out/reflect.d.ts +60 -0
  38. package/out/reflect.luau +310 -0
  39. package/out/serialization/types.d.ts +86 -0
  40. package/out/serialization/types.luau +9 -0
  41. package/out/utility/constructors.d.ts +4 -0
  42. package/out/utility/constructors.luau +12 -0
  43. package/out/utility/convertConciseDependencyInfo.d.ts +5 -0
  44. package/out/utility/convertConciseDependencyInfo.luau +29 -0
  45. package/out/utility/getClassImplements.d.ts +7 -0
  46. package/out/utility/getClassImplements.luau +27 -0
  47. package/out/utility/getClassesInPath.d.ts +23 -0
  48. package/out/utility/getClassesInPath.luau +91 -0
  49. package/out/utility/globs.d.ts +9 -0
  50. package/out/utility/globs.luau +64 -0
  51. package/out/utility/metadata.d.ts +12 -0
  52. package/out/utility/metadata.luau +43 -0
  53. package/out/utility/pathRoot.d.ts +17 -0
  54. package/out/utility/pathRoot.luau +105 -0
  55. package/out/utility/recycleThread.d.ts +1 -0
  56. package/out/utility/recycleThread.luau +31 -0
  57. package/out/utility/runtimeConfig.d.ts +59 -0
  58. package/out/utility/runtimeConfig.luau +25 -0
  59. package/out/utility/tsImport.d.ts +6 -0
  60. package/out/utility/tsImport.luau +15 -0
  61. package/out/utility/types.d.ts +16 -0
  62. package/out/utility/types.luau +22 -0
  63. package/out/utility/writable.d.ts +4 -0
  64. package/out/utility/writable.luau +2 -0
  65. package/package.json +33 -0
@@ -0,0 +1,85 @@
1
+ import type { Module } from "../module/module";
2
+ import type { OnExtinguished, OnInit, OnPhysics, OnRender, OnStart, OnTick } from "./lifecycleInterfaces";
3
+ import { PluginDefinition, type InterfaceContext } from "../plugin/pluginDefinition";
4
+ export interface LifecyclePluginOptions {
5
+ /**
6
+ * Whether per-frame lifecycle callbacks are wrapped in `debug.profilebegin` and
7
+ * `debug.setmemorycategory` with the provider's identifier, so that they show up by name in the
8
+ * MicroProfiler and the memory view.
9
+ *
10
+ * Defaults to `RunService.IsStudio()`, which is what v1's `flamework.json` defaulted to as well.
11
+ */
12
+ profiling?: boolean;
13
+ }
14
+ /**
15
+ * Tracks the objects attached to each lifecycle event for one module.
16
+ *
17
+ * The plugin builds one per ignition of every module that includes it, so nothing here is shared
18
+ * between modules, and provides it, so `module.resolveDependency<LifecycleProvider>()` answers what
19
+ * is attached to a module's events right now.
20
+ */
21
+ export declare class LifecycleProvider {
22
+ /** In attachment order, which for providers is dependency order. */
23
+ private onInit;
24
+ private initMembers;
25
+ /** The providers `postIgnite` starts, in attachment order; `onStart` is every member. */
26
+ private startOrder;
27
+ onStart: Set<OnStart>;
28
+ onTick: Set<OnTick>;
29
+ onPhysics: Set<OnPhysics>;
30
+ onRender: Set<OnRender>;
31
+ onExtinguished: Set<OnExtinguished>;
32
+ private identifiers;
33
+ private moduleConnections;
34
+ private lateProviders;
35
+ private hasStarted;
36
+ private isProfiling;
37
+ constructor(options: LifecyclePluginOptions);
38
+ private getIdentifier;
39
+ /**
40
+ * Drops the memoised identifier of an object that has left its last lifecycle event.
41
+ *
42
+ * The memo is keyed by the object itself, so an entry left behind is a strong reference to it:
43
+ * a removed component, and with it its instance, its attributes and everything it links to,
44
+ * held for as long as the module lives. `profile` fills it in for every object it runs a
45
+ * per-frame callback for, so the table grew by one for every component that ever ticked
46
+ * whenever profiling was on -- which it is in Studio by default, and in production for anyone
47
+ * who sets `core.profiling`.
48
+ *
49
+ * The entry stays while any event still holds the object: dropping it there would only make the
50
+ * next frame look it up again.
51
+ */
52
+ private forget;
53
+ private profile;
54
+ /**
55
+ * Runs `onInit` synchronously, waiting on a returned Promise, so that initialisation happens in
56
+ * dependency order and is complete before anything starts.
57
+ */
58
+ private runInit;
59
+ private runStart;
60
+ /**
61
+ * A provider constructed after ignition (a lazy one) still gets `onInit` and `onStart`, in that
62
+ * order, once every one of its interfaces has been attached. Instances attached late through
63
+ * `listen` or `createClassInstance` do not; they are owned by whoever created them.
64
+ */
65
+ private scheduleLateProvider;
66
+ addInit(object: OnInit, context: InterfaceContext): void;
67
+ removeInit(object: OnInit): void;
68
+ addStart(object: OnStart, context: InterfaceContext): void;
69
+ removeStart(object: OnStart): void;
70
+ postIgnite(module: Module): void;
71
+ extinguished(module: Module): void;
72
+ }
73
+ /**
74
+ * Creates a lifecycle plugin with the specified options.
75
+ *
76
+ * `LifecyclePlugin` is `createLifecyclePlugin()` with the defaults; use this when a module needs
77
+ * different ones, such as forcing profiling on or off.
78
+ */
79
+ export declare function createLifecyclePlugin(options?: LifecyclePluginOptions): PluginDefinition;
80
+ /**
81
+ * The lifecycle plugin with default options. Every module made with `Flamework.createModule()`
82
+ * starts with it; `disableDefaultLifecycle()` on the builder leaves it out, and including one built
83
+ * with {@link createLifecyclePlugin} takes its place.
84
+ */
85
+ export declare const LifecyclePlugin: PluginDefinition;
@@ -0,0 +1,424 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local Reflect_1 = TS.import(script, script.Parent.Parent, "reflect").Reflect
4
+ local RunService = TS.import(script, TS.getModule(script, "@rbxts", "services")).RunService
5
+ local getRuntimeConfig = TS.import(script, script.Parent.Parent, "utility", "runtimeConfig").getRuntimeConfig
6
+ local Provider = TS.import(script, script.Parent.Parent, "provider").Provider
7
+ local recycleThread = TS.import(script, script.Parent.Parent, "utility", "recycleThread").recycleThread
8
+ local Reflect = TS.import(script, script.Parent.Parent, "reflect").Reflect
9
+ local _pluginDefinition = TS.import(script, script.Parent.Parent, "plugin", "pluginDefinition")
10
+ local LIFECYCLE_SLOT = _pluginDefinition.LIFECYCLE_SLOT
11
+ local PluginDefinition = _pluginDefinition.PluginDefinition
12
+ --[[
13
+ *
14
+ * Tracks the objects attached to each lifecycle event for one module.
15
+ *
16
+ * The plugin builds one per ignition of every module that includes it, so nothing here is shared
17
+ * between modules, and provides it, so `module.resolveDependency<LifecycleProvider>()` answers what
18
+ * is attached to a module's events right now.
19
+
20
+ ]]
21
+ local LifecycleProvider
22
+ do
23
+ LifecycleProvider = setmetatable({}, {
24
+ __tostring = function()
25
+ return "LifecycleProvider"
26
+ end,
27
+ })
28
+ LifecycleProvider.__index = LifecycleProvider
29
+ function LifecycleProvider.new(...)
30
+ local self = setmetatable({}, LifecycleProvider)
31
+ return self:constructor(...) or self
32
+ end
33
+ function LifecycleProvider:constructor(options)
34
+ self.onInit = {}
35
+ self.initMembers = {}
36
+ self.startOrder = {}
37
+ self.onStart = {}
38
+ self.onTick = {}
39
+ self.onPhysics = {}
40
+ self.onRender = {}
41
+ self.onExtinguished = {}
42
+ self.identifiers = {}
43
+ self.moduleConnections = {}
44
+ self.lateProviders = {}
45
+ self.hasStarted = false
46
+ -- Per-module option, then the project's flamework.config.json, then Studio.
47
+ local _condition = options.profiling
48
+ if _condition == nil then
49
+ local _result = getRuntimeConfig().core
50
+ if _result ~= nil then
51
+ _result = _result.profiling
52
+ end
53
+ _condition = _result
54
+ if _condition == nil then
55
+ _condition = RunService:IsStudio()
56
+ end
57
+ end
58
+ self.isProfiling = _condition
59
+ end
60
+ function LifecycleProvider:getIdentifier(object)
61
+ local _identifiers = self.identifiers
62
+ local _object = object
63
+ local identifier = _identifiers[_object]
64
+ if identifier == nil then
65
+ local _condition = Reflect.getMetadata(object, "identifier")
66
+ if _condition == nil then
67
+ _condition = "[flamework listener]"
68
+ end
69
+ identifier = _condition
70
+ local _identifiers_1 = self.identifiers
71
+ local _object_1 = object
72
+ local _identifier = identifier
73
+ _identifiers_1[_object_1] = _identifier
74
+ end
75
+ return identifier
76
+ end
77
+ function LifecycleProvider:forget(object)
78
+ local _initMembers = self.initMembers
79
+ local _object = object
80
+ local _condition = _initMembers[_object] ~= nil
81
+ if not _condition then
82
+ local _onStart = self.onStart
83
+ local _object_1 = object
84
+ _condition = _onStart[_object_1] ~= nil
85
+ if not _condition then
86
+ local _onTick = self.onTick
87
+ local _object_2 = object
88
+ _condition = _onTick[_object_2] ~= nil
89
+ if not _condition then
90
+ local _onPhysics = self.onPhysics
91
+ local _object_3 = object
92
+ _condition = _onPhysics[_object_3] ~= nil
93
+ if not _condition then
94
+ local _onRender = self.onRender
95
+ local _object_4 = object
96
+ _condition = _onRender[_object_4] ~= nil
97
+ if not _condition then
98
+ local _onExtinguished = self.onExtinguished
99
+ local _object_5 = object
100
+ _condition = _onExtinguished[_object_5] ~= nil
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ local attached = _condition
107
+ if not attached then
108
+ local _identifiers = self.identifiers
109
+ local _object_1 = object
110
+ _identifiers[_object_1] = nil
111
+ end
112
+ end
113
+ function LifecycleProvider:removeFrom(set, value)
114
+ local _set = set
115
+ local _value = value
116
+ _set[_value] = nil
117
+ self:forget(value)
118
+ end
119
+ function LifecycleProvider:profile(callback, object)
120
+ if self.isProfiling then
121
+ local id = self:getIdentifier(object)
122
+ return recycleThread(function()
123
+ -- `profilebegin` ends when the thread yields or dies.
124
+ debug.profilebegin(id)
125
+ debug.setmemorycategory(id)
126
+ callback()
127
+ debug.resetmemorycategory()
128
+ end)
129
+ end
130
+ return recycleThread(callback)
131
+ end
132
+ function LifecycleProvider:runInit(object)
133
+ local id = self:getIdentifier(object)
134
+ if self.isProfiling then
135
+ debug.setmemorycategory(id)
136
+ end
137
+ local result = object:onInit()
138
+ if TS.Promise.is(result) then
139
+ local status, value = result:awaitStatus()
140
+ if status == TS.Promise.Status.Rejected then
141
+ error(`onInit failed for '{id}': {tostring(value)}`, 0)
142
+ end
143
+ end
144
+ if self.isProfiling then
145
+ debug.resetmemorycategory()
146
+ end
147
+ end
148
+ function LifecycleProvider:runStart(object)
149
+ task.spawn(function()
150
+ return object:onStart()
151
+ end)
152
+ end
153
+ function LifecycleProvider:scheduleLateProvider(object)
154
+ local _lateProviders = self.lateProviders
155
+ local _object = object
156
+ if _lateProviders[_object] ~= nil then
157
+ return nil
158
+ end
159
+ local _lateProviders_1 = self.lateProviders
160
+ local _object_1 = object
161
+ _lateProviders_1[_object_1] = true
162
+ task.defer(function()
163
+ local _lateProviders_2 = self.lateProviders
164
+ local _object_2 = object
165
+ if not (_lateProviders_2[_object_2] ~= nil) then
166
+ return nil
167
+ end
168
+ local _lateProviders_3 = self.lateProviders
169
+ local _object_3 = object
170
+ _lateProviders_3[_object_3] = nil
171
+ local _initMembers = self.initMembers
172
+ local _object_4 = object
173
+ if _initMembers[_object_4] ~= nil then
174
+ self:runInit(object)
175
+ end
176
+ local _onStart = self.onStart
177
+ local _object_5 = object
178
+ if _onStart[_object_5] ~= nil then
179
+ self:runStart(object)
180
+ end
181
+ end)
182
+ end
183
+ function LifecycleProvider:addInit(object, context)
184
+ local _initMembers = self.initMembers
185
+ local _object = object
186
+ _initMembers[_object] = true
187
+ -- Only a provider is initialised by the plugin. An instance attached through `listen` or
188
+ -- `createClassInstance` is owned by whoever created it -- `Components` runs a component's
189
+ -- `onInit` itself, before the component can be seen -- so one built during ignition must not
190
+ -- be initialised a second time here.
191
+ if context.kind ~= "provider" then
192
+ return nil
193
+ end
194
+ if not self.hasStarted then
195
+ local _onInit = self.onInit
196
+ local _object_1 = object
197
+ table.insert(_onInit, _object_1)
198
+ else
199
+ self:scheduleLateProvider(object)
200
+ end
201
+ end
202
+ function LifecycleProvider:removeInit(object)
203
+ local _initMembers = self.initMembers
204
+ local _object = object
205
+ _initMembers[_object] = nil
206
+ local _lateProviders = self.lateProviders
207
+ local _object_1 = object
208
+ _lateProviders[_object_1] = nil
209
+ local _onInit = self.onInit
210
+ local _object_2 = object
211
+ local index = (table.find(_onInit, _object_2) or 0) - 1
212
+ if index ~= -1 then
213
+ table.remove(self.onInit, index + 1)
214
+ end
215
+ self:forget(object)
216
+ end
217
+ function LifecycleProvider:addStart(object, context)
218
+ local _onStart = self.onStart
219
+ local _object = object
220
+ _onStart[_object] = true
221
+ -- Only a provider is started by the plugin, as with `onInit`: an instance attached through
222
+ -- `listen` or `createClassInstance` is owned by whoever created it. `Components` starts a
223
+ -- component itself, once the component is attached and ignition has finished.
224
+ if context.kind ~= "provider" then
225
+ return nil
226
+ end
227
+ if not self.hasStarted then
228
+ local _startOrder = self.startOrder
229
+ local _object_1 = object
230
+ table.insert(_startOrder, _object_1)
231
+ else
232
+ self:scheduleLateProvider(object)
233
+ end
234
+ end
235
+ function LifecycleProvider:removeStart(object)
236
+ local _onStart = self.onStart
237
+ local _object = object
238
+ _onStart[_object] = nil
239
+ local _lateProviders = self.lateProviders
240
+ local _object_1 = object
241
+ _lateProviders[_object_1] = nil
242
+ local _startOrder = self.startOrder
243
+ local _object_2 = object
244
+ local index = (table.find(_startOrder, _object_2) or 0) - 1
245
+ if index ~= -1 then
246
+ table.remove(self.startOrder, index + 1)
247
+ end
248
+ self:forget(object)
249
+ end
250
+ function LifecycleProvider:postIgnite(module)
251
+ -- Walked live rather than over a copy: an `onInit` may resolve a lazy provider, which joins
252
+ -- the end of the list while we iterate and is initialised in its turn -- over a copy it was
253
+ -- skipped, and then started with the rest, never initialised. Nothing leaves the list
254
+ -- during ignition, so the index stays true. A `while`, since a `for` compiles to a numeric
255
+ -- loop that reads the length once.
256
+ local index = 0
257
+ while index < #self.onInit do
258
+ self:runInit(self.onInit[index + 1])
259
+ index += 1
260
+ end
261
+ self.hasStarted = true
262
+ local _array = {}
263
+ local _length = #_array
264
+ local _array_1 = self.startOrder
265
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
266
+ for _, object in _array do
267
+ self:runStart(object)
268
+ end
269
+ local onTick = self.onTick
270
+ local onPhysics = self.onPhysics
271
+ local onRender = self.onRender
272
+ local connections = {}
273
+ -- Heartbeat rather than PostSimulation: the same point of the frame in a running game, but
274
+ -- Heartbeat also fires where no simulation runs (an edit-mode plugin, an Open Cloud Luau
275
+ -- task), so onTick works there too. PreSimulation has no such alias; onPhysics stays silent.
276
+ local _arg0 = RunService.Heartbeat:Connect(function(dt)
277
+ for provider in onTick do
278
+ self:profile(function()
279
+ return provider:onTick(dt)
280
+ end, provider)
281
+ end
282
+ end)
283
+ table.insert(connections, _arg0)
284
+ local _arg0_1 = RunService.PreSimulation:Connect(function(dt)
285
+ local now = time()
286
+ for provider in onPhysics do
287
+ self:profile(function()
288
+ return provider:onPhysics(dt, now)
289
+ end, provider)
290
+ end
291
+ end)
292
+ table.insert(connections, _arg0_1)
293
+ -- PreRender never fires on the server, so there is nothing to connect there.
294
+ if RunService:IsClient() then
295
+ local _arg0_2 = RunService.PreRender:Connect(function(dt)
296
+ for provider in onRender do
297
+ self:profile(function()
298
+ return provider:onRender(dt)
299
+ end, provider)
300
+ end
301
+ end)
302
+ table.insert(connections, _arg0_2)
303
+ end
304
+ local _moduleConnections = self.moduleConnections
305
+ local _module = module
306
+ _moduleConnections[_module] = connections
307
+ end
308
+ function LifecycleProvider:extinguished(module)
309
+ local _moduleConnections = self.moduleConnections
310
+ local _module = module
311
+ local connections = _moduleConnections[_module]
312
+ if connections then
313
+ local _moduleConnections_1 = self.moduleConnections
314
+ local _module_1 = module
315
+ _moduleConnections_1[_module_1] = nil
316
+ for _, connection in connections do
317
+ connection:Disconnect()
318
+ end
319
+ end
320
+ -- Over a copy, since a handler may detach objects; one detached by a handler before it --
321
+ -- `removeClassInstance` from an `onExtinguished` -- has left the event, so it is not told.
322
+ -- One failing handler must not leave the module stuck half-extinguished.
323
+ local _array = {}
324
+ local _length = #_array
325
+ for _v in self.onExtinguished do
326
+ _length += 1
327
+ _array[_length] = _v
328
+ end
329
+ for _, provider in _array do
330
+ if not (self.onExtinguished[provider] ~= nil) then
331
+ continue
332
+ end
333
+ local success, err = pcall(function()
334
+ return provider:onExtinguished()
335
+ end)
336
+ if not success then
337
+ warn(`[Flamework] onExtinguished failed for '{self:getIdentifier(provider)}': {tostring(err)}`)
338
+ end
339
+ end
340
+ end
341
+ do
342
+ -- (Flamework) LifecycleProvider metadata
343
+ Reflect_1.defineMetadata(LifecycleProvider, "identifier", "$:lifecycle/lifecyclePlugin@LifecycleProvider")
344
+ Reflect_1.defineMetadata(LifecycleProvider, "flamework:implements", {})
345
+ Reflect_1.defineMetadata(LifecycleProvider, "flamework:parameters", { "$:lifecycle/lifecyclePlugin@LifecyclePluginOptions" })
346
+ Reflect_1.defineMetadata(LifecycleProvider, "flamework:dependencies", { {
347
+ id = "$:lifecycle/lifecyclePlugin@LifecyclePluginOptions",
348
+ } })
349
+ end
350
+ LifecycleProvider = Provider()(LifecycleProvider) or LifecycleProvider
351
+ end
352
+ --* An observer that keeps one of the provider's plain event sets in step with the module.
353
+ local function observeSet(provider, set)
354
+ return {
355
+ onAdded = function(value)
356
+ local _set = set
357
+ local _value = value
358
+ _set[_value] = true
359
+ return _set
360
+ end,
361
+ onRemoved = function(value)
362
+ return provider:removeFrom(set, value)
363
+ end,
364
+ }
365
+ end
366
+ --[[
367
+ *
368
+ * Creates a lifecycle plugin with the specified options.
369
+ *
370
+ * `LifecyclePlugin` is `createLifecyclePlugin()` with the defaults; use this when a module needs
371
+ * different ones, such as forcing profiling on or off.
372
+
373
+ ]]
374
+ local function createLifecyclePlugin(options)
375
+ if options == nil then
376
+ options = {}
377
+ end
378
+ local setup = function(target)
379
+ -- One per ignition: the setup runs for every module that includes the plugin, and again for
380
+ -- every ignition of a definition, so nothing here is shared between modules.
381
+ local lifecycle = LifecycleProvider.new(options)
382
+ target.provideInstance(lifecycle, "$:lifecycle/lifecyclePlugin@LifecycleProvider")
383
+ target.onPostIgnite(function(module)
384
+ return lifecycle:postIgnite(module)
385
+ end)
386
+ target.onExtinguished(function(module)
387
+ return lifecycle:extinguished(module)
388
+ end)
389
+ target.observe({
390
+ onAdded = function(value, context)
391
+ return lifecycle:addInit(value, context)
392
+ end,
393
+ onRemoved = function(value)
394
+ return lifecycle:removeInit(value)
395
+ end,
396
+ }, "$:lifecycle/lifecycleInterfaces@OnInit")
397
+ target.observe({
398
+ onAdded = function(value, context)
399
+ return lifecycle:addStart(value, context)
400
+ end,
401
+ onRemoved = function(value)
402
+ return lifecycle:removeStart(value)
403
+ end,
404
+ }, "$:lifecycle/lifecycleInterfaces@OnStart")
405
+ target.observe(observeSet(lifecycle, lifecycle.onTick), "$:lifecycle/lifecycleInterfaces@OnTick")
406
+ target.observe(observeSet(lifecycle, lifecycle.onRender), "$:lifecycle/lifecycleInterfaces@OnRender")
407
+ target.observe(observeSet(lifecycle, lifecycle.onPhysics), "$:lifecycle/lifecycleInterfaces@OnPhysics")
408
+ target.observe(observeSet(lifecycle, lifecycle.onExtinguished), "$:lifecycle/lifecycleInterfaces@OnExtinguished")
409
+ end
410
+ return PluginDefinition.new("Lifecycle", setup, LIFECYCLE_SLOT)
411
+ end
412
+ --[[
413
+ *
414
+ * The lifecycle plugin with default options. Every module made with `Flamework.createModule()`
415
+ * starts with it; `disableDefaultLifecycle()` on the builder leaves it out, and including one built
416
+ * with {@link createLifecyclePlugin} takes its place.
417
+
418
+ ]]
419
+ local LifecyclePlugin = createLifecyclePlugin()
420
+ return {
421
+ createLifecyclePlugin = createLifecyclePlugin,
422
+ LifecycleProvider = LifecycleProvider,
423
+ LifecyclePlugin = LifecyclePlugin,
424
+ }
@@ -0,0 +1,171 @@
1
+ import { t } from "@rbxts/t";
2
+ export declare namespace Modding {
3
+ /**
4
+ * This function is able to utilize Flamework's user macros to generate and inspect types.
5
+ * This function supports all values natively supported by Flamework's user macros.
6
+ *
7
+ * For example, if you want to retrieve the properties of an instance, you could write code like this:
8
+ * ```ts
9
+ * // Returns an array of all keys part of the union.
10
+ * const basePartKeys = Modding.inspect<InstancePropertyNames<BasePart>[]>();
11
+ * ```
12
+ *
13
+ * @metadata macro
14
+ */
15
+ export function inspect<T>(value?: Modding.Emit<T>): T;
16
+ /**
17
+ * This type emits runtime equivalents of types, such as generating strings from string literal types.
18
+ *
19
+ * You are able to generate most TS types, including objects and tuples which will generate equivalent objects at runtime.
20
+ * Additionally, you can generate unions by using `Array<T>`, which will generate an array where each constituent of `T` is its own element.
21
+ *
22
+ * This type is primarily used to mark a user macro parameter as metadata, and is not necessary if you use other macro types.
23
+ */
24
+ export type Emit<T> = T & {
25
+ /** @hidden */ _flamework_macro_many: T;
26
+ };
27
+ /**
28
+ * Creates an injectable type that can be used to modify dependency injection behavior.
29
+ */
30
+ export type Injectable<C extends {
31
+ type: unknown;
32
+ id?: unknown;
33
+ metadata?: unknown[];
34
+ }> = RealType<C["type"]> & {
35
+ /** @hidden @deprecated */
36
+ _flamework_injectable: C;
37
+ };
38
+ /**
39
+ * An internal type for intrinsic user macro metadata.
40
+ *
41
+ * @hidden
42
+ */
43
+ export type Intrinsic<N extends string, M extends unknown[], T = symbol> = T & {
44
+ _flamework_intrinsic: [N, ...M];
45
+ };
46
+ /**
47
+ * This namespace contains types and metadata related to the current macro's callsite.
48
+ */
49
+ export namespace Caller {
50
+ /**
51
+ * Retrieves metadata about the callsite using Flamework's user macros.
52
+ */
53
+ type CallerHelper<U, M extends string> = U & {
54
+ /** @hidden */ _flamework_macro_caller: M;
55
+ };
56
+ /**
57
+ * The starting line of the expression in the TypeScript source, starting at 1.
58
+ */
59
+ export type Line = CallerHelper<number, "line">;
60
+ /**
61
+ * The char at the start of the expression relative to the starting line, starting at 1.
62
+ */
63
+ export type Character = CallerHelper<number, "character">;
64
+ /**
65
+ * The width of the expression.
66
+ * This includes the width of multiline statements.
67
+ */
68
+ export type Width = CallerHelper<number, "width">;
69
+ /**
70
+ * A unique identifier that can be used to identify exact callsites.
71
+ * This can be used for hooks.
72
+ *
73
+ * Derived from the callsite's position, so it is the same in every file of one build and,
74
+ * without obfuscation, across builds. With obfuscation on it changes with every build, so
75
+ * that what it names -- a remote, say -- cannot be mapped once and found again in the next
76
+ * release.
77
+ */
78
+ export type Uuid = CallerHelper<string, "uuid">;
79
+ /**
80
+ * The source text for the expression.
81
+ */
82
+ export type Text = CallerHelper<string, "text">;
83
+ /**
84
+ * This API will generate a constant reference to the nested metadata.
85
+ * This means that the same object will be passed in for every invocation of a specific function call.
86
+ *
87
+ * This can be used to implement caching, and avoid allocation overhead for large metadata.
88
+ */
89
+ export type Constant<T> = T & {
90
+ /** @hidden */ _flamework_macro_shared_ref: T;
91
+ };
92
+ export {};
93
+ }
94
+ /**
95
+ * This namespace contains types that allow you to perform functions or fetch metadata about specific types.
96
+ */
97
+ export namespace Target {
98
+ type TargetHelper<T, U, M extends string> = U & {
99
+ /** @hidden */ _flamework_macro_generic: [T, M];
100
+ };
101
+ /**
102
+ * Retrieves the ID from the type.
103
+ *
104
+ * The ID is a mostly unique identifier meant to identify specific resources in Flamework projects, such as providers.
105
+ */
106
+ export type Id<T> = TargetHelper<T, string, "id">;
107
+ /**
108
+ * Retrieves the text of the type, equivalent to what is seen in TypeScript's intellisense.
109
+ *
110
+ * The resulting text may not be identical as the type inputted as its dependent on how TypeScript renders types.
111
+ */
112
+ export type Text<T> = TargetHelper<T, string, "text">;
113
+ /**
114
+ * Retrieves a `t` guard that matches this specific type.
115
+ */
116
+ export type Guard<T> = TargetHelper<T, t.check<T>, "guard">;
117
+ /**
118
+ * Retrieves the dependency info for this type, which contains the ID and any metadata included on the type.
119
+ */
120
+ export type Dependency<T> = TargetHelper<T, DependencyInfo, "dependency">;
121
+ /**
122
+ * Retrieves the dependency info for this type, which contains the ID and any metadata included on the type.
123
+ *
124
+ * This is equivalent to the {@link Dependency} type, except it will shorten itself to a string (the type's ID) if possible.
125
+ */
126
+ export type DependencyConcise<T> = TargetHelper<T, DependencyInfo | string, "dependencyConcise">;
127
+ /**
128
+ * Retrieves the labels from this tuple.
129
+ *
130
+ * This can also be used to extract parameter names via `Parameters<T>`
131
+ */
132
+ export type Labels<T extends readonly unknown[]> = (string[] & {
133
+ _flamework_macro_tuple_labels: T;
134
+ }) | undefined;
135
+ /**
136
+ * Hashes a string literal type (such as an event name.)
137
+ *
138
+ * The second type argument, `C`, is for providing a context to the hashing which will generate new hashes
139
+ * for strings which already have a hash under another context.
140
+ */
141
+ export type Hash<T extends string, C extends string = never> = string & {
142
+ /** @hidden */ _flamework_macro_hash: [T, C];
143
+ };
144
+ /**
145
+ * This is equivalent to {@link Hash `Hash`} except it will only hash strings when `obfuscation` is turned on.
146
+ */
147
+ export type Obfuscate<T extends string, C extends string = never> = string & {
148
+ /** @hidden */ _flamework_macro_hash: [T, C, true];
149
+ };
150
+ export {};
151
+ }
152
+ /**
153
+ * Information about an injected dependency.
154
+ */
155
+ export interface DependencyInfo {
156
+ /**
157
+ * The ID used to resolve this dependency.
158
+ */
159
+ id: string;
160
+ /**
161
+ * Metadata provided by the injectable type.
162
+ */
163
+ metadata?: unknown[];
164
+ }
165
+ type RealType<T> = T extends {
166
+ _flamework_injectable: {
167
+ type: infer R;
168
+ };
169
+ } ? RealType<R> : T;
170
+ export {};
171
+ }