solid-tag-runtime 0.0.13 → 0.0.15

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,181 @@
1
+ # Solid runtime setup and provider resolution
2
+
3
+ `solid-tag-runtime/solid` is an **optional additive integration layer**. The core `createRuntime()` API remains synchronous and provider-agnostic.
4
+
5
+ ## Standard Solid family
6
+
7
+ The helper treats these packages as one coordinated runtime family:
8
+
9
+ ```text
10
+ solid-js
11
+ @solidjs/web
12
+ @solidjs/html
13
+ @solidjs/signals
14
+ ```
15
+
16
+ The family is resolved coherently rather than as four unrelated imports.
17
+
18
+ ## High-level setup
19
+
20
+ ```ts
21
+ import { createSolidRuntime } from "solid-tag-runtime/solid";
22
+
23
+ const runtime = await createSolidRuntime({
24
+ modules: {
25
+ "@app/state": state,
26
+ },
27
+ });
28
+ ```
29
+
30
+ `createSolidRuntime()`:
31
+
32
+ 1. resolves/imports the standard Solid family;
33
+ 2. merges those namespaces with `modules`;
34
+ 3. gives caller-supplied modules precedence;
35
+ 4. calls the normal runtime engine;
36
+ 5. installs a lazy Solid integration capability used by wrapperless DOM rendering.
37
+
38
+ The returned value is the normal `SolidTagRuntime` API.
39
+
40
+ ## Low-level setup
41
+
42
+ Nothing changes for applications that already own their exact Solid namespaces:
43
+
44
+ ```ts
45
+ import * as Solid from "solid-js";
46
+ import * as SolidWeb from "@solidjs/web";
47
+ import html from "@solidjs/html";
48
+ import { createRuntime } from "solid-tag-runtime";
49
+
50
+ const runtime = createRuntime({
51
+ modules: {
52
+ "solid-js": Solid,
53
+ "@solidjs/web": SolidWeb,
54
+ "@solidjs/html": { default: html },
55
+ },
56
+ });
57
+ ```
58
+
59
+ This path performs no provider detection and installs no implicit DOM delegation behavior.
60
+
61
+ ## Composable loader
62
+
63
+ ```ts
64
+ import { loadSolidModules } from "solid-tag-runtime/solid";
65
+
66
+ const solidModules = await loadSolidModules();
67
+
68
+ const runtime = createRuntime({
69
+ modules: {
70
+ ...solidModules,
71
+ "@app/state": state,
72
+ },
73
+ });
74
+ ```
75
+
76
+ The returned object is directly compatible with the existing `modules` option.
77
+
78
+ ## Resolution precedence
79
+
80
+ For the standard family the loader uses this precedence:
81
+
82
+ ```text
83
+ 1. already supplied namespace
84
+ 2. explicit specifier override
85
+ 3. existing browser import-map/effective host resolution
86
+ 4. provider inferred from an existing Solid-family mapping
87
+ 5. provider inferred weakly from other page mappings
88
+ 6. configured fallback provider
89
+ 7. actionable failure
90
+ ```
91
+
92
+ Existing mappings are authoritative. The helper never silently replaces them.
93
+
94
+ ## Source modes
95
+
96
+ ```ts
97
+ await loadSolidModules({ source: "auto" });
98
+ await loadSolidModules({ source: "host" });
99
+ await loadSolidModules({ source: "esm.sh" });
100
+ await loadSolidModules({ source: "jsdelivr" });
101
+ ```
102
+
103
+ ### `auto`
104
+
105
+ Use host/browser resolution first. Fill missing packages only when a coherent provider path can be determined.
106
+
107
+ If only part of the Solid family resolves from an opaque host/bundler identity and the loader cannot identify the provider/version behind that runtime, `auto` fails instead of filling the rest from a CDN. This prevents a hidden second Solid runtime. Supply the missing namespaces explicitly or provide a coherent mapping/provider configuration.
108
+
109
+ ### `host`
110
+
111
+ Use only already-resolvable host/bundler/browser modules. No CDN fallback is allowed.
112
+
113
+ ### `esm.sh`
114
+
115
+ Use explicit/existing mappings where present and generate missing package URLs through the esm.sh adapter.
116
+
117
+ ### `jsdelivr`
118
+
119
+ Use explicit/existing mappings where present and generate missing package URLs through the jsDelivr adapter. Cases that cannot safely preserve a pre-existing Solid identity fail rather than mixing providers silently.
120
+
121
+ ## Tested fallback version
122
+
123
+ When provider fallback is needed and there is no versioned Solid anchor, this release uses a documented tested family version rather than CDN `latest`:
124
+
125
+ ```ts
126
+ import { TESTED_SOLID_VERSION } from "solid-tag-runtime/solid";
127
+ ```
128
+
129
+ For `0.0.14` and `0.0.15`, the tested fallback line is Solid `2.0.0-rc.13`.
130
+
131
+ If an existing Solid mapping is explicitly versioned, that version becomes the family anchor for generated siblings. An explicitly unversioned existing mapping remains unversioned; the loader does not pretend it is pinned.
132
+
133
+ ## esm.sh identity handling
134
+
135
+ When an authoritative page mapping exists, generated esm.sh siblings externalize that dependency so the browser resolves it through the existing mapping.
136
+
137
+ When there is no existing core anchor, generated sibling package URLs pin coordinated Solid dependencies through provider-specific `deps` parameters. Solid 2's family direction is modeled with `@solidjs/signals` as the reactive core consumed by `solid-js`, then `@solidjs/web`, then `@solidjs/html`; the generated URLs pin/externalize that family closure rather than treating `@solidjs/signals` as depending back on `solid-js`.
138
+
139
+ Provider query details remain isolated in the provider adapter; the core runtime does not know they exist.
140
+
141
+ ## Import maps are read-only
142
+
143
+ The helpers may inspect import-map script contents and use the browser's effective resolver, but they never insert or rewrite import maps.
144
+
145
+ ```text
146
+ loadSolidModules()
147
+ createSolidRuntime()
148
+ ↓
149
+ read/detect only
150
+ ↓
151
+ no global import-map mutation
152
+ ```
153
+
154
+ If an application wants to install an import map, it should do so before module evaluation using application-owned tooling.
155
+
156
+ ## User overrides
157
+
158
+ Caller modules win:
159
+
160
+ ```ts
161
+ const runtime = await createSolidRuntime({
162
+ modules: {
163
+ "solid-js": CustomSolid,
164
+ "@app/state": state,
165
+ },
166
+ });
167
+ ```
168
+
169
+ This is the escape hatch for custom builds, embedded runtimes, tests, and applications that already control dependency identity.
170
+
171
+ ## Wrapperless delegation capability
172
+
173
+ `createSolidRuntime()` installs one private capability used by the HTML adapter:
174
+
175
+ ```text
176
+ ensureDelegation(document)
177
+ ```
178
+
179
+ Normal users do not call it. It is invoked lazily only when wrapperless `<script render>` mounting requires Solid's delegated-event infrastructure.
180
+
181
+ See [Wrapperless delegation](./wrapperless-delegation.md).
@@ -0,0 +1,81 @@
1
+ # Wrapperless Solid 2 event delegation
2
+
3
+ Bare declarative rendering uses marker ranges instead of a container element:
4
+
5
+ ```html
6
+ <script type="solid-jsx" render>
7
+ export default function App() {
8
+ return <button onClick={() => console.log("clicked")}>Click</button>;
9
+ }
10
+ </script>
11
+ ```
12
+
13
+ Each declaration remains an **independent Solid reactive root**.
14
+
15
+ ## Ownership model
16
+
17
+ ```text
18
+ Document
19
+ │
20
+ │ lazily, once per Document × @solidjs/web namespace:
21
+ ├── delegation host
22
+ │
23
+ ├── wrapperless declaration A
24
+ │ └── createRoot A + insert(range A)
25
+ │
26
+ └── wrapperless declaration B
27
+ └── createRoot B + insert(range B)
28
+ ```
29
+
30
+ The delegation host exists only for DOM/event infrastructure. It is not the reactive parent of the wrapperless roots.
31
+
32
+ Disposing A does not dispose B and does not tear down the document host.
33
+
34
+ ## When it is initialized
35
+
36
+ The high-level factory:
37
+
38
+ ```ts
39
+ await createSolidRuntime(...)
40
+ ```
41
+
42
+ installs the capability but performs no DOM work immediately.
43
+
44
+ The first wrapperless range mount does:
45
+
46
+ ```text
47
+ ensure document delegation host
48
+ ensure delegated event types
49
+ create independent root
50
+ insert component into marker range
51
+ ```
52
+
53
+ If the application never performs wrapperless rendering, no document delegation host is created by this feature.
54
+
55
+ ## Selector rendering is unchanged
56
+
57
+ ```html
58
+ <script type="solid-jsx" render="#app">
59
+ ```
60
+
61
+ continues to use normal Solid container rendering.
62
+
63
+ ## `<solid-render>` is unchanged
64
+
65
+ ```html
66
+ <solid-render module="/Counter.jsx"></solid-render>
67
+ ```
68
+
69
+ continues to use its own persistent light-DOM container. This feature does not change its ownership model.
70
+
71
+ ## Low-level `createRuntime()`
72
+
73
+ The core runtime deliberately does not install Solid-specific DOM behavior.
74
+
75
+ If wrapperless delegated-event setup should be automatic, use `createSolidRuntime()` from `solid-tag-runtime/solid`.
76
+
77
+ Advanced low-level users remain free to supply their own render adapter or host DOM setup.
78
+
79
+ ## Delegated events
80
+
81
+ The integration prefers the renderer's exported delegated-event set when available and otherwise uses the standard Solid/dom-expressions delegated UI event family. Registration is idempotent per renderer/document pair.
@@ -0,0 +1,24 @@
1
+ import { createSolidRuntime } from "solid-tag-runtime/solid";
2
+
3
+ const runtime = await createSolidRuntime({
4
+ solid: {
5
+ source: "auto",
6
+ // Optional when the host/import map cannot resolve the complete family:
7
+ fallbackProvider: "esm.sh",
8
+ },
9
+ modules: {
10
+ "@app/config": {
11
+ greeting: "Hello",
12
+ },
13
+ },
14
+ });
15
+
16
+ runtime.define("/Greeting.jsx", `
17
+ import { greeting } from "@app/config";
18
+
19
+ export default function Greeting() {
20
+ return <p>{greeting} from createSolidRuntime()</p>;
21
+ }
22
+ `);
23
+
24
+ export default runtime;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-tag-runtime",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "Runtime module system for JSX modules compiled with solid-tag and executed through @solidjs/html",
5
5
  "type": "module",
6
6
  "exports": {
@@ -23,6 +23,11 @@
23
23
  "types": "./html.d.ts",
24
24
  "import": "./src/html.js",
25
25
  "default": "./src/html.js"
26
+ },
27
+ "./solid": {
28
+ "types": "./solid.d.ts",
29
+ "import": "./src/solid/index.js",
30
+ "default": "./src/solid/index.js"
26
31
  }
27
32
  },
28
33
  "main": "./src/index.js",
@@ -32,6 +37,7 @@
32
37
  "src",
33
38
  "index.d.ts",
34
39
  "html.d.ts",
40
+ "solid.d.ts",
35
41
  "README.md",
36
42
  "ARCHITECTURE.md",
37
43
  "docs",
package/solid.d.ts ADDED
@@ -0,0 +1,77 @@
1
+ import type {
2
+ ModuleNamespaceLike,
3
+ RuntimeOptions,
4
+ SolidTagRuntime,
5
+ } from "./index.js";
6
+
7
+ export type SolidRuntimePackageName =
8
+ | "solid-js"
9
+ | "@solidjs/web"
10
+ | "@solidjs/html"
11
+ | "@solidjs/signals";
12
+
13
+ export type SolidModuleProviderId = "esm.sh" | "jsdelivr";
14
+ export type SolidModuleSource = "auto" | "host" | SolidModuleProviderId;
15
+
16
+ export interface SolidRuntimeModules {
17
+ "solid-js": ModuleNamespaceLike | Function;
18
+ "@solidjs/web": ModuleNamespaceLike | Function;
19
+ "@solidjs/html": ModuleNamespaceLike | Function;
20
+ "@solidjs/signals": ModuleNamespaceLike | Function;
21
+ }
22
+
23
+ export interface LoadSolidModulesOptions {
24
+ /** Resolution policy. `auto` prefers the existing host/page resolver first. */
25
+ source?: SolidModuleSource;
26
+ /** CDN used only when `auto` cannot complete the family through the host. */
27
+ fallbackProvider?: SolidModuleProviderId;
28
+ /** Version used for provider-generated URLs when no versioned Solid anchor exists. */
29
+ version?: string;
30
+ /** Already-resolved namespaces. Provided entries are never re-imported. */
31
+ modules?: Partial<SolidRuntimeModules>;
32
+ /** Explicit URL/specifier overrides. Exact values are preserved. */
33
+ specifiers?: Partial<Record<SolidRuntimePackageName, string>>;
34
+ /** Optional Document used for read-only import-map/provider inspection. */
35
+ document?: Document;
36
+ }
37
+
38
+ export interface CreateSolidRuntimeOptions extends Omit<RuntimeOptions, "modules"> {
39
+ /** Application/host modules. User entries override automatically loaded defaults. */
40
+ modules?: RuntimeOptions["modules"] & Partial<SolidRuntimeModules>;
41
+ /** Options for resolving the standard Solid package family. */
42
+ solid?: LoadSolidModulesOptions;
43
+ }
44
+
45
+ export interface SolidResolutionInspection {
46
+ pageMappings: Map<string, string>;
47
+ authoritativeMappings: Map<string, string>;
48
+ provider?: SolidModuleProviderId;
49
+ version?: string;
50
+ }
51
+
52
+ export declare class SolidModuleResolutionError extends Error {
53
+ provider?: string;
54
+ version?: string;
55
+ missing?: string[];
56
+ }
57
+
58
+ export declare const SOLID_RUNTIME_PACKAGES: readonly [
59
+ "solid-js",
60
+ "@solidjs/web",
61
+ "@solidjs/html",
62
+ "@solidjs/signals",
63
+ ];
64
+
65
+ export declare const TESTED_SOLID_VERSION: string;
66
+
67
+ export declare function loadSolidModules(
68
+ options?: LoadSolidModulesOptions,
69
+ ): Promise<SolidRuntimeModules>;
70
+
71
+ export declare function createSolidRuntime(
72
+ options?: CreateSolidRuntimeOptions,
73
+ ): Promise<SolidTagRuntime>;
74
+
75
+ export declare function inspectSolidResolution(
76
+ options?: Pick<LoadSolidModulesOptions, "specifiers" | "document">,
77
+ ): SolidResolutionInspection;
@@ -0,0 +1,69 @@
1
+ // Solid/dom-expressions' standard delegated event family. Prefer a renderer's
2
+ // exported DelegatedEvents set when present; this is the compatibility fallback.
3
+ export const DEFAULT_SOLID_DELEGATED_EVENTS = Object.freeze([
4
+ "beforeinput",
5
+ "click",
6
+ "dblclick",
7
+ "contextmenu",
8
+ "focusin",
9
+ "focusout",
10
+ "input",
11
+ "keydown",
12
+ "keyup",
13
+ "mousedown",
14
+ "mousemove",
15
+ "mouseout",
16
+ "mouseover",
17
+ "mouseup",
18
+ "pointerdown",
19
+ "pointermove",
20
+ "pointerout",
21
+ "pointerover",
22
+ "pointerup",
23
+ "touchend",
24
+ "touchmove",
25
+ "touchstart",
26
+ ]);
27
+
28
+ const delegatedByRenderer = new WeakMap();
29
+
30
+ export function ensureDelegatedEvents(web, document, events) {
31
+ if (!web || (typeof web !== "object" && typeof web !== "function")) {
32
+ throw new TypeError("Solid delegation requires an @solidjs/web namespace.");
33
+ }
34
+ if (!document) throw new TypeError("Solid delegation requires a Document.");
35
+ if (typeof web.delegateEvents !== "function") return [];
36
+
37
+ let byDocument = delegatedByRenderer.get(web);
38
+ if (!byDocument) {
39
+ byDocument = new WeakMap();
40
+ delegatedByRenderer.set(web, byDocument);
41
+ }
42
+ let delegated = byDocument.get(document);
43
+ if (!delegated) {
44
+ delegated = new Set();
45
+ byDocument.set(document, delegated);
46
+ }
47
+
48
+ const requested = normalizeEvents(events ?? web.DelegatedEvents ?? DEFAULT_SOLID_DELEGATED_EVENTS);
49
+ const fresh = requested.filter(event => !delegated.has(event));
50
+ if (!fresh.length) return [];
51
+
52
+ web.delegateEvents(fresh, document);
53
+ for (const event of fresh) delegated.add(event);
54
+ return fresh;
55
+ }
56
+
57
+ function normalizeEvents(events) {
58
+ if (!events) return [];
59
+ const values = typeof events[Symbol.iterator] === "function" ? Array.from(events) : [];
60
+ const result = [];
61
+ const seen = new Set();
62
+ for (const value of values) {
63
+ const event = String(value ?? "").trim().toLowerCase();
64
+ if (!event || seen.has(event)) continue;
65
+ seen.add(event);
66
+ result.push(event);
67
+ }
68
+ return result;
69
+ }
@@ -0,0 +1,29 @@
1
+ const hostsByDocument = new WeakMap();
2
+
3
+ export function ensureDocumentDelegationHost(web, document) {
4
+ if (!web || (typeof web !== "object" && typeof web !== "function")) {
5
+ throw new TypeError("Solid delegation requires an @solidjs/web namespace.");
6
+ }
7
+ if (!document) throw new TypeError("Solid delegation requires a Document.");
8
+ if (typeof web.render !== "function") {
9
+ throw new TypeError("@solidjs/web does not provide render() required for document delegation.");
10
+ }
11
+
12
+ let byRenderer = hostsByDocument.get(document);
13
+ if (!byRenderer) {
14
+ byRenderer = new WeakMap();
15
+ hostsByDocument.set(document, byRenderer);
16
+ }
17
+
18
+ let host = byRenderer.get(web);
19
+ if (host) return host;
20
+
21
+ const dispose = web.render(() => undefined, document);
22
+ host = {
23
+ document,
24
+ web,
25
+ dispose: typeof dispose === "function" ? dispose : undefined,
26
+ };
27
+ byRenderer.set(web, host);
28
+ return host;
29
+ }
package/src/html.js CHANGED
@@ -1219,7 +1219,8 @@ async function connectObserver(controller, root, callOptions = {}, mode = {}) {
1219
1219
  }
1220
1220
  }
1221
1221
 
1222
- const observer = new MutationObserverImpl(() => {
1222
+ const observer = new MutationObserverImpl(records => {
1223
+ if (!observerMutationsRequireScan(controller, records, callOptions)) return;
1223
1224
  void enqueueObserverScan(controller, callOptions).catch(() => {});
1224
1225
  });
1225
1226
 
@@ -1247,6 +1248,80 @@ async function connectObserver(controller, root, callOptions = {}, mode = {}) {
1247
1248
  return result;
1248
1249
  }
1249
1250
 
1251
+ function observerMutationsRequireScan(controller, records, callOptions = {}) {
1252
+ const mutations = Array.from(records ?? []);
1253
+
1254
+ // MutationObserver never invokes its callback with an empty batch, but custom
1255
+ // test/host implementations sometimes do. Preserve the historical conservative
1256
+ // behavior for those implementations instead of silently dropping discovery.
1257
+ if (mutations.length === 0) return true;
1258
+
1259
+ const selector = callOptions.selector ?? controller.selector;
1260
+
1261
+ for (const mutation of mutations) {
1262
+ if (!mutation || mutation.type !== "childList") return true;
1263
+
1264
+ const addedNodes = mutation.addedNodes;
1265
+ const removedNodes = mutation.removedNodes;
1266
+ if (addedNodes == null || removedNodes == null) return true;
1267
+
1268
+ for (const node of Array.from(addedNodes)) {
1269
+ if (nodeOrDescendantMatches(node, selector)) return true;
1270
+
1271
+ // <solid-render> is not part of the script selector, but observer batch
1272
+ // completion is also a retry boundary for newly connected render instances.
1273
+ if (nodeOrDescendantMatches(node, "solid-render")) return true;
1274
+ }
1275
+
1276
+ for (const node of Array.from(removedNodes)) {
1277
+ if (removedNodeContainsMountedDeclaration(controller, node)) return true;
1278
+ }
1279
+ }
1280
+
1281
+ return false;
1282
+ }
1283
+
1284
+ function nodeOrDescendantMatches(node, selector) {
1285
+ if (!node) return false;
1286
+
1287
+ try {
1288
+ if (typeof node.matches === "function" && node.matches(selector)) return true;
1289
+ if (typeof node.querySelector === "function" && node.querySelector(selector)) return true;
1290
+ if (typeof node.querySelectorAll === "function" && node.querySelectorAll(selector)?.length > 0) return true;
1291
+ } catch {
1292
+ // A custom selector/DOM implementation that cannot be classified safely
1293
+ // should keep the old conservative behavior rather than miss discovery.
1294
+ return true;
1295
+ }
1296
+
1297
+ // Standard DOM nodes that did not match above cannot affect discovery.
1298
+ if (typeof node.nodeType === "number") return false;
1299
+
1300
+ // Unknown host DOM objects cannot be classified safely.
1301
+ return typeof node.getAttribute === "function";
1302
+ }
1303
+
1304
+ function removedNodeContainsMountedDeclaration(controller, node) {
1305
+ if (!node) return false;
1306
+
1307
+ for (const record of controller.bindings.values()) {
1308
+ if (!record.mount) continue;
1309
+ const anchor = record.mount.mode === "in-place"
1310
+ ? record.range?.startMarker
1311
+ : record.element;
1312
+ if (!anchor) continue;
1313
+ if (node === anchor) return true;
1314
+
1315
+ try {
1316
+ if (typeof node.contains === "function" && node.contains(anchor)) return true;
1317
+ } catch {
1318
+ return true;
1319
+ }
1320
+ }
1321
+
1322
+ return false;
1323
+ }
1324
+
1250
1325
  function stopObserver(controller, options = {}) {
1251
1326
  if (!controller.connected && !controller.observer) return;
1252
1327
  const root = controller.observerRoot;
package/src/render.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { SolidTagRuntimeError } from "./errors.js";
2
+ import { getSolidRuntimeIntegration } from "./solid/integration.js";
2
3
 
3
4
  export class HTMLRenderError extends SolidTagRuntimeError {
4
5
  constructor(message, options = {}) {
@@ -68,6 +69,9 @@ export function createDefaultHTMLRenderAdapter(runtime) {
68
69
 
69
70
  async mountRange({ parent, before, startMarker, endMarker, Component, props }) {
70
71
  const { Solid, Web } = await getSolidModules();
72
+ const document = parent?.ownerDocument ?? globalThis.document;
73
+ const integration = getSolidRuntimeIntegration(runtime);
74
+ if (integration && document) integration.ensureDelegation(document);
71
75
  if (typeof Solid.createRoot !== "function") {
72
76
  throw new HTMLRenderError("solid-js does not provide createRoot().");
73
77
  }
@@ -0,0 +1,29 @@
1
+ export function readImportMapImports(document = globalThis.document) {
2
+ const imports = new Map();
3
+ if (!document || typeof document.querySelectorAll !== "function") return imports;
4
+
5
+ let scripts = [];
6
+ try {
7
+ scripts = Array.from(document.querySelectorAll('script[type="importmap"]'));
8
+ } catch {
9
+ return imports;
10
+ }
11
+
12
+ for (const script of scripts) {
13
+ const text = String(script?.textContent ?? "").trim();
14
+ if (!text) continue;
15
+ try {
16
+ const parsed = JSON.parse(text);
17
+ const values = parsed?.imports;
18
+ if (!values || typeof values !== "object") continue;
19
+ for (const [specifier, target] of Object.entries(values)) {
20
+ if (typeof target === "string" && target) imports.set(specifier, target);
21
+ }
22
+ } catch {
23
+ // Import-map parsing is advisory here. The browser remains authoritative
24
+ // for actual resolution; malformed page maps must not crash inspection.
25
+ }
26
+ }
27
+
28
+ return imports;
29
+ }
@@ -0,0 +1,67 @@
1
+ import { createRuntime as createRuntimeCore } from "../runtime.js";
2
+ import { installSolidRuntimeIntegration } from "./integration.js";
3
+ import {
4
+ SOLID_RUNTIME_PACKAGES,
5
+ TESTED_SOLID_VERSION,
6
+ pickSolidRuntimeModules,
7
+ } from "./packages.js";
8
+ import {
9
+ SolidModuleResolutionError,
10
+ createDefaultSolidEnvironment,
11
+ inspectSolidResolution,
12
+ loadSolidModulesWithEnvironment,
13
+ } from "./resolve.js";
14
+
15
+ export { SOLID_RUNTIME_PACKAGES, TESTED_SOLID_VERSION } from "./packages.js";
16
+ export { SolidModuleResolutionError, inspectSolidResolution } from "./resolve.js";
17
+
18
+ export async function loadSolidModules(options = {}) {
19
+ return loadSolidModulesWithEnvironment(options, createDefaultSolidEnvironment());
20
+ }
21
+
22
+ export async function createSolidRuntime(options = {}) {
23
+ return createSolidRuntimeWithEnvironment(options, createDefaultSolidEnvironment());
24
+ }
25
+
26
+ // Internal/testable composition point. It intentionally is not part of the
27
+ // package's documented public type surface.
28
+ export async function createSolidRuntimeWithEnvironment(options = {}, environment) {
29
+ const {
30
+ solid = {},
31
+ modules = {},
32
+ compiler: suppliedCompiler,
33
+ compilerOptions,
34
+ ...runtimeOptions
35
+ } = options;
36
+
37
+ const suppliedSolidModules = pickSolidRuntimeModules(modules);
38
+ const loadedSolidModules = await loadSolidModulesWithEnvironment({
39
+ ...solid,
40
+ modules: {
41
+ ...(solid.modules ?? {}),
42
+ ...suppliedSolidModules,
43
+ },
44
+ }, environment);
45
+
46
+ const mergedModules = {
47
+ ...loadedSolidModules,
48
+ ...modules,
49
+ };
50
+
51
+ let compiler = suppliedCompiler;
52
+ if (!compiler) {
53
+ // Keep the optional /solid layer cheap/testable when the caller already
54
+ // supplies a compiler, while preserving createRuntime()'s default behavior.
55
+ const { createSolidTagCompiler } = await import("../compiler.js");
56
+ compiler = createSolidTagCompiler(compilerOptions);
57
+ }
58
+
59
+ const runtime = createRuntimeCore({
60
+ ...runtimeOptions,
61
+ compiler,
62
+ modules: mergedModules,
63
+ });
64
+
65
+ installSolidRuntimeIntegration(runtime, pickSolidRuntimeModules(mergedModules));
66
+ return runtime;
67
+ }