solid-tag-runtime 0.0.7 → 0.0.9

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/html.d.ts CHANGED
@@ -1,17 +1,31 @@
1
1
  import { SolidTagRuntimeError } from "./index.js";
2
2
  import type { ModuleFormat, ModuleNamespaceLike, SolidTagRuntime } from "./index.js";
3
3
 
4
- export interface HTMLModuleScriptElement {
4
+ export interface HTMLAttributeElementLike {
5
5
  textContent?: string | null;
6
6
  baseURI?: string;
7
7
  ownerDocument?: HTMLDocumentLike | null;
8
- parentNode?: { removeChild?(element: any): unknown } | null;
8
+ parentNode?: {
9
+ removeChild?(element: any): unknown;
10
+ insertBefore?(element: any, reference: any): unknown;
11
+ } | null;
9
12
  remove?(): void;
13
+ replaceWith?(...nodes: any[]): void;
10
14
  getAttribute(name: string): string | null;
11
15
  hasAttribute?(name: string): boolean;
12
16
  setAttribute?(name: string, value: string): void;
13
17
  }
14
18
 
19
+ export interface HTMLModuleScriptElement extends HTMLAttributeElementLike {}
20
+
21
+ export interface SolidRenderElement extends HTMLAttributeElementLike, HTMLAppendTarget {
22
+ props: Record<string, unknown>;
23
+ childNodes?: ArrayLike<any> | Iterable<any>;
24
+ attributes?: ArrayLike<{ name: string; value: string }> | Iterable<{ name: string; value: string }>;
25
+ replaceChildren?(...nodes: any[]): void;
26
+ dispatchEvent?(event: unknown): boolean;
27
+ }
28
+
15
29
  export interface HTMLAppendTarget {
16
30
  append?(...nodes: any[]): void;
17
31
  appendChild?(element: any): unknown;
@@ -21,6 +35,8 @@ export interface HTMLDocumentLike extends HTMLModuleRoot, HTMLAppendTarget {
21
35
  body?: HTMLAppendTarget;
22
36
  documentElement?: HTMLAppendTarget;
23
37
  createElement?(tagName: string): any;
38
+ createComment?(data: string): any;
39
+ createDocumentFragment?(): any;
24
40
  }
25
41
 
26
42
  export interface HTMLModuleRoot {
@@ -28,7 +44,9 @@ export interface HTMLModuleRoot {
28
44
  ownerDocument?: HTMLDocumentLike | null;
29
45
  body?: HTMLAppendTarget;
30
46
  documentElement?: HTMLAppendTarget;
31
- querySelectorAll(selector: string): Iterable<HTMLModuleScriptElement> | ArrayLike<HTMLModuleScriptElement>;
47
+ querySelectorAll(selector: string): Iterable<any> | ArrayLike<any>;
48
+ querySelector?(selector: string): any;
49
+ contains?(node: any): boolean;
32
50
  }
33
51
 
34
52
  export interface HTMLFetchResponse {
@@ -44,8 +62,9 @@ export interface HTMLMutationObserverLike {
44
62
  observe(
45
63
  target: unknown,
46
64
  options: {
47
- childList: boolean;
48
- subtree: boolean;
65
+ childList?: boolean;
66
+ subtree?: boolean;
67
+ attributes?: boolean;
49
68
  },
50
69
  ): void;
51
70
  disconnect(): void;
@@ -53,12 +72,44 @@ export interface HTMLMutationObserverLike {
53
72
 
54
73
  export interface HTMLMutationObserverConstructor {
55
74
  new (
56
- callback: (...args: unknown[]) => void,
75
+ callback: (...args: any[]) => void,
57
76
  ): HTMLMutationObserverLike;
58
77
  }
59
78
 
79
+ export interface HTMLMountRecord {
80
+ kind?: "container" | "range" | string;
81
+ target?: unknown;
82
+ updateProps?(props: Record<string, unknown>): void;
83
+ dispose?(): void | Promise<void>;
84
+ }
85
+
86
+ export interface HTMLRenderAdapter {
87
+ mountContainer(options: {
88
+ runtime: SolidTagRuntime;
89
+ target: any;
90
+ Component: Function;
91
+ props: Record<string, unknown>;
92
+ element?: HTMLAttributeElementLike | SolidRenderElement;
93
+ moduleId?: string;
94
+ }): HTMLMountRecord | Promise<HTMLMountRecord>;
95
+
96
+ mountRange(options: {
97
+ runtime: SolidTagRuntime;
98
+ parent: any;
99
+ before: any;
100
+ startMarker: any;
101
+ endMarker: any;
102
+ Component: Function;
103
+ props: Record<string, unknown>;
104
+ element?: HTMLModuleScriptElement;
105
+ moduleId?: string;
106
+ }): HTMLMountRecord | Promise<HTMLMountRecord>;
107
+ }
108
+
60
109
  export interface DefineScriptOptions {
61
110
  root?: HTMLModuleRoot;
111
+ /** Optional selector-resolution root for declarative render="...". */
112
+ renderRoot?: HTMLModuleRoot;
62
113
  baseUrl?: string;
63
114
  format?: ModuleFormat | "javascript";
64
115
  fetch?: HTMLFetch;
@@ -72,15 +123,28 @@ export interface HTMLModuleDefinition {
72
123
  id: string;
73
124
  format: ModuleFormat;
74
125
  entry: boolean;
126
+ /** undefined = no render, true = in-place, string = selector target. */
127
+ render?: true | string;
128
+ /** Named component export. Missing means default export. */
129
+ component?: string;
75
130
  sourceUrl?: string;
76
131
  inline: boolean;
77
132
  element: HTMLModuleScriptElement;
78
133
  }
79
134
 
135
+ export interface HTMLRenderedModule {
136
+ id: string;
137
+ namespace: ModuleNamespaceLike;
138
+ component: string;
139
+ mode: "selector" | "in-place";
140
+ target?: unknown;
141
+ element: HTMLModuleScriptElement;
142
+ }
143
+
80
144
  export interface RemoveHTMLElementOptions {
81
145
  /** Remove the runtime module as well as releasing HTML ownership. Default: true. */
82
146
  removeModule?: boolean;
83
- /** Remove the script element from the DOM. Default: true. */
147
+ /** Remove the script declaration/range from the DOM. Default: true. */
84
148
  removeFromDOM?: boolean;
85
149
  /** Invalidate runtime dependents when removing the module. Default: true. */
86
150
  invalidateDependents?: boolean;
@@ -96,6 +160,8 @@ export interface RemoveHTMLElementResult {
96
160
  export interface RegisterHTMLOptions extends DefineScriptOptions {
97
161
  selector?: string;
98
162
  executeEntries?: boolean;
163
+ /** Execute declarative render actions. Default: true. */
164
+ executeRenders?: boolean;
99
165
  }
100
166
 
101
167
  export interface RegisterHTMLResult {
@@ -105,8 +171,57 @@ export interface RegisterHTMLResult {
105
171
  id: string;
106
172
  namespace: ModuleNamespaceLike;
107
173
  }>;
174
+ renders: string[];
175
+ rendered: HTMLRenderedModule[];
108
176
  }
109
177
 
178
+ export type HTMLRegistrationOrigin =
179
+ | "initial-scan"
180
+ | "observer"
181
+ | "observer-initial"
182
+ | "observer-root-change"
183
+ | "root-change-scan"
184
+ | "define-element"
185
+ | "register-element"
186
+ | "append"
187
+ | "add-module"
188
+ | "update-element"
189
+ | "remove-element"
190
+ | "solid-render"
191
+ | string;
192
+
193
+ export type HTMLRenderSource = "script-render" | "solid-render";
194
+ export type HTMLRenderMode = "selector" | "in-place" | "container";
195
+
196
+ export type HTMLRuntimeEvent =
197
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-discovered"; element: HTMLModuleScriptElement; moduleId?: string; origin: HTMLRegistrationOrigin; accepted: boolean }
198
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-claimed"; element: HTMLModuleScriptElement; moduleId: string; format: ModuleFormat; entry: boolean; render?: true | string; component?: string; sourceUrl?: string; origin: HTMLRegistrationOrigin }
199
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-loading"; element: HTMLModuleScriptElement; moduleId: string; sourceUrl: string; origin: HTMLRegistrationOrigin }
200
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-loaded"; element: HTMLModuleScriptElement; moduleId: string; sourceUrl: string; origin: HTMLRegistrationOrigin; bytes: number; durationMs: number }
201
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-registered"; element: HTMLModuleScriptElement; moduleId: string; definition: HTMLModuleDefinition; origin: HTMLRegistrationOrigin }
202
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-updating"; element: HTMLModuleScriptElement; moduleId: string; origin: HTMLRegistrationOrigin }
203
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-updated"; element: HTMLModuleScriptElement; moduleId: string; definition: HTMLModuleDefinition; origin: HTMLRegistrationOrigin }
204
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-removing"; element: HTMLModuleScriptElement; moduleId: string; origin: HTMLRegistrationOrigin; removeModule: boolean; removeFromDOM: boolean }
205
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-released"; element: HTMLModuleScriptElement; moduleId: string; origin: HTMLRegistrationOrigin }
206
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "element-removed"; element: HTMLModuleScriptElement; moduleId: string; origin: HTMLRegistrationOrigin; moduleRemoved: boolean; elementRemoved: boolean }
207
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "observer-connected"; root: HTMLModuleRoot; subtree: boolean; registerExisting: boolean; reason: string }
208
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "observer-disconnected"; root?: HTMLModuleRoot; reason: string }
209
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "observer-batch"; root: HTMLModuleRoot; origin: HTMLRegistrationOrigin; discovered: number; matched: number; claimed: number; ignored: number; modules: string[] }
210
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "root-changing"; previousRoot?: HTMLModuleRoot; root: HTMLModuleRoot; connected: boolean; registerExisting: boolean }
211
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "root-changed"; previousRoot?: HTMLModuleRoot; root: HTMLModuleRoot; connected: boolean; registerExisting: boolean }
212
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "append-target-changed"; previousTarget?: HTMLAppendTarget; target: HTMLAppendTarget }
213
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "entry-executing"; element: HTMLModuleScriptElement; moduleId: string; origin: HTMLRegistrationOrigin }
214
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "entry-executed"; element: HTMLModuleScriptElement; moduleId: string; namespace: ModuleNamespaceLike; origin: HTMLRegistrationOrigin }
215
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "render-mounting"; element: HTMLModuleScriptElement | SolidRenderElement; moduleId?: string; component: string; mode: HTMLRenderMode; origin: HTMLRegistrationOrigin; source: HTMLRenderSource }
216
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "render-mounted"; element: HTMLModuleScriptElement | SolidRenderElement; moduleId?: string; component: string; mode: HTMLRenderMode; target?: unknown; origin: HTMLRegistrationOrigin; source: HTMLRenderSource }
217
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "render-disposing"; element: HTMLModuleScriptElement | SolidRenderElement; moduleId?: string; component: string; mode: HTMLRenderMode; reason: string; origin: HTMLRegistrationOrigin; source: HTMLRenderSource }
218
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "render-disposed"; element: HTMLModuleScriptElement | SolidRenderElement; moduleId?: string; component: string; mode: HTMLRenderMode; reason: string; origin: HTMLRegistrationOrigin; source: HTMLRenderSource }
219
+ | { htmlRuntimeId: string; scope?: string; timestamp: number; type: "html-error"; operation: "discover" | "claim" | "fetch" | "register" | "update" | "remove" | "entry" | "render" | "solid-render" | "root-change" | "observer" | string; error: unknown; element?: HTMLModuleScriptElement | SolidRenderElement; moduleId?: string; origin?: HTMLRegistrationOrigin };
220
+
221
+ export type HTMLRuntimeEventType = HTMLRuntimeEvent["type"];
222
+ export type HTMLRuntimeEventOfType<T extends HTMLRuntimeEventType> =
223
+ Extract<HTMLRuntimeEvent, { type: T }>;
224
+
110
225
  export interface ObserveHTMLOptions extends RegisterHTMLOptions {
111
226
  /** Register scripts already present when observation starts. Default: true. */
112
227
  registerExisting?: boolean;
@@ -124,9 +239,12 @@ export interface AddHTMLModuleOptions extends DefineScriptOptions {
124
239
  source?: string;
125
240
  src?: string;
126
241
  entry?: boolean;
242
+ render?: true | string;
243
+ component?: string;
127
244
  type?: string;
128
245
  language?: string;
129
246
  executeEntries?: boolean;
247
+ executeRenders?: boolean;
130
248
  appendTo?: HTMLAppendTarget;
131
249
  document?: HTMLDocumentLike;
132
250
  createElement?: (tagName: string) => HTMLModuleScriptElement;
@@ -135,6 +253,8 @@ export interface AddHTMLModuleOptions extends DefineScriptOptions {
135
253
  export interface HTMLRuntimeOptions extends ObserveHTMLOptions {
136
254
  appendTo?: HTMLAppendTarget;
137
255
  createElement?: (tagName: string) => HTMLModuleScriptElement;
256
+ /** Override Solid mounting for tests/special hosts. */
257
+ renderAdapter?: HTMLRenderAdapter;
138
258
  }
139
259
 
140
260
  export interface SetHTMLRootOptions extends RegisterHTMLOptions {
@@ -151,72 +271,36 @@ export interface HTMLRuntimeController {
151
271
  readonly runtime: SolidTagRuntime;
152
272
  readonly scope?: string;
153
273
  readonly connected: boolean;
154
- /** Current configured/effective discovery root when available. */
155
274
  readonly root?: HTMLModuleRoot;
156
- /** Current effective target used by append()/addModule() when available. */
157
275
  readonly appendTarget?: HTMLAppendTarget;
158
- /** Result of the observer's initial scan. */
159
276
  readonly initial: RegisterHTMLResult;
160
277
 
161
- /** One-shot scan of matching scripts under the configured/root override. */
162
- register(options?: RegisterHTMLOptions): Promise<RegisterHTMLResult>;
278
+ subscribe(listener: (event: HTMLRuntimeEvent) => void): () => boolean;
279
+ subscribe<T extends HTMLRuntimeEventType>(
280
+ type: T,
281
+ listener: (event: HTMLRuntimeEventOfType<T>) => void,
282
+ ): () => boolean;
283
+ subscribe<const T extends readonly HTMLRuntimeEventType[]>(
284
+ types: T,
285
+ listener: (event: HTMLRuntimeEventOfType<T[number]>) => void,
286
+ ): () => boolean;
163
287
 
164
- /** Start live addition observation. Returns this controller. */
288
+ register(options?: RegisterHTMLOptions): Promise<RegisterHTMLResult>;
165
289
  observe(options?: ObserveHTMLOptions): Promise<HTMLRuntimeController>;
166
-
167
- /** Wait for queued observer work and scan for newly discoverable scripts. */
168
290
  flush(options?: RegisterHTMLOptions): Promise<RegisterHTMLResult>;
169
291
  disconnect(): void;
292
+ /** Dispose HTML-owned mounts/registry state without disposing the core runtime. */
293
+ dispose(): Promise<void>;
170
294
 
171
- /**
172
- * Change the discovery/observation root. A connected observer is rebound to
173
- * the new node automatically.
174
- */
175
- setRoot(
176
- root: HTMLModuleRoot,
177
- options?: SetHTMLRootOptions,
178
- ): Promise<RegisterHTMLResult>;
179
-
180
- /** Change both the discovery root and append target to the selected root. */
181
- moveTo(
182
- root: HTMLModuleRoot,
183
- options?: SetHTMLRootOptions,
184
- ): Promise<RegisterHTMLResult>;
185
-
186
- /** Change only where append()/addModule() insert future elements. */
295
+ setRoot(root: HTMLModuleRoot, options?: SetHTMLRootOptions): Promise<RegisterHTMLResult>;
296
+ moveTo(root: HTMLModuleRoot, options?: SetHTMLRootOptions): Promise<RegisterHTMLResult>;
187
297
  setAppendTarget(target: HTMLAppendTarget): HTMLRuntimeController;
188
298
 
189
- /** Define one element without auto-running an entry. */
190
- defineElement(
191
- element: HTMLModuleScriptElement,
192
- options?: DefineScriptOptions,
193
- ): Promise<HTMLModuleDefinition>;
194
-
195
- /** Explicitly claim/register an existing element for this runtime. */
196
- registerElement(
197
- element: HTMLModuleScriptElement,
198
- options?: RegisterHTMLOptions,
199
- ): Promise<HTMLModuleDefinition>;
200
-
201
- /** Re-read and replace source for an element already owned by this controller. */
202
- updateElement(
203
- element: HTMLModuleScriptElement,
204
- options?: RegisterHTMLOptions,
205
- ): Promise<HTMLModuleDefinition>;
206
-
207
- /** Release an owned element and optionally remove its module and DOM node. */
208
- removeElement(
209
- element: HTMLModuleScriptElement,
210
- options?: RemoveHTMLElementOptions,
211
- ): Promise<RemoveHTMLElementResult>;
212
-
213
- /** Claim first, append a user-created element, then register it directly. */
214
- append(
215
- element: HTMLModuleScriptElement,
216
- options?: RegisterHTMLOptions & { appendTo?: HTMLAppendTarget },
217
- ): Promise<HTMLModuleDefinition>;
218
-
219
- /** Create a runtime script element and add it through the controller. */
299
+ defineElement(element: HTMLModuleScriptElement, options?: DefineScriptOptions): Promise<HTMLModuleDefinition>;
300
+ registerElement(element: HTMLModuleScriptElement, options?: RegisterHTMLOptions): Promise<HTMLModuleDefinition>;
301
+ updateElement(element: HTMLModuleScriptElement, options?: RegisterHTMLOptions): Promise<HTMLModuleDefinition>;
302
+ removeElement(element: HTMLModuleScriptElement, options?: RemoveHTMLElementOptions): Promise<RemoveHTMLElementResult>;
303
+ append(element: HTMLModuleScriptElement, options?: RegisterHTMLOptions & { appendTo?: HTMLAppendTarget }): Promise<HTMLModuleDefinition>;
220
304
  addModule(options: AddHTMLModuleOptions): Promise<HTMLModuleDefinition>;
221
305
 
222
306
  owns(element: HTMLModuleScriptElement): boolean;
@@ -224,7 +308,16 @@ export interface HTMLRuntimeController {
224
308
  getElement(id: string): HTMLModuleScriptElement | undefined;
225
309
  }
226
310
 
227
- /** Legacy observer shape is now the full HTML runtime controller. */
311
+ export interface CustomElementRegistryLike {
312
+ define(name: string, constructor: any): void;
313
+ get(name: string): any;
314
+ }
315
+
316
+ export interface RegisterSolidRenderElementOptions {
317
+ customElements?: CustomElementRegistryLike;
318
+ HTMLElement?: new (...args: any[]) => any;
319
+ }
320
+
228
321
  export type HTMLObserverController = HTMLRuntimeController;
229
322
 
230
323
  export declare class HTMLModuleError extends SolidTagRuntimeError {
@@ -238,6 +331,12 @@ export declare class HTMLModuleOwnershipError extends HTMLModuleError {
238
331
  requestedScope?: string;
239
332
  }
240
333
 
334
+ export declare class HTMLRenderError extends SolidTagRuntimeError {
335
+ element?: HTMLModuleScriptElement | SolidRenderElement;
336
+ moduleId?: string;
337
+ component?: string;
338
+ }
339
+
241
340
  export declare const htmlModuleSelector: string;
242
341
  export declare const htmlRuntimeScopeAttribute: "data-solid-runtime";
243
342
 
@@ -246,6 +345,10 @@ export declare function createHTMLRuntime(
246
345
  options?: HTMLRuntimeOptions,
247
346
  ): HTMLRuntimeController;
248
347
 
348
+ export declare function registerSolidRenderElement(
349
+ options?: RegisterSolidRenderElementOptions,
350
+ ): any | undefined;
351
+
249
352
  export declare function defineScript(
250
353
  runtime: SolidTagRuntime,
251
354
  element: HTMLModuleScriptElement,
package/index.d.ts CHANGED
@@ -91,17 +91,50 @@ export interface ClearRuntimeOptions {
91
91
  preserveHostModules?: boolean;
92
92
  }
93
93
 
94
+ export type ModuleResolutionKind =
95
+ | "custom"
96
+ | "registered"
97
+ | "url"
98
+ | "absolute"
99
+ | "relative"
100
+ | "native";
101
+
102
+ export type ModuleErrorPhase =
103
+ | "resolve"
104
+ | "analyze"
105
+ | "compile"
106
+ | "link"
107
+ | "url-create"
108
+ | "evaluate"
109
+ | "host-bridge";
110
+
111
+ export interface LinkedDependency {
112
+ specifier: string;
113
+ resolvedId: string;
114
+ }
115
+
94
116
  export type RuntimeLifecycleEvent =
95
117
  | { runtimeId: string; timestamp: number; type: "module-defined"; id: string; kind: ModuleInfo["kind"]; version: number; operation: "define" | "defineMany" | "update" | "defineModule" | "defineUrl"; replaced: boolean; module: ModuleInfo }
118
+ | { runtimeId: string; timestamp: number; type: "module-updated"; id: string; kind: ModuleInfo["kind"]; previousVersion: number; version: number; format?: ModuleFormat; module: ModuleInfo }
119
+ | { runtimeId: string; timestamp: number; type: "modules-defined"; ids: string[]; modules: ModuleInfo[] }
120
+ | { runtimeId: string; timestamp: number; type: "module-resolving"; specifier: string; importer: string | null }
121
+ | { runtimeId: string; timestamp: number; type: "module-resolved"; specifier: string; importer: string | null; resolvedId: string; resolutionKind: ModuleResolutionKind }
122
+ | { runtimeId: string; timestamp: number; type: "module-linking"; id: string; kind: ModuleInfo["kind"]; version: number }
123
+ | { runtimeId: string; timestamp: number; type: "module-linked"; id: string; kind: ModuleInfo["kind"]; version: number; dependencies: LinkedDependency[]; module: ModuleInfo }
96
124
  | { runtimeId: string; timestamp: number; type: "module-invalidated"; id: string; kind: ModuleInfo["kind"]; version: number; reason: string }
97
125
  | { runtimeId: string; timestamp: number; type: "module-compiled"; id: string; kind: ModuleInfo["kind"]; version: number; module: ModuleInfo }
98
126
  | { runtimeId: string; timestamp: number; type: "module-evaluating"; id: string; kind: ModuleInfo["kind"]; version: number }
99
127
  | { runtimeId: string; timestamp: number; type: "module-evaluated"; id: string; kind: ModuleInfo["kind"]; version: number; module: ModuleInfo }
100
128
  | { runtimeId: string; timestamp: number; type: "module-removed"; id: string; kind: ModuleInfo["kind"]; version: number; invalidateDependents: boolean }
101
- | { runtimeId: string; timestamp: number; type: "module-error"; id?: string; kind?: ModuleInfo["kind"]; version?: number; phase: string; error: unknown }
129
+ | { runtimeId: string; timestamp: number; type: "module-error"; id?: string; kind?: ModuleInfo["kind"]; version?: number; phase: ModuleErrorPhase; error: unknown }
102
130
  | { runtimeId: string; timestamp: number; type: "runtime-cleared"; ids: string[]; preserveHostModules: boolean }
103
131
  | { runtimeId: string; timestamp: number; type: "runtime-disposed" };
104
132
 
133
+ export type RuntimeLifecycleEventType = RuntimeLifecycleEvent["type"];
134
+ export type RuntimeLifecycleEventOfType<T extends RuntimeLifecycleEventType> =
135
+ Extract<RuntimeLifecycleEvent, { type: T }>;
136
+
137
+
105
138
  export interface SolidTagRuntime {
106
139
  define(id: string, source: string, options?: DefineOptions): string;
107
140
  defineMany(definitions: SourceModuleDefinition[]): string[];
@@ -117,6 +150,14 @@ export interface SolidTagRuntime {
117
150
  remove(id: string, options?: RemoveModuleOptions): boolean;
118
151
  clear(options?: ClearRuntimeOptions): string[];
119
152
  subscribe(listener: (event: RuntimeLifecycleEvent) => void): () => boolean;
153
+ subscribe<T extends RuntimeLifecycleEventType>(
154
+ type: T,
155
+ listener: (event: RuntimeLifecycleEventOfType<T>) => void,
156
+ ): () => boolean;
157
+ subscribe<const T extends readonly RuntimeLifecycleEventType[]>(
158
+ types: T,
159
+ listener: (event: RuntimeLifecycleEventOfType<T[number]>) => void,
160
+ ): () => boolean;
120
161
  modules(): ModuleInfo[];
121
162
  dependencies(id: string): string[];
122
163
  dependents(id: string): string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-tag-runtime",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
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": {
package/src/events.js ADDED
@@ -0,0 +1,63 @@
1
+ export function createEventDispatcher(options = {}) {
2
+ const subscriptions = new Set();
3
+ const onListenerError = options.onListenerError;
4
+
5
+ return {
6
+ subscribe,
7
+ emit,
8
+ clear,
9
+ get size() {
10
+ return subscriptions.size;
11
+ },
12
+ };
13
+
14
+ function subscribe(typesOrListener, maybeListener) {
15
+ let types;
16
+ let listener;
17
+
18
+ if (typeof typesOrListener === "function") {
19
+ listener = typesOrListener;
20
+ types = undefined;
21
+ } else {
22
+ listener = maybeListener;
23
+ if (typeof typesOrListener === "string") {
24
+ types = new Set([typesOrListener]);
25
+ } else if (Array.isArray(typesOrListener)) {
26
+ if (typesOrListener.length === 0 || typesOrListener.some(type => typeof type !== "string" || !type)) {
27
+ throw new TypeError("subscribe(types, listener) expects a non-empty event type or event type array.");
28
+ }
29
+ types = new Set(typesOrListener);
30
+ } else {
31
+ throw new TypeError("subscribe() expects a listener, event type + listener, or event type array + listener.");
32
+ }
33
+ }
34
+
35
+ if (typeof listener !== "function") {
36
+ throw new TypeError("subscribe() expects a listener function.");
37
+ }
38
+
39
+ const subscription = { types, listener };
40
+ subscriptions.add(subscription);
41
+
42
+ return () => subscriptions.delete(subscription);
43
+ }
44
+
45
+ function emit(event) {
46
+ for (const subscription of [...subscriptions]) {
47
+ if (subscription.types && !subscription.types.has(event.type)) continue;
48
+ try {
49
+ subscription.listener(event);
50
+ } catch (error) {
51
+ try {
52
+ onListenerError?.(error, event);
53
+ } catch {
54
+ // Listener error reporting must never break the emitter.
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ function clear() {
61
+ subscriptions.clear();
62
+ }
63
+ }