@solidrt/cli 0.0.42 → 0.0.43

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/AGENTS.md CHANGED
@@ -32,10 +32,16 @@ Two reliable checks that need no GUI:
32
32
 
33
33
  1. `bunx srt bundle src/index.tsx` - exit 0 means the app compiles. Fast.
34
34
  2. `bunx srt render src/index.tsx --size 480x640 --duration 1 --fps 2` -
35
- renders offscreen via EGL/wgpu and writes `frame-NNNNNN.png`. This actually
35
+ renders offscreen via EGL and writes `frame-NNNNNN.png`. This actually
36
36
  proves the app renders. Combine with `--fps`/`--duration` (defaults
37
37
  1280x720, 60fps, 1s).
38
38
 
39
+ Also headless: the bundled flux runtime runs a plain `.js` file directly -
40
+ `node_modules/@solidrt/<platform>/flux script.js` (e.g.
41
+ `@solidrt/linux-x64-gnu`). No display, no dev server, full `flux:*` module
42
+ access. The right tool for micro-benchmarks and for probing flux module
43
+ behavior in isolation.
44
+
39
45
  `render` gotchas:
40
46
  - Frames are written to the RUNTIME's working dir (`~/.local/share/SolidRT/go/`),
41
47
  NOT the directory you ran the command from. Look there for the PNGs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/cli",
3
- "version": "0.0.42",
3
+ "version": "0.0.43",
4
4
  "license": "MIT",
5
5
  "author": "Antoine van Wel",
6
6
  "type": "module",
@@ -28,17 +28,16 @@
28
28
  "zod": "^4.4.3"
29
29
  },
30
30
  "optionalDependencies": {
31
- "@solidrt/darwin-arm64": "0.0.42",
32
- "@solidrt/linux-arm64-gnu": "0.0.42",
33
- "@solidrt/linux-x64-gnu": "0.0.42",
34
- "@solidrt/win32-x64-msvc": "0.0.42"
31
+ "@solidrt/darwin-arm64": "0.0.43",
32
+ "@solidrt/linux-arm64-gnu": "0.0.43",
33
+ "@solidrt/linux-x64-gnu": "0.0.43",
34
+ "@solidrt/win32-x64-msvc": "0.0.43"
35
35
  },
36
36
  "peerDependencies": {
37
- "@solidrt/core": "0.0.42",
38
37
  "typescript": "^7"
39
38
  },
40
39
  "devDependencies": {
41
- "@solidrt/flux-types": "0.0.42",
40
+ "@solidrt/flux-types": "0.0.43",
42
41
  "@types/babel__core": "^7.20.5",
43
42
  "@types/bun": "latest"
44
43
  }
@@ -54,9 +54,12 @@ Authoritative references ship inside the installed packages - read them:
54
54
  top-level props, not inside `layout`/`style`.
55
55
  3. `render(() => <App/>)` once, top level. The root MUST be a `<Window>`
56
56
  (from @solidrt/components) or the core `<window>` - it throws otherwise.
57
- 4. `Window`/`View` do not paint on their own; they only paint when you set
58
- `style.backgroundColor`/`borderColor` etc - there is no separate
59
- background element to place by hand.
57
+ 4. Components' `Window`/`View` do not paint on their own; they only paint
58
+ when you set `style.backgroundColor`/`borderColor` etc - there is no
59
+ separate background element to place by hand. That is the components level
60
+ only: the core `<view>`/`<window>` have no background prop at all - in a
61
+ core-only app the background is a draw-primitive child
62
+ (`<d-rect color={...} />`) behind the content.
60
63
  5. There is no onClick/onPress on host elements. Use `Pressable`/`Button`
61
64
  from components (`onPress`), or `onPointerDown` on a `View` for anything
62
65
  custom.
@@ -125,7 +128,15 @@ Authoritative references ship inside the installed packages - read them:
125
128
  effect's apply phase, or `onSettled`; opt in narrowly with
126
129
  `createSignal(v, { ownedWrite: true })` for a signal that genuinely is
127
130
  internal state.
128
- 19. Cover/contain images: give `Image` a `fit` prop ("fill" | "cover" |
131
+ 19. Transform origin on a `d-view`: unset `originX`/`originY` pivots
132
+ scale/rotate at the view's local (0,0), the point its children's
133
+ coordinates are drawn against (a laid-out view pivots at its own box
134
+ center; a d-view has no box). To pivot a detached group around its
135
+ content's center, set the origin explicitly in pixels
136
+ (`originX={100} originY={50}` for content drawn in a 200x100 local
137
+ space). Avoid pct()/keyword origins on a d-view - they resolve against
138
+ the box inherited from the nearest laid-out ancestor.
139
+ 20. Cover/contain images: give `Image` a `fit` prop ("fill" | "cover" |
129
140
  "contain" | "none" | "scale-down", CSS object-fit semantics, centered)
130
141
  plus a box via `layout` in any form - numbers, pct(), flex. Without
131
142
  `fit`, only NUMERIC layout sizes reach the image; `width: pct(100)`
@@ -153,7 +164,7 @@ work stops being free" below is where it does not. Rules, in order of leverage:
153
164
  to compileShader/linkProgram. Params drive any uniform type: a number
154
165
  fills a `float`/`int` scalar, a flat number array fills `vec2`/`vec3`/
155
166
  `vec4` (2/3/4 numbers) or `mat4` (16, column-major), dispatched by the
156
- shader's own declaration - a ported shader's `vec2 uCenter` or Shadertoy's
167
+ shader's own declaration - a ported shader's `vec2 uCenter` or
157
168
  `vec3 iResolution` needs no splitting into scalars. To combine several
158
169
  GPU passes, stack `<texture>` elements and set `blendMode` (e.g. a base
159
170
  pass plus an additive `blendMode="plus"` pass) rather than writing a
@@ -171,7 +182,10 @@ work stops being free" below is where it does not. Rules, in order of leverage:
171
182
  on screen and to shaders sampling the texture.
172
183
  2. Reduce setProperty calls wherever possible: one path string rebuilt per
173
184
  frame beats N elements with N animated positions; a shader beats the path
174
- string. get_stats' setPropsPerFrame is the counter to watch.
185
+ string. get_stats' setPropsPerFrame is the counter to watch. Compiled JSX
186
+ attribute expressions diff before writing, so a per-frame expression that
187
+ returns an unchanged value costs no property write - setPropsPerFrame
188
+ counts values that actually changed, not expressions re-run.
175
189
  3. Never leave onFrame registered while nothing animates: a pending onFrame
176
190
  is a standing frame request, so the runtime renders and presents every
177
191
  vsync even when the callback body does nothing - an invisible 60fps GPU
@@ -187,7 +201,11 @@ work stops being free" below is where it does not. Rules, in order of leverage:
187
201
  system classifies these as Transform and keeps the node's own cache).
188
202
  What DOES invalidate the cache is any paint or content change inside the
189
203
  subtree - colors, path data, text, a Show toggling - so drive animation
190
- with transforms and keep the cached content itself static.
204
+ with transforms and keep the cached content itself static. Off a boundary,
205
+ `opacity` on a view is NOT cheap: it wraps the subtree in a compositing
206
+ layer (save_layer) for as long as it is below 1. To fade a single
207
+ primitive, put the alpha in its `color` (`rgba(...)`) - paint alpha is
208
+ free; reserve view `opacity` for fading a genuine group as a whole.
191
209
  5. "snapshot" boundaries pay first-frame texture allocation + raster:
192
210
  creating many at once (dealing a board of 64 sprites) is a visible
193
211
  one-frame hiccup - pool or pre-warm if that moment matters.
@@ -308,6 +326,9 @@ its tools over guessing at runtime state:
308
326
  - get_buffer: a vertex-buffer range decoded to numbers (f32/u16/u8, 64 KiB
309
327
  per call) - verify geometry after a writeBuffer instead of inferring it
310
328
  from pixels
329
+ - list_debug / call_debug: the app's own debug commands (registered with
330
+ `registerDebug` from `srt:dev`) - list them, then invoke by name with a
331
+ JSON argument. Per client, like get_snapshot
311
332
  - reload: rebuild from source and push to every client - THE dev loop is
