@flamework-experimental/transformer 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 (72) hide show
  1. package/README.md +66 -0
  2. package/flamework-schema.json +76 -0
  3. package/flamework.config.schema.json +197 -0
  4. package/out/classes/buildInfo.js +467 -0
  5. package/out/classes/diagnostics.js +110 -0
  6. package/out/classes/logger.js +201 -0
  7. package/out/classes/nodeMetadata.js +232 -0
  8. package/out/classes/transformState.js +623 -0
  9. package/out/index.js +75 -0
  10. package/out/transformations/expressions/transformAccessExpression.js +35 -0
  11. package/out/transformations/expressions/transformBinaryExpression.js +57 -0
  12. package/out/transformations/expressions/transformCallExpression.js +33 -0
  13. package/out/transformations/expressions/transformDeleteExpression.js +22 -0
  14. package/out/transformations/expressions/transformNewExpression.js +17 -0
  15. package/out/transformations/expressions/transformUnaryExpression.js +63 -0
  16. package/out/transformations/macros/intrinsics/components.js +64 -0
  17. package/out/transformations/macros/intrinsics/env.js +31 -0
  18. package/out/transformations/macros/intrinsics/guards.js +43 -0
  19. package/out/transformations/macros/intrinsics/inlining.js +22 -0
  20. package/out/transformations/macros/intrinsics/networking.js +131 -0
  21. package/out/transformations/macros/intrinsics/parameters.js +81 -0
  22. package/out/transformations/macros/intrinsics/paths.js +42 -0
  23. package/out/transformations/macros/updateComponentConfig.js +409 -0
  24. package/out/transformations/plugins/nodeFactory.js +159 -0
  25. package/out/transformations/plugins/pluginHost.js +235 -0
  26. package/out/transformations/plugins/typeFacade.js +242 -0
  27. package/out/transformations/statements/transformClassDeclaration.js +282 -0
  28. package/out/transformations/transformExpression.js +34 -0
  29. package/out/transformations/transformFile.js +78 -0
  30. package/out/transformations/transformNetworkingCall.js +566 -0
  31. package/out/transformations/transformNode.js +27 -0
  32. package/out/transformations/transformStatement.js +57 -0
  33. package/out/transformations/transformStatementList.js +64 -0
  34. package/out/transformations/transformUserMacro.js +698 -0
  35. package/out/transformer.js +52 -0
  36. package/out/util/cache.js +10 -0
  37. package/out/util/constants.js +5 -0
  38. package/out/util/diagnosticsUtils.js +112 -0
  39. package/out/util/env.js +267 -0
  40. package/out/util/factory.js +583 -0
  41. package/out/util/functions/addLeadingComment.js +13 -0
  42. package/out/util/functions/arePathsEqual.js +14 -0
  43. package/out/util/functions/assert.js +17 -0
  44. package/out/util/functions/buildGuardFromType.js +713 -0
  45. package/out/util/functions/buildInstanceShape.js +156 -0
  46. package/out/util/functions/buildSerializerFromType.js +2309 -0
  47. package/out/util/functions/createPathTranslator.js +54 -0
  48. package/out/util/functions/emitTypescriptMismatch.js +80 -0
  49. package/out/util/functions/getDeclarationName.js +23 -0
  50. package/out/util/functions/getDeclarationOfType.js +7 -0
  51. package/out/util/functions/getIndexExpression.js +16 -0
  52. package/out/util/functions/getInstanceTypeFromType.js +75 -0
  53. package/out/util/functions/getNodeList.js +6 -0
  54. package/out/util/functions/getPackageJson.js +44 -0
  55. package/out/util/functions/getSuperClasses.js +51 -0
  56. package/out/util/functions/isAttributesAccess.js +23 -0
  57. package/out/util/functions/isCleanBuildDirectory.js +13 -0
  58. package/out/util/functions/isDefinedType.js +16 -0
  59. package/out/util/functions/isPathDescendantOf.js +25 -0
  60. package/out/util/functions/isTupleType.js +10 -0
  61. package/out/util/functions/parseCommandLine.js +31 -0
  62. package/out/util/functions/shuffle.js +39 -0
  63. package/out/util/functions/tryResolve.js +15 -0
  64. package/out/util/functions/validateConstraintMetadata.js +60 -0
  65. package/out/util/packages.js +12 -0
  66. package/out/util/projectConfig.js +221 -0
  67. package/out/util/schema.js +80 -0
  68. package/out/util/tsInternals.js +16 -0
  69. package/out/util/uid.js +227 -0
  70. package/package.json +45 -0
  71. package/rojo-schema.json +34 -0
  72. package/types.d.ts +4 -0
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Flamework
2
+
3
+ Flamework is an extensible framework for roblox-ts designed around portable, isolated and testable modules.
4
+
5
+ ## Documentation
6
+
7
+ **[docs/](docs/README.md)** -- start there. A ten-part guide that builds up from a working entry
8
+ point to plugins and project layout, plus reference material:
9
+
10
+ | | |
11
+ |---|---|
12
+ | [Guide](docs/README.md#guide) | Getting started, modules, providers, lifecycle events, components, networking, macros, plugins, project structure, migrating from v1. |
13
+ | [Internals](docs/reference/internals.md) | What the transformer does to your code and what the runtime does with the result. |
14
+ | [Transformer plugins](docs/reference/transformer-plugins.md) | Adding macro types of your own. |
15
+
16
+ The Flamework website documents v1, most of which no longer applies:
17
+
18
+ https://flamework.fireboltofdeath.dev/docs/introduction
19
+
20
+ ## Development
21
+
22
+ This repository is a [Bun](https://bun.sh) workspace. It also needs
23
+ [Lune](https://lune-org.github.io/docs) on `PATH` to run the runtime specs.
24
+
25
+ ```sh
26
+ bun install
27
+ bun run build # builds every package in dependency order
28
+ bun run test # build + transformer tests + runtime specs
29
+ bun run lint
30
+ ```
31
+
32
+ ### Packages
33
+
34
+ | Package | Description |
35
+ |---|---|
36
+ | `packages/core` | Modules, dependency injection, plugins and lifecycle events |
37
+ | `packages/components` | CollectionService components, built on the core plugin system |
38
+ | `packages/networking` | Remote events and functions |
39
+ | `packages/testing` | In-place tests: sections, cleanup, a bindable and a remote to run them, a cloud entry; and `flamework-test`, the CLI that runs them in Roblox Studio on this machine or through Open Cloud (`cli/`) |
40
+ | `packages/transformer` | The roblox-ts transformer |
41
+ | `packages/transformer-plugin` | Public API for writing transformer plugins |
42
+ | `packages/specs` | Runtime specs, compiled by `rbxtsc` and executed under Lune |
43
+
44
+ ### Tests
45
+
46
+ Two suites, both run by `bun run test`:
47
+
48
+ - **Transformer tests** (`bun run test:unit`) compile a fixture project with the real `rbxtsc` and
49
+ assert on the emitted Luau — guard generation, identifiers, nested macros and the plugin system.
50
+ - **Runtime specs** (`bun run test:runtime`) execute compiled `@flamework-experimental/core`, `components` and
51
+ `networking` under Lune using the harness in [`tests/runtime`](tests/runtime), which models
52
+ roblox-ts's `TS.import` tree over the filesystem and stubs the Roblox API surface Flamework
53
+ touches (Instances, attributes, CollectionService, RemoteEvents, Players, signals, `task`,
54
+ `Enum`, and a `Heartbeat` pump so `Promise.delay` -- and therefore request timeouts -- runs).
55
+ They cover dependency injection, modules, hooks and the per-frame lifecycle events, component
56
+ construction, dependencies and streaming, and both halves of networking: events, functions,
57
+ middleware and the generated guards.
58
+
59
+ They run twice, once as `Server` and once as `Client`, because realm-dependent code paths --
60
+ `@Provider`'s metadata, component streaming, and the client/server halves of networking -- differ
61
+ between them. Where a spec asserts something realm-specific, running it from both sides is what
62
+ proves the two agree: a function receives on `$name` and sends on `@name` from the server and the
63
+ mirror image from the client, so the pair of runs pins the wire format down from both ends.
64
+
65
+ Specs live in [`packages/specs`](packages/specs) and are compiled by `rbxtsc` like any other
66
+ Flamework consumer, so they exercise the transformer and the runtime together.
@@ -0,0 +1,76 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "#root",
4
+ "type": "object",
5
+ "properties": {
6
+ "globs": {
7
+ "$id": "globs",
8
+ "type": "object",
9
+ "properties": {
10
+ "paths": {
11
+ "type": "object",
12
+ "additionalProperties": {
13
+ "type": "array",
14
+ "items": {
15
+ "type": "string"
16
+ }
17
+ }
18
+ },
19
+ "origins": {
20
+ "type": "object",
21
+ "additionalProperties": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "string"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ },
30
+ "buildInfo": {
31
+ "$id": "buildInfo",
32
+ "required": ["version", "flameworkVersion", "identifiers"],
33
+ "type": "object",
34
+ "properties": {
35
+ "version": {
36
+ "type": "number"
37
+ },
38
+ "flameworkVersion": {
39
+ "type": "string"
40
+ },
41
+ "identifierPrefix": {
42
+ "type": "string"
43
+ },
44
+ "idGenerationMode": {
45
+ "type": "string"
46
+ },
47
+ "buildSeed": {
48
+ "type": "string"
49
+ },
50
+ "identifiers": {
51
+ "type": "object",
52
+ "additionalProperties": {
53
+ "type": "string"
54
+ }
55
+ },
56
+ "salt": {
57
+ "type": "string"
58
+ },
59
+ "stringHashes": {
60
+ "type": "object",
61
+ "additionalProperties": {
62
+ "type": "string"
63
+ }
64
+ },
65
+ "metadata": {
66
+ "type": "object",
67
+ "properties": {
68
+ "globs": {
69
+ "$ref": "globs"
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,197 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "flamework.config.schema.json",
4
+ "title": "Flamework project configuration",
5
+ "description": "One file for every Flamework package, read from flamework.config.json next to (or above) your tsconfig.json. The transformer section can also be written inline on the transformer entry in tsconfig.json, where it overrides the file; the other sections are compiled into include/flamework/config.json for the runtime packages. Any string may reference the environment as ${NAME} or ${NAME:-fallback} ($$ for a literal dollar), read from .env and .env.local next to this file with the process environment on top; a string where a boolean, number or list is expected is converted.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "$schema": {
10
+ "type": "string",
11
+ "description": "Editor support: point this at node_modules/@flamework-experimental/transformer/flamework.config.schema.json."
12
+ },
13
+ "transformer": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "description": "Options for @flamework-experimental/transformer.",
17
+ "properties": {
18
+ "plugins": {
19
+ "type": "array",
20
+ "description": "Transformer plugins to load. Each entry is a module specifier or a path relative to the package root, optionally with options passed to the plugin as `api.options`.",
21
+ "items": {
22
+ "oneOf": [
23
+ { "type": "string" },
24
+ {
25
+ "type": "object",
26
+ "additionalProperties": false,
27
+ "required": ["path"],
28
+ "properties": {
29
+ "path": { "type": "string" },
30
+ "options": { "type": "object" }
31
+ }
32
+ }
33
+ ]
34
+ }
35
+ },
36
+ "noSemanticDiagnostics": {
37
+ "type": "boolean",
38
+ "description": "Skips TypeScript's semantic diagnostics. Faster, but type errors no longer stop the build and diagnostic spans may be wrong.",
39
+ "default": false
40
+ },
41
+ "salt": {
42
+ "type": "string",
43
+ "description": "Salt for generated hashes. Defaults to a random 64-byte salt stored in flamework.build."
44
+ },
45
+ "hashPrefix": {
46
+ "type": "string",
47
+ "description": "Prefix for generated ids. Defaults to the package name; set a short one in a game to keep ids compact and distinct from any package's."
48
+ },
49
+ "obfuscation": {
50
+ "type": "boolean",
51
+ "description": "Obfuscates identifiers: randomises remote names, shuffles metadata and shortens ids. Game projects only.",
52
+ "default": false
53
+ },
54
+ "idGenerationMode": {
55
+ "type": "string",
56
+ "enum": ["full", "short", "tiny", "obfuscated"],
57
+ "description": "How identifiers are generated. Only shorten in a game; a published package must stay on \"full\" so its ids do not collide with its consumers'.",
58
+ "default": "full"
59
+ },
60
+ "optimizations": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "description": "Experimental output optimisations.",
64
+ "properties": {
65
+ "guardGenerationDedupLimit": {
66
+ "type": "integer",
67
+ "minimum": 1,
68
+ "description": "Object and union types that occur at least this many times inside one generated guard are emitted once as a local and referenced."
69
+ }
70
+ }
71
+ }
72
+ }
73
+ },
74
+ "core": {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "description": "Options for @flamework-experimental/core.",
78
+ "properties": {
79
+ "profiling": {
80
+ "type": "boolean",
81
+ "description": "Wraps every lifecycle event in debug.profilebegin so providers show up in the MicroProfiler. Defaults to true in Studio and false elsewhere; createLifecyclePlugin({ profiling }) overrides it per module."
82
+ }
83
+ }
84
+ },
85
+ "networking": {
86
+ "type": "object",
87
+ "additionalProperties": false,
88
+ "description": "Options for @flamework-experimental/networking.",
89
+ "properties": {
90
+ "serialization": {
91
+ "type": "boolean",
92
+ "description": "Serialises every event and function payload into a buffer, with encode and decode code generated from the event's parameter types at each createServer/createClient call site. Values that cannot live in a buffer (Instances, unknown) travel alongside it.",
93
+ "default": false
94
+ }
95
+ }
96
+ },
97
+ "components": {
98
+ "type": "object",
99
+ "additionalProperties": false,
100
+ "description": "Options for @flamework-experimental/components.",
101
+ "properties": {
102
+ "warningTimeout": {
103
+ "type": "number",
104
+ "minimum": 0,
105
+ "description": "Seconds before a component that never qualifies produces a warning; 0 disables it. Components that set their own warningTimeout keep it.",
106
+ "default": 5
107
+ },
108
+ "attributeWarningTimeout": {
109
+ "type": "number",
110
+ "minimum": 0,
111
+ "description": "Seconds before an instance-valued attribute that has not streamed in produces a warning; 0 disables it. Defaults to warningTimeout.",
112
+ "default": 5
113
+ },
114
+ "streamingMode": {
115
+ "type": "string",
116
+ "enum": ["Disabled", "Watching", "Contextual"],
117
+ "description": "Default ComponentStreamingMode for components that do not set one.",
118
+ "default": "Contextual"
119
+ }
120
+ }
121
+ },
122
+ "scopes": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "description": "Build scopes: which scoped modules, registrations, providers and components are active in this build. Usually driven by the environment, as \"active\": \"${FLAMEWORK_SCOPES:-}\".",
126
+ "properties": {
127
+ "active": {
128
+ "type": "array",
129
+ "items": { "type": "string" },
130
+ "description": "The active scopes. A string from the environment is split on commas; \"*\" activates every scope and an empty list activates none.",
131
+ "default": []
132
+ }
133
+ }
134
+ },
135
+ "testing": {
136
+ "type": "object",
137
+ "additionalProperties": false,
138
+ "description": "Options for @flamework-experimental/testing. Tests are on when the \"testing\" scope is active (scopes.active, usually FLAMEWORK_SCOPES in .env), so a release build carries none; \"activeIn\" renames that scope and \"enabled\" overrides it.",
139
+ "properties": {
140
+ "enabled": {
141
+ "type": "boolean",
142
+ "description": "Whether the plugin attaches the host at all: Workspace.FlameworkTests (a BindableFunction) and Workspace.FlameworkTestsServer (a RemoteFunction). Unset, it follows activeIn and inactiveIn, so this is an override for either direction."
143
+ },
144
+ "activeIn": {
145
+ "type": "array",
146
+ "items": { "type": "string" },
147
+ "description": "Scopes under which tests are on: the host attaches when at least one is active, the way activeIn works everywhere else (an empty list is no constraint). A string from the environment is split on commas.",
148
+ "default": ["testing"]
149
+ },
150
+ "inactiveIn": {
151
+ "type": "array",
152
+ "items": { "type": "string" },
153
+ "description": "Scopes under which tests stay off, whatever else is active. A string from the environment is split on commas.",
154
+ "default": []
155
+ },
156
+ "autoRun": {
157
+ "type": "boolean",
158
+ "description": "Runs every test right after the module ignites, printing the results. Otherwise tests only run when the bindable or remote is invoked.",
159
+ "default": false
160
+ },
161
+ "timeout": {
162
+ "type": "number",
163
+ "minimum": 0,
164
+ "description": "Seconds a single test may take before it is cancelled and counted as failed.",
165
+ "default": 30
166
+ },
167
+ "entry": {
168
+ "type": "string",
169
+ "description": "Cloud runs only. The source path of a ModuleScript exporting `ignite()`, for example \"src/server/main\": an Open Cloud Luau execution task runs none of the place's Scripts, so the runner requires this module and ignites the game itself before invoking the bindable. Studio runs need none, the place runs itself. Compiled into the artifact as a tree path."
170
+ }
171
+ }
172
+ },
173
+ "cloud": {
174
+ "type": "object",
175
+ "additionalProperties": false,
176
+ "description": "Where the flamework-test CLI (@flamework-experimental/testing) publishes the build and runs its tests: a testing place, never the original. Read by that CLI only; never compiled into the place. Keep the key in the environment: \"apiKey\": \"${ROBLOX_API_KEY:-}\".",
177
+ "properties": {
178
+ "testingUniverseId": {
179
+ "type": "string",
180
+ "description": "The testing experience's universe id, from the Creator Dashboard URL (game.GameId in Studio)."
181
+ },
182
+ "testingPlaceId": {
183
+ "type": "string",
184
+ "description": "The place to publish to, run tests in, and open in Studio. Never the original place."
185
+ },
186
+ "apiKey": {
187
+ "type": "string",
188
+ "description": "An Open Cloud API key with universe-places:write and universe.place.luau-execution-session:read and :write for the testing experience. Reference the environment, \"${ROBLOX_API_KEY:-}\", so the key is never in the file."
189
+ },
190
+ "originalPlace": {
191
+ "type": "string",
192
+ "description": "A copy of the original place (File > Save to File in Studio), relative to this file. When set, the CLI lays the Rojo build over a copy of it before publishing, following the project file, so the tests see assets that exist only in the original. Needs lune."
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }