@rbxts/app-forge 0.7.2-alpha.12 β†’ 0.7.2-alpha.13

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.
package/README.md CHANGED
@@ -26,6 +26,7 @@ If you’ve ever ended up with tangled UI state, duplicated visibility logic, or
26
26
  * **px scaling** built-in via `loners-pretty-vide-utils`
27
27
  * **Vide context integration**
28
28
  * **Story / sandbox rendering**
29
+ * **Built-in debug logger & performance tracing**
29
30
  * Fully typed with **roblox-ts**
30
31
 
31
32
  ---
@@ -86,6 +87,7 @@ Apps are registered using a decorator and rendered through `AppForge`.
86
87
  * mounts and unmounts UI
87
88
  * enforces rules
88
89
  * exposes imperative helpers (`open`, `close`, `toggle`)
90
+ * owns the **debugger & logger** instance
89
91
 
90
92
  You usually create **one Forge per UI root**.
91
93
 
@@ -134,8 +136,6 @@ const forge = new CreateVideForge();
134
136
 
135
137
  ### Mounting (Game Runtime)
136
138
 
137
- AppForge is mounted once from application bootstrap code (commonly a Flamework controller).
138
-
139
139
  ```ts
140
140
  const forge = new CreateVideForge();
141
141
 
@@ -152,52 +152,6 @@ forge.mount(
152
152
  );
153
153
  ```
154
154
 
155
- Notes:
156
-
157
- * `forge` is **implicitly available** to Apps
158
- * `props` are user-defined and become `this.props` inside Apps
159
- * visibility & rules are controlled entirely by the Forge
160
-
161
- ---
162
-
163
- ### Mounting (Game Runtime)
164
-
165
- AppForge is typically mounted from a **controller** (e.g. Flamework) and targets `PlayerGui`.
166
-
167
- ```ts
168
- const forge = new CreateVideForge();
169
-
170
- forge.mount(
171
- () => (
172
- <screengui
173
- Name="App"
174
- ZIndexBehavior="Sibling"
175
- ResetOnSpawn={false}
176
- />
177
- ),
178
- props,
179
- Players.LocalPlayer.WaitForChild("PlayerGui"),
180
- );
181
- ```
182
-
183
- This:
184
-
185
- * creates a single root `ScreenGui`
186
- * mounts all rendered apps under it
187
- * keeps AppForge in control of visibility & rules
188
-
189
- ---
190
-
191
- ### Mounting
192
-
193
- ```ts
194
- forge.mount(
195
- () => <screengui ResetOnSpawn={false} />,
196
- props,
197
- playerGui,
198
- );
199
- ```
200
-
201
155
  ---
202
156
 
203
157
  ### Opening & Closing Apps
@@ -208,20 +162,11 @@ forge.close("Inventory");
208
162
  forge.toggle("Inventory");
209
163
  ```
210
164
 
211
- You can also access the reactive source directly:
212
-
213
- ```ts
214
- const visible = forge.getSource("Inventory");
215
- ```
216
-
217
165
  ---
218
166
 
219
167
  ## 🧱 Defining an App
220
168
 
221
169
  ```ts
