@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,12 @@
1
+ /**
2
+ * Finds the `include/flamework` folder that holds a metadata module written by the transformer
3
+ * (`include/flamework/<name>.json`), by walking up from this script until a `flamework` folder
4
+ * with the requested child is found. The include directory is an ancestor of every Flamework
5
+ * package in a roblox-ts project, which is what makes this work.
6
+ */
7
+ export declare function findMetadataFolder(name: string): Instance | undefined;
8
+ /**
9
+ * Finds and requires a metadata module written by the transformer; Rojo turns the JSON file into a
10
+ * ModuleScript returning its table.
11
+ */
12
+ export declare function findMetadataContainer<T>(name: string): T | undefined;
@@ -0,0 +1,43 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --[[
3
+ *
4
+ * Finds the `include/flamework` folder that holds a metadata module written by the transformer
5
+ * (`include/flamework/<name>.json`), by walking up from this script until a `flamework` folder
6
+ * with the requested child is found. The include directory is an ancestor of every Flamework
7
+ * package in a roblox-ts project, which is what makes this work.
8
+
9
+ ]]
10
+ local function findMetadataFolder(name)
11
+ -- Outside a real place (the Lune harness) `script` is a plain table: there is no tree to walk.
12
+ if not (typeof(script) == "Instance") then
13
+ return nil
14
+ end
15
+ local current = script
16
+ while current do
17
+ local flamework = current:FindFirstChild("flamework")
18
+ if flamework then
19
+ local metadata = flamework:FindFirstChild(name)
20
+ if metadata and metadata:IsA("ModuleScript") then
21
+ return flamework
22
+ end
23
+ end
24
+ current = current.Parent
25
+ end
26
+ end
27
+ --[[
28
+ *
29
+ * Finds and requires a metadata module written by the transformer; Rojo turns the JSON file into a
30
+ * ModuleScript returning its table.
31
+
32
+ ]]
33
+ local function findMetadataContainer(name)
34
+ local folder = findMetadataFolder(name)
35
+ if folder == nil then
36
+ return nil
37
+ end
38
+ return require(folder:FindFirstChild(name))
39
+ end
40
+ return {
41
+ findMetadataFolder = findMetadataFolder,
42
+ findMetadataContainer = findMetadataContainer,
43
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The instance every compile-time path is relative to: `game` in a place, and the Rojo tree's own
3
+ * root in a model or a Studio plugin, whose tree hangs off no service.
4
+ *
5
+ * The transformer emits paths relative to the tree's root, and records in `paths.json` how far
6
+ * below that root the include folder sits; the root is found once by climbing that far from the
7
+ * folder the metadata was found in. With no metadata -- a package on its own, the test harness --
8
+ * it is `game`.
9
+ */
10
+ export declare function getPathRoot(): Instance;
11
+ /**
12
+ * Walks a compile-time path from {@link getPathRoot}, waiting for each child in turn.
13
+ *
14
+ * Under `game` the first segment names a service, and `StarterPlayer/StarterPlayerScripts` is
15
+ * answered from the local player's `PlayerScripts`, which is where that content actually runs.
16
+ */
17
+ export declare function resolveRbxPath(rbxPath: readonly string[]): Instance;
@@ -0,0 +1,105 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _services = TS.import(script, TS.getModule(script, "@rbxts", "services"))
4
+ local Players = _services.Players
5
+ local RunService = _services.RunService
6
+ local StarterPlayer = _services.StarterPlayer
7
+ local _metadata = TS.import(script, script.Parent, "metadata")
8
+ local findMetadataContainer = _metadata.findMetadataContainer
9
+ local findMetadataFolder = _metadata.findMetadataFolder
10
+ --* The shape of `include/flamework/paths.json`, which the transformer writes for game and plugin projects.
11
+ local cached
12
+ local override
13
+ --[[
14
+ *
15
+ * The instance every compile-time path is relative to: `game` in a place, and the Rojo tree's own
16
+ * root in a model or a Studio plugin, whose tree hangs off no service.
17
+ *
18
+ * The transformer emits paths relative to the tree's root, and records in `paths.json` how far
19
+ * below that root the include folder sits; the root is found once by climbing that far from the
20
+ * folder the metadata was found in. With no metadata -- a package on its own, the test harness --
21
+ * it is `game`.
22
+
23
+ ]]
24
+ local function getPathRoot()
25
+ if override ~= nil then
26
+ return override
27
+ end
28
+ if cached == nil then
29
+ cached = game
30
+ local folder = findMetadataFolder("paths")
31
+ local paths = findMetadataContainer("paths")
32
+ if folder ~= nil and paths ~= nil then
33
+ -- The folder is `include/flamework`; its parent is the include folder itself.
34
+ local node = folder.Parent
35
+ do
36
+ local i = 0
37
+ local _shouldIncrement = false
38
+ while true do
39
+ if _shouldIncrement then
40
+ i += 1
41
+ else
42
+ _shouldIncrement = true
43
+ end
44
+ if not (i < paths.includeDepth and node ~= nil) then
45
+ break
46
+ end
47
+ node = node.Parent
48
+ end
49
+ end
50
+ if node ~= nil then
51
+ cached = node
52
+ end
53
+ end
54
+ end
55
+ return cached
56
+ end
57
+ --[[
58
+ *
59
+ * Walks a compile-time path from {@link getPathRoot}, waiting for each child in turn.
60
+ *
61
+ * Under `game` the first segment names a service, and `StarterPlayer/StarterPlayerScripts` is
62
+ * answered from the local player's `PlayerScripts`, which is where that content actually runs.
63
+
64
+ ]]
65
+ local function resolveRbxPath(rbxPath)
66
+ -- Copied so that a generated path literal is not consumed by this call.
67
+ local _array = {}
68
+ local _length = #_array
69
+ table.move(rbxPath, 1, #rbxPath, _length + 1, _array)
70
+ local path = _array
71
+ local node = getPathRoot()
72
+ if node == game then
73
+ local serviceName = table.remove(path, 1)
74
+ local _arg0 = serviceName ~= nil
75
+ assert(_arg0, "a path under game has to name a service first")
76
+ node = game:GetService(serviceName)
77
+ if node == StarterPlayer then
78
+ local _arg0_1 = table.remove(path, 1) == "StarterPlayerScripts"
79
+ assert(_arg0_1, "StarterPlayer only supports StarterPlayerScripts")
80
+ local _arg0_2 = RunService:IsClient()
81
+ assert(_arg0_2, "The server cannot load StarterPlayer content")
82
+ node = Players.LocalPlayer:WaitForChild("PlayerScripts")
83
+ end
84
+ end
85
+ for _, segment in path do
86
+ node = node:WaitForChild(segment)
87
+ end
88
+ return node
89
+ end
90
+ --[[
91
+ *
92
+ * Replaces the root paths resolve from, or restores the discovered one with `undefined`. For the
93
+ * test harness, which has no tree to discover it in.
94
+ *
95
+ * @internal
96
+
97
+ ]]
98
+ local function __setPathRoot(root)
99
+ override = root
100
+ end
101
+ return {
102
+ getPathRoot = getPathRoot,
103
+ resolveRbxPath = resolveRbxPath,
104
+ __setPathRoot = __setPathRoot,
105
+ }
@@ -0,0 +1 @@
1
+ export declare function recycleThread(func: () => void): void;
@@ -0,0 +1,31 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local inactiveThread
3
+ local function reusableThread(func)
4
+ local thread = coroutine.running()
5
+ while true do
6
+ if inactiveThread == thread then
7
+ inactiveThread = nil
8
+ end
9
+ func()
10
+ -- If there's a different idle thread, we should end the current thread.
11
+ if inactiveThread ~= nil then
12
+ break
13
+ end
14
+ inactiveThread = thread
15
+ -- Let go of the callback while idle: it closes over whatever it was run for -- a lifecycle
16
+ -- listener, a component -- which would otherwise stay reachable from this thread until the
17
+ -- next callback comes through, and for good when none does.
18
+ func = nil
19
+ func = coroutine.yield()
20
+ end
21
+ end
22
+ local function recycleThread(func)
23
+ if inactiveThread then
24
+ task.spawn(inactiveThread, func)
25
+ else
26
+ task.spawn(reusableThread, func)
27
+ end
28
+ end
29
+ return {
30
+ recycleThread = recycleThread,
31
+ }
@@ -0,0 +1,59 @@
1
+ export interface CoreRuntimeConfig {
2
+ /** Whether lifecycle events are wrapped in `debug.profilebegin`. Defaults to running in Studio. */
3
+ profiling?: boolean;
4
+ }
5
+ export interface NetworkingRuntimeConfig {
6
+ /** Whether event and function payloads are serialized. Compiled into the metadata; informational at runtime. */
7
+ serialization?: boolean;
8
+ }
9
+ export interface ComponentsRuntimeConfig {
10
+ /** Default `warningTimeout` for components that do not set one. */
11
+ warningTimeout?: number;
12
+ /** Default `attributeWarningTimeout` for components that do not set one. */
13
+ attributeWarningTimeout?: number;
14
+ /** Default `streamingMode` for components that do not set one. */
15
+ streamingMode?: "Disabled" | "Watching" | "Contextual";
16
+ }
17
+ export interface ScopesRuntimeConfig {
18
+ /**
19
+ * The scopes this build was compiled with, usually taken from the environment at compile time.
20
+ * `"*"` stands for every scope. Read by the scope checks in `@flamework-experimental/core`.
21
+ */
22
+ active?: string[];
23
+ }
24
+ export interface TestingRuntimeConfig {
25
+ /**
26
+ * Whether the plugin attaches the host at all. Unset, it follows the scope condition below, so
27
+ * this is an override for either direction.
28
+ */
29
+ enabled?: boolean;
30
+ /** Scopes under which tests are on: the host attaches when at least one is active. Default `["testing"]`. */
31
+ activeIn?: readonly string[];
32
+ /** Scopes under which tests stay off, whatever else is active. */
33
+ inactiveIn?: readonly string[];
34
+ /** Runs every test right after ignition, instead of only on request. */
35
+ autoRun?: boolean;
36
+ /** Seconds a single test may take before it is cancelled and counted as failed. */
37
+ timeout?: number;
38
+ /**
39
+ * The tree path of a ModuleScript exporting `ignite()`, resolved by the transformer from the
40
+ * source path in `flamework.config.json`, for runs where nothing starts the game by itself.
41
+ */
42
+ entry?: readonly string[];
43
+ }
44
+ /**
45
+ * The runtime sections of the project's `flamework.config.json`. The transformer writes them to
46
+ * `include/flamework/config.json` for game projects; a project without them gets an empty object.
47
+ */
48
+ export interface RuntimeConfig {
49
+ core?: CoreRuntimeConfig;
50
+ networking?: NetworkingRuntimeConfig;
51
+ components?: ComponentsRuntimeConfig;
52
+ scopes?: ScopesRuntimeConfig;
53
+ testing?: TestingRuntimeConfig;
54
+ }
55
+ /**
56
+ * Returns the runtime sections of `flamework.config.json`, read once. Every package takes its
57
+ * defaults from here, so one file configures the transformer and the runtime alike.
58
+ */
59
+ export declare function getRuntimeConfig(): RuntimeConfig;
@@ -0,0 +1,25 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local findMetadataContainer = TS.import(script, script.Parent, "metadata").findMetadataContainer
4
+ --[[
5
+ *
6
+ * The runtime sections of the project's `flamework.config.json`. The transformer writes them to
7
+ * `include/flamework/config.json` for game projects; a project without them gets an empty object.
8
+
9
+ ]]
10
+ local cached
11
+ --[[
12
+ *
13
+ * Returns the runtime sections of `flamework.config.json`, read once. Every package takes its
14
+ * defaults from here, so one file configures the transformer and the runtime alike.
15
+
16
+ ]]
17
+ local function getRuntimeConfig()
18
+ if cached == nil then
19
+ cached = findMetadataContainer("config") or {}
20
+ end
21
+ return cached
22
+ end
23
+ return {
24
+ getRuntimeConfig = getRuntimeConfig,
25
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * This imports the module using the current TS runtime.
3
+ *
4
+ * This is necessary when loading packages which must be imported using the RuntimeLib.
5
+ */
6
+ export declare function tsImport(module: ModuleScript): unknown;
@@ -0,0 +1,15 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local tsImpl = _G[script]
3
+ --[[
4
+ *
5
+ * This imports the module using the current TS runtime.
6
+ *
7
+ * This is necessary when loading packages which must be imported using the RuntimeLib.
8
+
9
+ ]]
10
+ local function tsImport(module)
11
+ return tsImpl.import(script, module)
12
+ end
13
+ return {
14
+ tsImport = tsImport,
15
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Alias for destructors, which is just a callback.
3
+ */
4
+ export type Destructor = () => void;
5
+ /**
6
+ * Checks whether `T` is a union.
7
+ */
8
+ export type IsUnion<T, U = T> = T extends T ? (U extends T ? false : true) : never;
9
+ /**
10
+ * Checks whether this interface contains a single field, which is also a Callback.
11
+ */
12
+ export type HasSingleCallback<T> = [IsUnion<keyof T>, T[keyof T]] extends [false, Callback] ? true : false;
13
+ /**
14
+ * If this interface contains a single callback, extract its type.
15
+ */
16
+ export type ExtractSingleCallback<T> = HasSingleCallback<T> extends true ? T[keyof T] : never;
@@ -0,0 +1,22 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ --[[
3
+ *
4
+ * Alias for destructors, which is just a callback.
5
+
6
+ ]]
7
+ --[[
8
+ *
9
+ * Checks whether `T` is a union.
10
+
11
+ ]]
12
+ --[[
13
+ *
14
+ * Checks whether this interface contains a single field, which is also a Callback.
15
+
16
+ ]]
17
+ --[[
18
+ *
19
+ * If this interface contains a single callback, extract its type.
20
+
21
+ ]]
22
+ return nil
@@ -0,0 +1,4 @@
1
+ export type ToWritable<T> = T extends ReadonlySet<infer V> ? Set<V> : T extends ReadonlyMap<infer K, infer V> ? Map<K, V> : Writable<T>;
2
+ export type WritableState<T> = Writable<{
3
+ [k in keyof T]: ToWritable<T[k]>;
4
+ }>;
@@ -0,0 +1,2 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ return nil
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@flamework-experimental/core",
3
+ "version": "2.0.0-alpha.0",
4
+ "main": "out/init.luau",
5
+ "types": "out/index.d.ts",
6
+ "scripts": {
7
+ "build": "rbxtsc",
8
+ "watch": "rbxtsc -w"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/rbxts-flamework/core.git"
13
+ },
14
+ "files": [
15
+ "out",
16
+ "flamework.build"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "devDependencies": {
22
+ "@rbxts/compiler-types": "^3.0.0-types.0",
23
+ "@rbxts/types": "^1.0.948",
24
+ "roblox-ts": "^3.0.0"
25
+ },
26
+ "dependencies": {
27
+ "@rbxts/maid": "^1.0.0-ts.1",
28
+ "@rbxts/object-utils": "^1.0.4",
29
+ "@rbxts/services": "^1.1.4",
30
+ "@rbxts/signal": "^1.0.3",
31
+ "@rbxts/t": "^3.1.0"
32
+ }
33
+ }