solid-tag-runtime 0.0.11 → 0.0.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.
@@ -0,0 +1,112 @@
1
+ # HTML runtime and ownership
2
+
3
+ `solid-tag-runtime/html` adapts the core module graph to browser DOM declarations. The core runtime itself does not scan or own DOM.
4
+
5
+ ## Create a controller
6
+
7
+ ```ts
8
+ import { createHTMLRuntime } from "solid-tag-runtime/html";
9
+
10
+ const html = createHTMLRuntime(runtime, {
11
+ scope: "main",
12
+ root: document,
13
+ acceptUnscoped: false,
14
+ });
15
+ ```
16
+
17
+ ## Register existing declarations
18
+
19
+ ```ts
20
+ await html.register();
21
+ ```
22
+
23
+ ## Observe later declarations
24
+
25
+ ```ts
26
+ await html.observe({ registerExisting: false });
27
+
28
+ // after external DOM mutations
29
+ await html.flush();
30
+ ```
31
+
32
+ ## Script declarations
33
+
34
+ ```html
35
+ <script
36
+ type="solid-jsx"
37
+ data-solid-runtime="main"
38
+ module="/ui/Button.jsx"
39
+ >
40
+ export function Button(props) {
41
+ return <button>{props.children}</button>;
42
+ }
43
+ </script>
44
+ ```
45
+
46
+ Supported source types include `solid-jsx`, `solid-js`, and `solid-module` (plus `text/...` aliases).
47
+
48
+ ## `src` vs `module`
49
+
50
+ ```html
51
+ <script
52
+ type="solid-jsx"
53
+ src="./source/Button.jsx"
54
+ module="/ui/Button.jsx"
55
+ ></script>
56
+ ```
57
+
58
+ - `src` = where source is loaded from
59
+ - `module` = identity in the runtime graph
60
+
61
+ ## Ownership
62
+
63
+ A physical runtime script element has at most one HTML controller owner.
64
+
65
+ ```ts
66
+ await html.registerElement(script);
67
+ await html.append(script);
68
+ await html.addModule({ id: "/dynamic.js", source, format: "js" });
69
+
70
+ html.owns(script);
71
+ html.getModuleId(script);
72
+ html.getElement("/dynamic.js");
73
+ ```
74
+
75
+ Ownership is claimed before asynchronous source loading or DOM insertion, preventing observer/manual-registration races.
76
+
77
+ ## Update and remove owned declarations
78
+
79
+ ```ts
80
+ script.textContent = updatedSource;
81
+ await html.updateElement(script);
82
+
83
+ await html.removeElement(script);
84
+ ```
85
+
86
+ Ordinary DOM removal does not implicitly delete a runtime module. The explicit controller APIs keep DOM ownership and runtime graph lifecycle synchronized.
87
+
88
+ ## Multiple runtimes
89
+
90
+ ```ts
91
+ const main = createHTMLRuntime(mainRuntime, {
92
+ scope: "main",
93
+ acceptUnscoped: false,
94
+ });
95
+
96
+ const preview = createHTMLRuntime(previewRuntime, {
97
+ scope: "preview",
98
+ acceptUnscoped: false,
99
+ });
100
+ ```
101
+
102
+ `data-solid-runtime` is declarative routing metadata. In-memory ownership is authoritative.
103
+
104
+ ## Root lifecycle
105
+
106
+ ```ts
107
+ await html.setRoot(nextRoot);
108
+ await html.moveTo(nextRoot);
109
+ html.setAppendTarget(document.head);
110
+ ```
111
+
112
+ `root` controls discovery/observation; `appendTarget` controls where explicit additions are inserted. Reparenting the exact same root node does not require `setRoot()`.
@@ -0,0 +1,77 @@
1
+ # Lifecycle events
2
+
3
+ Lifecycle subscriptions are observational. They cannot cancel compilation, change resolution, modify source, or stop rendering.
4
+
5
+ ## Core runtime
6
+
7
+ Catch all events:
8
+
9
+ ```ts
10
+ const leave = runtime.subscribe(event => {
11
+ console.log(event.type, event);
12
+ });
13
+ ```
14
+
15
+ One event type:
16
+
17
+ ```ts
18
+ const leaveErrors = runtime.subscribe("module-error", event => {
19
+ console.error(event.phase, event.error);
20
+ });
21
+ ```
22
+
23
+ Several event types:
24
+
25
+ ```ts
26
+ const leaveEvaluation = runtime.subscribe(
27
+ ["module-evaluating", "module-evaluated"],
28
+ event => console.log(event.type, event.id),
29
+ );
30
+ ```
31
+
32
+ Each call returns its own disposer.
33
+
34
+ ### Core event groups
35
+
36
+ Definition/lifecycle:
37
+
38
+ - `module-defined`
39
+ - `module-updated`
40
+ - `modules-defined`
41
+ - `module-invalidated`
42
+ - `module-removed`
43
+ - `runtime-cleared`
44
+ - `runtime-disposed`
45
+
46
+ Resolution/link/evaluation:
47
+
48
+ - `module-resolving`
49
+ - `module-resolved`
50
+ - `module-linking`
51
+ - `module-linked`
52
+ - `module-compiled`
53
+ - `module-evaluating`
54
+ - `module-evaluated`
55
+ - `module-error`
56
+
57
+ Compile-cache events:
58
+
59
+ - `compile-cache-hit`
60
+ - `compile-cache-miss`
61
+ - `compile-cache-write`
62
+ - `compile-cache-refresh`
63
+ - `compile-cache-bypass`
64
+ - `compile-cache-error`
65
+ - `compile-cache-evict`
66
+
67
+ ## HTML runtime
68
+
69
+ ```ts
70
+ html.subscribe("element-registered", event => {
71
+ console.log(event.moduleId);
72
+ });
73
+ ```
74
+
75
+ HTML events cover ownership, observation, roots, entry execution, render mounting/disposal, warnings, and errors.
76
+
77
+ Listener exceptions are isolated from runtime/HTML operations and are reported to the console rather than aborting the underlying action.
@@ -0,0 +1,93 @@
1
+ # Runtime modules and resolution
2
+
3
+ The primary abstraction in `solid-tag-runtime` is a module. Components are ordinary module exports.
4
+
5
+ ## Source modules
6
+
7
+ ```ts
8
+ runtime.define("/math.js", `export const answer = 42;`, {
9
+ format: "js",
10
+ });
11
+ ```
12
+
13
+ JSX is the default format:
14
+
15
+ ```ts
16
+ runtime.define("/Greeting.jsx", `
17
+ export default function Greeting() {
18
+ return <p>Hello</p>;
19
+ }
20
+ `);
21
+ ```
22
+
23
+ ## Host modules
24
+
25
+ Expose existing JavaScript values by reference:
26
+
27
+ ```ts
28
+ runtime.defineModule("@app/state", {
29
+ count,
30
+ setCount,
31
+ });
32
+ ```
33
+
34
+ Dynamic modules import those references normally:
35
+
36
+ ```tsx
37
+ import { count, setCount } from "@app/state";
38
+ ```
39
+
40
+ Host values are not serialized.
41
+
42
+ ## URL modules
43
+
44
+ ```ts
45
+ runtime.defineUrl(
46
+ "some-library",
47
+ "https://example.test/library.js",
48
+ );
49
+ ```
50
+
51
+ ## Resolution
52
+
53
+ Resolution is runtime-local. The default rules are:
54
+
55
+ 1. custom `resolve()` callback
56
+ 2. exact registered ID
57
+ 3. absolute URL
58
+ 4. absolute virtual path
59
+ 5. relative virtual path
60
+ 6. unresolved bare native import when `allowNativeImports:true`
61
+ 7. otherwise `ModuleResolutionError`
62
+
63
+ Virtual paths do not silently become network requests. Missing `/ui/Button.jsx` or `./Button.jsx` is a runtime-resolution error.
64
+
65
+ ```ts
66
+ runtime.resolve("./Button.jsx", "/ui/App.jsx");
67
+ // /ui/Button.jsx
68
+ ```
69
+
70
+ ## Batch definition
71
+
72
+ ```ts
73
+ runtime.defineMany([
74
+ { id: "/dep.js", source: "export const value = 41;", format: "js" },
75
+ { id: "/main.js", source: 'import { value } from "./dep.js"; export const answer = value + 1;', format: "js" },
76
+ ]);
77
+ ```
78
+
79
+ The complete batch is installed before buffered lifecycle events are published.
80
+
81
+ ## Updates and removal
82
+
83
+ ```ts
84
+ runtime.update("/Button.jsx", newSource);
85
+ runtime.remove("/Button.jsx");
86
+ runtime.clear();
87
+ ```
88
+
89
+ Updates/removals invalidate linked/evaluated dependents. Compiler artifacts follow the separate cache rules documented in [Persistent compile cache](./compile-cache.md).
90
+
91
+ ## Current cycle limitation
92
+
93
+ Circular graphs between runtime-defined source modules are rejected. The current native-module URL backend requires final dependency URLs before an importing URL can be created.
@@ -0,0 +1,65 @@
1
+ # Declarative rendering
2
+
3
+ A runtime script can define a module and mount one component instance.
4
+
5
+ ## Render into a selector
6
+
7
+ ```html
8
+ <div id="app"></div>
9
+
10
+ <script type="solid-jsx" module="/App.jsx" render="#app">
11
+ export default function App() {
12
+ return <h1>Hello</h1>;
13
+ }
14
+ </script>
15
+ ```
16
+
17
+ Without `component`, rendering selects `module.default`.
18
+
19
+ ## Named export
20
+
21
+ ```html
22
+ <script
23
+ type="solid-jsx"
24
+ module="/widgets.jsx"
25
+ render="#app"
26
+ component="Counter"
27
+ >
28
+ export function Counter() {
29
+ return <button>Counter</button>;
30
+ }
31
+ </script>
32
+ ```
33
+
34
+ ## In-place rendering
35
+
36
+ Bare `render` means mount at the exact declaration position:
37
+
38
+ ```html
39
+ <p>Before</p>
40
+
41
+ <script type="solid-jsx" module="/Message.jsx" render>
42
+ export default function Message() {
43
+ return <strong>Hello</strong>;
44
+ }
45
+ </script>
46
+
47
+ <p>After</p>
48
+ ```
49
+
50
+ The adapter replaces the declaration with an owned marker range. No wrapper is introduced.
51
+
52
+ ## Registration ordering
53
+
54
+ All matching declarations in a discovered batch are defined before any `entry` or `render` declaration executes. An importer may therefore appear before its dependency in document order.
55
+
56
+ ## `entry` vs `render`
57
+
58
+ - `entry` = evaluate a module for side effects
59
+ - `render` = evaluate a module because a component export must mount
60
+
61
+ Combining `entry` and `render` on one declaration is rejected.
62
+
63
+ ## Runtime scope diagnostics
64
+
65
+ A scoped render declaration is immediate work. If `data-solid-runtime="main"` cannot be handled by any registered controller covering that DOM root, the HTML adapter emits `html-warning` with code `unresolved-runtime-scope` and logs one warning.
@@ -0,0 +1,111 @@
1
+ # `<solid-render>`
2
+
3
+ `<solid-render>` references an already-defined runtime module and mounts a component instance into its own light DOM.
4
+
5
+ ```html
6
+ <script type="solid-jsx" module="/Counter.jsx">
7
+ export default function Counter() {
8
+ return <button>Counter</button>;
9
+ }
10
+ </script>
11
+
12
+ <solid-render module="/Counter.jsx"></solid-render>
13
+ ```
14
+
15
+ ## Important HTML syntax rule
16
+
17
+ **Always use an explicit closing tag in HTML.**
18
+
19
+ Correct:
20
+
21
+ ```html
22
+ <solid-render module="/Counter.jsx"></solid-render>
23
+ ```
24
+
25
+ Do not write:
26
+
27
+ ```html
28
+ <solid-render module="/Counter.jsx" />
29
+ ```
30
+
31
+ Custom elements are not HTML void elements. The HTML parser ignores the XML-style self-closing slash, so following siblings may become children of `<solid-render>`. Because initial child content is captured as `props.children`, this can make later page content appear to disappear.
32
+
33
+ ## Named component
34
+
35
+ ```html
36
+ <solid-render
37
+ module="/widgets.jsx"
38
+ component="Counter"
39
+ ></solid-render>
40
+ ```
41
+
42
+ ## Runtime selection
43
+
44
+ ```html
45
+ <solid-render
46
+ data-solid-runtime="main"
47
+ module="/Counter.jsx"
48
+ ></solid-render>
49
+ ```
50
+
51
+ The selected controller must match scope rules and contain the element within its configured root.
52
+
53
+ ## Declarative props
54
+
55
+ ```html
56
+ <solid-render
57
+ module="/UserCard.jsx"
58
+ prop:name="Alice"
59
+ prop:user-id="42"
60
+ prop:compact
61
+ ></solid-render>
62
+ ```
63
+
64
+ Rules:
65
+
66
+ - `prop:user-id` becomes `userId`
67
+ - a present empty prop becomes `true`
68
+ - other attribute values remain strings
69
+ - renderer configuration (`module`, `component`, `data-solid-runtime`) is not forwarded
70
+ - `prop:module` is a normal component prop and does not collide with renderer `module`
71
+
72
+ ## Programmatic props
73
+
74
+ ```ts
75
+ const element = document.querySelector("solid-render");
76
+
77
+ element.props = {
78
+ user,
79
+ onSave,
80
+ service,
81
+ };
82
+ ```
83
+
84
+ Programmatic values may contain arbitrary JavaScript references and override declarative `prop:*` values.
85
+
86
+ ## Reactive updates
87
+
88
+ Changing `prop:*` or `.props` updates the existing component instance without remounting.
89
+
90
+ Changing `module`, `component`, or `data-solid-runtime` changes render identity and therefore disposes/remounts.
91
+
92
+ ## Children
93
+
94
+ Initial child DOM becomes `props.children`:
95
+
96
+ ```html
97
+ <solid-render module="/Card.jsx">
98
+ <p>Hello from HTML.</p>
99
+ </solid-render>
100
+ ```
101
+
102
+ Initial children are captured once. Named slots and dynamic child recapture are not part of the current API.
103
+
104
+ ## Multiple instances
105
+
106
+ ```html
107
+ <solid-render module="/Counter.jsx"></solid-render>
108
+ <solid-render module="/Counter.jsx"></solid-render>
109
+ ```
110
+
111
+ The evaluated module namespace is shared, while each element owns an independent Solid component/root lifecycle.
@@ -0,0 +1,41 @@
1
+ import { createRuntime } from "solid-tag-runtime";
2
+ import * as Solid from "solid-js";
3
+ import * as SolidWeb from "@solidjs/web";
4
+ import html from "@solidjs/html";
5
+
6
+ const runtime = createRuntime({
7
+ modules: {
8
+ "solid-js": Solid,
9
+ "@solidjs/web": SolidWeb,
10
+ "@solidjs/html": { default: html },
11
+ },
12
+ });
13
+
14
+ runtime.define(
15
+ "/Button.jsx",
16
+ `
17
+ export function Button(props) {
18
+ return <button onClick={props.onClick}>{props.children}</button>;
19
+ }
20
+ `,
21
+ );
22
+
23
+ runtime.define(
24
+ "/Counter.jsx",
25
+ `
26
+ import { createSignal } from "solid-js";
27
+ import { Button } from "./Button.jsx";
28
+
29
+ export function Counter() {
30
+ const [count, setCount] = createSignal(0);
31
+ return (
32
+ <Button onClick={() => setCount(value => value + 1)}>
33
+ Count: {count()}
34
+ </Button>
35
+ );
36
+ }
37
+ `,
38
+ );
39
+
40
+ const { Counter } = await runtime.import("/Counter.jsx");
41
+ console.log(Counter);
@@ -0,0 +1,35 @@
1
+ import {
2
+ createRuntime,
3
+ createIndexedDBCompileCache,
4
+ } from "solid-tag-runtime";
5
+
6
+ const store = createIndexedDBCompileCache({
7
+ database: "my-app-runtime",
8
+ });
9
+
10
+ function createAppRuntime() {
11
+ return createRuntime({
12
+ compileCache: {
13
+ store,
14
+ namespace: "main",
15
+ version: "1",
16
+ maxEntries: 500,
17
+ maxBytes: 50 * 1024 * 1024,
18
+ },
19
+ });
20
+ }
21
+
22
+ // First runtime: compile miss + persistent write.
23
+ const first = createAppRuntime();
24
+ first.define("/config.js", `export const value = 42;`, { format: "js" });
25
+ await first.import("/config.js");
26
+ console.log("first", first.getModuleInfo("/config.js")?.compileCache);
27
+ first.dispose();
28
+
29
+ // New runtime, same source and cache namespace/version: compile hit.
30
+ // Linking, module URL creation, and native evaluation are still fresh.
31
+ const second = createAppRuntime();
32
+ second.define("/config.js", `export const value = 42;`, { format: "js" });
33
+ await second.import("/config.js");
34
+ console.log("second", second.getModuleInfo("/config.js")?.compileCache);
35
+ second.dispose();