222
- import { VideApp, VideArgs } from "@rbxts/app-forge";
223
- import Vide from "@rbxts/vide";
224
-
225
170
  @VideApp({
226
171
  name: "Inventory",
227
172
  renderGroup: "Lobby",
@@ -246,165 +191,71 @@ export class Inventory extends VideArgs {
246
191
 
247
192
  ---
248
193
 
249
- ## πŸ”— Parent / Child Apps
250
-
251
- ```ts
252
- @VideApp({
253
- name: "InventoryInfo",
254
- renderGroup: "Lobby",
255
- rules: {
256
- parent: "Inventory",
257
- },
258
- })
259
- export class InventoryInfo extends VideArgs {
260
- render() {
261
- return <frame />;
262
- }
263
- }
264
- ```
265
-
266
- Behavior:
267
-
268
- * When `Inventory` closes β†’ `InventoryInfo` closes
269
- * Child is **anchored** to parent unless `detach: true`
270
-
271
- ```ts
272
- rules: {
273
- parent: "Inventory",
274
- detach: true,
275
- }
276
- ```
277
-
278
- ---
279
-
280
- ## 🚦 Exclusive Groups
281
-
282
- ```ts
283
- @VideApp({
284
- name: "Settings",
285
- rules: {
286
- exclusiveGroup: "Menus",
287
- },
288
- })
289
- ```
194
+ ## 🐞 Debugging & Logging
290
195
 
291
- Only one app in the same `exclusiveGroup` may be open at a time.
196
+ AppForge includes a **built-in debugger** designed for Studio-only diagnostics.
292
197
 
293
- ---
198
+ ### Debug Tags
294
199
 
295
- ## 🎭 Render Control
296
-
297
- AppForge supports **multiple render selection modes**. You can render by:
298
-
299
- * a single app name
300
- * multiple app names
301
- * one or more render groups
302
- * combinations of `group + name(s)`
303
-
304
- All render options are passed via `VideRenderProps`.
305
-
306
- ---
307
-
308
- ### Render a single app
200
+ Debug output is grouped by **typed tags**:
309
201
 
310
202
  ```ts
311
- render: { name: "Inventory" }
203
+ type DebugTag =
204
+ | "render"
205
+ | "rules"
206
+ | "state"
207
+ | "px"
208
+ | "lifecycle";
312
209
  ```
313
210
 
314
- ---
315
-
316
- ### Render multiple apps
317
-
318
- ```ts
319
- render: { names: ["Inventory", "InventoryInfo"] }
320
- ```
211
+ Each subsystem logs under its respective tag.
321
212
 
322
213
  ---
323
214
 
324
- ### Render by group
215
+ ### Enabling Debug Tags
325
216
 
326
217
  ```ts
327
- render: { group: "Lobby" }
218
+ forge.debug.enable("render");
219
+ forge.debug.enable("rules");
328
220
  ```
329
221
 
330
- ---
331
-
332
- ### Render by group + name
222
+ Enable everything at once:
333
223
 
334
224
  ```ts
335
- render: {
336
- group: "Lobby",
337
- name: "Inventory",
338
- }
225
+ forge.debug.enableAll();
339
226
  ```
340
227
 
341
- Only renders `Inventory` **if** it belongs to the `Lobby` group.
342
-
343
- ---
344
-
345
- ### Render by group + names
228
+ Disable:
346
229
 
347
230
  ```ts
348
- render: {
349
- group: "Lobby",
350
- names: ["Inventory", "Settings"],
351
- }
231
+ forge.debug.disable("render");
352
232
  ```
353
233
 
354
- Only renders apps that:
355
-
356
- * are in the specified group(s)
357
- * and whose names match the provided list
234
+ Debug logging only runs in **Roblox Studio**.
358
235
 
359
236
  ---
360
237
 
361
- ## πŸ§ͺ Story / Sandbox Rendering
238
+ ### Performance Tracing
362
239
 
363
- AppForge provides `forge.story` for **isolated rendering**, commonly used with **UI Labs**.
240
+ Certain systems emit **timing logs** when enabled:
364
241
 
365
242
  ```ts
366
- const forge = new CreateVideForge();
367
-
368
- return forge.story({
369
- props,
370
- config: {
371
- px: {
372
- target: storyProps.target,
373
- },
374
- },
375
- render: { group: "Lobby" },
376
- });
243
+ forge.debug.enable("render");
377
244
  ```
378
245
 
379
- This is ideal for:
246
+ Output example:
380
247
 
381
- * component stories
382
- * previews
383
- * controlled visibility via bindings
248
+ ```
249
+ [PERF][render][Inventory] 1.243ms
250
+ ```
384
251
 
385
252
  ---
386
253
 
387
- ## 🧠 Context Access Inside Apps
254
+ ### Static Registration Logs
388
255
 
389
- App props are provided via Vide context.
256
+ App registration (decorators) run **before a Forge exists**.
390
257
 
391
- ```ts
392
- import { Provider } from "@rbxts/vide";
393
- import { VideContexts } from "@rbxts/app-forge";
394
-
395
- <Provider context={VideContexts.App} value={this.props}>
396
- {() => <Child />}
397
- </Provider>
398
- ```
399
-
400
- Or via hook:
401
-
402
- ````ts
403
- ```ts
404
- import { useVideAppContext } from "@rbxts/app-forge";
405
-
406
- const app = useVideAppContext();
407
- ````
258
+ These use an internal **static logger** and will still emit warnings and errors during Studio load (e.g. duplicate app names).
408
259
 
409
260
  ---
410
261
 
@@ -418,6 +269,7 @@ AppForge
418
269
  β”œβ”€ Rule Engine
419
270
  β”‚ β”œβ”€ Parent Rule
420
271
  β”‚ └─ Exclusive Group Rule
272
+ β”œβ”€ Debugger / Logger
421
273
  └─ Vide Mount
422
274
  ```
423
275
 
@@ -428,6 +280,7 @@ AppForge
428
280
  * Apps are **singletons per Forge**
429
281
  * Rendering twice will warn if px is re‑initialized
430
282
  * Rules are enforced **reactively**
283
+ * Debug logging is **Studio-only**
431
284
  * This package is currently **alpha** β€” APIs may change
432
285
 
433
286
  ---
@@ -443,27 +296,17 @@ AppForge
443
296
 
444
297
  ## βš›οΈ React Support (Planned)
445
298
 
446
- AppForge is designed as a **renderer-agnostic App Manager**.b
299
+ AppForge is designed as a **renderer-agnostic App Manager**.
447
300
 
448
301
  Currently:
449
302
 
450
303
  * βœ… **Vide renderer** is production-ready
451
304
  * 🚧 **React renderer** exists but is **very early / experimental**
452
305
 
453
- React support is intentionally paused while the Vide API stabilizes. The author is still learning React, and decided to refocus on Vide first. React will be revisited once the core architecture is fully locked in.
454
-
455
- Public surface (subject to change):
456
-
457
- ```ts
458
- import { ReactApp, ReactArgs, CreateReactForge } from "@rbxts/app-forge";
459
- ```
460
-
461
- **Vide is the recommended and supported path today.**
306
+ Vide is the recommended and supported path today.
462
307
 
463
308
  ---
464
309
 
465
310
  ## πŸ“œ License
466
311
 
467
312
  MIT
468
-
469
- ---
@@ -12,14 +12,16 @@ export default class Renders extends Rules {
12
12
  * Entry point for mounting renders.
13
13
  * Decides render strategy based on props.
14
14
  */
15
- protected renderMount(this: AppForge, props: Types.Props.Main): Vide.Node;
15
+ protected renderMount(this: AppForge, props: Types.Props.Main): void | Instance | Vide.InstanceAttributes<Instance> | Vide.VideAction<any> | ReadonlyMap<number, Vide.Node> | {
16
+ readonly [key: number]: Vide.Node;
17
+ } | Vide.FunctionNode;
16
18
  private renderNames;
17
19
  private collectByGroup;
18
20
  private normalizeGroups;
19
21
  protected renderApp(this: AppForge, props: Types.Props.Main): Vide.Node;
20
- protected renderApps(this: AppForge, props: Types.Props.Main): Vide.Node[];
21
- protected renderGroup(this: AppForge, props: Types.Props.Main): Vide.Node[];
22
- protected renderGroupByName(this: AppForge, props: Types.Props.Main): Vide.Node[];
23
- protected renderGroupByNames(this: AppForge, props: Types.Props.Main): Vide.Node[];
24
- protected renderAll(this: AppForge, props: Types.Props.Main): Vide.Node[];
22
+ protected renderApps(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
23
+ protected renderGroup(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
24
+ protected renderGroupByName(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
25
+ protected renderGroupByNames(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
26
+ protected renderAll(this: AppForge, props: Types.Props.Main): void | Vide.Node[];
25
27
  }
@@ -92,7 +92,7 @@ do
92
92
  end
93
93
  function Renders:renderNames(props, names, forge)
94
94
  if #names == 0 then
95
- error("No app names provided to render", 2)
95
+ return warn("No app names provided to render | Make sure you have the paths where decorators are used!")
96
96
  end
97
97
  -- β–Ό ReadonlyArray.map β–Ό
98
98
  local _newValue = table.create(#names)
@@ -265,26 +265,28 @@ do
265
265
  end
266
266
  function AppForge:story(props)
267
267
  self.debug:logTag("lifecycle", "story", "Creating story mount")
268
- local Container = create("Frame")({
268
+ local container = create("Frame")({
269
269
  Name = "Story Container",
270
270
  BackgroundTransparency = 1,
271
271
  AnchorPoint = Vector2.new(0.5, 0.5),
272
272
  Position = UDim2.fromScale(0.5, 0.5),
273
273
  Size = UDim2.fromScale(1, 1),
274
274
  })
275
- apply(Container)({
276
- [0] = self:renderMount(props),
275
+ local render = self:renderMount(props)
276
+ apply(container)({
277
+ [0] = if render then render else nil,
277
278
  })
278
- return Container
279
+ return container
279
280
  end
280
281
  function AppForge:mount(callback, props, target)
281
282
  self.debug:logTag("lifecycle", "mount", "Mounting AppForge")
282
- local Container = callback()
283
+ local container = callback()
284
+ local render = self:renderMount(props)
283
285
  self.innerMount = mount(function()
284
- apply(Container)({
285
- [0] = self:renderMount(props),
286
+ apply(container)({
287
+ [0] = if render then render else nil,
286
288
  })
287
- return Container
289
+ return container
288
290
  end, target)
289
291
  return self.innerMount
290
292
  end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/app-forge",
3
- "version": "0.7.2-alpha.12",
3
+ "version": "0.7.2-alpha.13",
4
4
  "description": "An App Manager for Vide",
5
5
  "main": "out/init.lua",
6
6
  "types": "out/index.d.ts",