312
333
  edit -> reload -> get_logs -> get_snapshot. reload surfaces build errors
313
334
  but not type errors; run `bunx srt check` for those.
@@ -350,6 +371,13 @@ flag: `"args": [..., "mcp", "--port", "N"]`.
350
371
  - console.log + get_logs is your primary probe into runtime state. For state
351
372
  you will want repeatedly (a pose, a mode, a counter), bind a debug key that
352
373
  logs it and read it back via get_logs.
374
+ - Better than debug keys when driving the app over MCP: register debug
375
+ COMMANDS - `registerDebug(name, fn)` from `srt:dev`, invoked via the
376
+ list_debug/call_debug tools. `seek`/`pause`/`play` commands turn verifying
377
+ an animation into "jump to t, snapshot, look"; a `zoom` command that
378
+ shrinks a viewBox to a region gives magnified captures without touching
379
+ source. Registrations reset on hot reload, so register at module init;
380
+ sync return values only.
353
381
  - Key events start at the focused node and bubble to the window root; with
354
382
  nothing focused they go to the window root alone. So a debug key bound via
355
383
  `<window onKeyDown>` always fires (unless a focused component consumes the
@@ -367,6 +395,13 @@ flag: `"args": [..., "mcp", "--port", "N"]`.
367
395
  - When a human reports a visual bug: capture a snapshot and SAY WHAT YOU SEE
368
396
  in it before investigating, so you agree on the symptom. If you cannot see
369
397
  the problem in the capture, say that instead of guessing.
398
+ - Snapshots are downscaled by the time you see them, so a full-window capture
399
+ cannot show you a defect a few pixels across. Whenever you hand-author
400
+ geometry - a `d-path` from raw path math, a `radius` where two shapes meet,
401
+ a stroke join - inspect it MAGNIFIED once, when you write it: a throwaway
402
+ entry file drawing the construction at 4-8x (pushed with `load`), or a
403
+ `zoom` debug command on the real app. Verifying that a shape is in the
404
+ right place is not the same check as verifying it is drawn right.
370
405
  - GPU/geometry bugs: inspect the actual GPU data FIRST - get_gpu_resources
371
406
  for draw counts/uniforms/sizes, get_texture for atlas or data-texture
372
407
  contents ("is this tile blank?" is a ten-second question), get_buffer for
@@ -9,12 +9,12 @@
9
9
  "android": "srt client --android"
10
10
  },
11
11
  "dependencies": {
12
- "@solidrt/core": "0.0.42",
13
- "@solidrt/components": "0.0.42"
12
+ "@solidrt/core": "0.0.43",
13
+ "@solidrt/components": "0.0.43"
14
14
  },
15
15
  "devDependencies": {
16
- "@solidrt/cli": "0.0.42",
17
- "@solidrt/flux-types": "0.0.42",
16
+ "@solidrt/cli": "0.0.43",
17
+ "@solidrt/flux-types": "0.0.43",
18
18
  "typescript": "^7"
19
19
  }
20
20
  }
package/src/bundler.ts CHANGED
@@ -72,7 +72,11 @@ async function codeFromOutputs(outputs: BuildArtifact[]): Promise<string> {
72
72
  }
73
73
 
74
74
  // Bun build plugin that runs JSX/TSX through babel-preset-solid (universal
75
- // generate, targeting @solidrt/core) plus the TS preset. Plain .js/.ts app
75
+ // generate, targeting @solidrt/core) plus the TS preset. `moduleName` only ends
76
+ // up as an import specifier in the emitted code, resolved from the app's tree at
77
+ // bundle time; the CLI itself never loads core, so core is deliberately neither
78
+ // a dependency nor a peer of this package (a second copy under the CLI could be
79
+ // hoisted over the app's and bundle two runtime instances). Plain .js/.ts app
76
80
  // modules take the same path (solid is a no-op without JSX) so inlineImport
77
81
  // can rewrite their `with { type: "binary" }` imports too; dependency code
78
82
  // (node_modules) skips the babel detour and keeps Bun's native loaders.