@electrojs/runtime 1.0.0

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,1476 @@
1
+ import { a as createBridgeClient, i as PreloadBridgeApi, n as ElectroIpcRenderer, r as IPC_CHANNELS, t as BridgeClientConfig } from "./client-CVXQ55OB.mjs";
2
+ import * as electron from "electron";
3
+ import { BaseWindow, BaseWindowConstructorOptions, Rectangle, WebContents, WebContentsView, WebPreferences } from "electron";
4
+ import { Constructor, InjectionToken, Provider, ProviderScope } from "@electrojs/common";
5
+
6
+ //#region src/logging.d.ts
7
+ type ElectroLogLevel = "debug" | "info" | "warn" | "error";
8
+ interface ElectroLogBindings {
9
+ readonly target?: string;
10
+ }
11
+ interface ElectroLogContext {
12
+ readonly [key: string]: unknown;
13
+ }
14
+ interface ElectroLogger {
15
+ debug(message: string, context?: ElectroLogContext): void;
16
+ info(message: string, context?: ElectroLogContext): void;
17
+ warn(message: string, context?: ElectroLogContext): void;
18
+ error(message: string, context?: ElectroLogContext): void;
19
+ child(bindings: ElectroLogBindings): ElectroLogger;
20
+ }
21
+ declare function createConsoleLogger(): ElectroLogger;
22
+ //#endregion
23
+ //#region src/container/injector.d.ts
24
+ /**
25
+ * Hierarchical dependency injection container.
26
+ *
27
+ * Each module in the runtime graph owns an `Injector` instance. Injectors form a parent-child
28
+ * tree: when a token is not found locally, resolution walks up to the parent injector.
29
+ *
30
+ * Providers are registered via {@link Injector.provide} (class-based) or
31
+ * {@link Injector.provideValue} (pre-existing value). Resolution is triggered by
32
+ * {@link Injector.get} or indirectly by calling {@link inject} inside a framework-managed context.
33
+ *
34
+ * @remarks
35
+ * - Singleton providers are instantiated once per injector and cached.
36
+ * - Transient providers create a new instance on every resolution.
37
+ * - Circular dependencies are detected at resolution time and throw {@link DIError}.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * const root = new Injector();
42
+ * root.provide(MyService);
43
+ *
44
+ * const child = root.createChild();
45
+ * child.get(MyService); // resolves from root
46
+ * ```
47
+ */
48
+ declare class Injector {
49
+ private readonly parent?;
50
+ private readonly providers;
51
+ private readonly instances;
52
+ private readonly resolutionPath;
53
+ constructor(parent?: Injector | undefined);
54
+ /** Create a child injector that delegates unresolved tokens to this injector. */
55
+ createChild(): Injector;
56
+ /**
57
+ * Register a class-based provider.
58
+ *
59
+ * Accepts either a bare `@Injectable()` class or a `{ provide, useClass }` object.
60
+ *
61
+ * @throws {@link DIError} if a provider with the same token is already registered in this injector.
62
+ */
63
+ provide(provider: Provider): void;
64
+ /**
65
+ * Register a pre-existing value as a provider.
66
+ *
67
+ * Use this for configuration objects, constants, or instances created outside the DI system.
68
+ *
69
+ * @throws {@link DIError} if a provider with the same token is already registered in this injector.
70
+ */
71
+ provideValue<T>(token: InjectionToken<T>, value: T): void;
72
+ /** Check whether a provider is registered for the given token in this injector or any ancestor. */
73
+ has(token: InjectionToken): boolean;
74
+ /**
75
+ * Resolve a provider by token, instantiating it if necessary.
76
+ *
77
+ * Resolution walks up the injector hierarchy until a matching provider is found.
78
+ *
79
+ * @throws {@link DIError} if no provider is found, a circular dependency is detected,
80
+ * or the target class is not framework-managed.
81
+ */
82
+ get<T>(token: InjectionToken<T>): T;
83
+ private resolve;
84
+ private resolveRecord;
85
+ private resolveSingleton;
86
+ private instantiate;
87
+ private resolveWithPath;
88
+ }
89
+ //#endregion
90
+ //#region src/modules/scanner.d.ts
91
+ /** Discriminates the role of a provider: plain service, renderer view, or window host. */
92
+ type ProviderKind = "provider" | "view" | "window";
93
+ /** Discriminates bridge method semantics: commands mutate state, queries are read-only. */
94
+ type BridgeMethodKind = "command" | "query";
95
+ /**
96
+ * Static, serializable description of a module extracted from `@Module()` decorator metadata.
97
+ * This is the first layer of the two-layer entity model -- it captures the declaration
98
+ * without instantiating anything, making it suitable for static analysis and tooling.
99
+ */
100
+ interface ModuleDefinition {
101
+ /** Unique module identifier, derived from the class name or explicit `@Module({ id })`. */
102
+ readonly id: string;
103
+ /** The decorated module class constructor. */
104
+ readonly target: Constructor;
105
+ /** Module constructors this module imports (resolved from `@Module({ imports })`). */
106
+ readonly imports: readonly Constructor[];
107
+ /** Runtime-managed declarations declared in this module, fully scanned with capabilities. */
108
+ readonly providers: readonly ProviderDefinition[];
109
+ /** Provider constructors this module exports to importers. */
110
+ readonly exportTargets: readonly Constructor[];
111
+ }
112
+ /**
113
+ * Static description of a provider (service, view, or window) within a module.
114
+ * Aggregates all capability metadata (bridge methods, signal handlers, jobs) discovered
115
+ * from the provider's decorated methods.
116
+ */
117
+ interface ProviderDefinition {
118
+ /** Provider identifier, defaults to the class name. */
119
+ readonly id: string;
120
+ readonly target: Constructor;
121
+ /** ID of the module that owns this provider. */
122
+ readonly ownerModuleId: string;
123
+ readonly scope: ProviderScope;
124
+ readonly kind: ProviderKind;
125
+ /** Present only if the provider is decorated with `@View()`. */
126
+ readonly view?: ViewDefinition;
127
+ /** Present only if the provider is decorated with `@Window()`. */
128
+ readonly window?: WindowDefinition;
129
+ /** Bridge command/query methods exposed by this provider. */
130
+ readonly bridgeMethods: readonly BridgeMethodDefinition[];
131
+ /** Signal subscriptions declared by this provider. */
132
+ readonly signalHandlers: readonly SignalHandlerDefinition[];
133
+ /** Scheduled jobs declared by this provider. */
134
+ readonly jobs: readonly JobDefinition[];
135
+ }
136
+ /**
137
+ * Static description of a renderer view, extracted from `@View()` decorator metadata.
138
+ * Views represent web content (HTML pages or routes) rendered inside a `BrowserWindow`.
139
+ */
140
+ interface ViewDefinition {
141
+ readonly id: string;
142
+ readonly ownerModuleId: string;
143
+ /** Path or URL to the HTML/renderer entry for this view. */
144
+ readonly source: string;
145
+ /** Bridge channels this view is allowed to invoke (allowlist for access control). */
146
+ readonly access: readonly string[];
147
+ /** Signal IDs this view is allowed to receive. */
148
+ readonly signals: readonly string[];
149
+ readonly target: Constructor;
150
+ /** Optional Electron configuration from `@View({ configuration })` (webPreferences, etc). */
151
+ readonly configuration?: {
152
+ readonly webPreferences?: electron.WebPreferences;
153
+ };
154
+ }
155
+ /**
156
+ * Static description of an Electron `BrowserWindow` host, extracted from `@Window()` decorator metadata.
157
+ */
158
+ interface WindowDefinition {
159
+ readonly id: string;
160
+ readonly ownerModuleId: string;
161
+ readonly target: Constructor;
162
+ /** Optional Electron `BrowserWindow` configuration overrides. */
163
+ readonly configuration?: object;
164
+ }
165
+ /**
166
+ * Static description of a bridge method (IPC handler) exposed to the renderer process.
167
+ * Channel names are derived as `moduleId:methodId`.
168
+ */
169
+ interface BridgeMethodDefinition {
170
+ /** Fully qualified IPC channel name (`moduleId:methodId`). */
171
+ readonly channel: string;
172
+ readonly kind: BridgeMethodKind;
173
+ readonly moduleId: string;
174
+ readonly providerName: string;
175
+ /** Name of the method on the provider class that handles this channel. */
176
+ readonly methodName: string;
177
+ }
178
+ /**
179
+ * Static description of a signal handler that subscribes to an application signal.
180
+ * Signal IDs come from the `@signal()` decorator's `id` option, or default to the method name.
181
+ */
182
+ interface SignalHandlerDefinition {
183
+ /** Signal identifier this handler subscribes to (from `@signal({ id })` or method name). */
184
+ readonly signalId: string;
185
+ readonly moduleId: string;
186
+ readonly providerName: string;
187
+ /** Name of the method on the provider class that handles this signal. */
188
+ readonly methodName: string;
189
+ }
190
+ /**
191
+ * Static description of a scheduled job declared via `@Job()` decorator.
192
+ */
193
+ interface JobDefinition {
194
+ /** Fully qualified job identifier (`moduleId:methodId`). */
195
+ readonly jobId: string;
196
+ readonly moduleId: string;
197
+ readonly providerName: string;
198
+ /** Name of the method on the provider class that executes this job. */
199
+ readonly methodName: string;
200
+ /** Optional cron expression for recurring execution. */
201
+ readonly cron?: string;
202
+ }
203
+ /**
204
+ * Complete static description of an application's module graph and all capabilities.
205
+ *
206
+ * This is the top-level output of {@link scanModules} and the first layer of the
207
+ * two-layer entity model. It is fully serializable (except `target` constructor
208
+ * references) for use by CLI tooling, validation, and static analysis.
209
+ */
210
+ interface AppDefinition {
211
+ /** The root module constructor that was passed to {@link scanModules}. */
212
+ readonly rootModule: Constructor;
213
+ /** All discovered modules in traversal order (root-first). */
214
+ readonly modules: readonly ModuleDefinition[];
215
+ /** All providers across all modules. */
216
+ readonly providers: readonly ProviderDefinition[];
217
+ /** All views across all modules. */
218
+ readonly views: readonly ViewDefinition[];
219
+ /** All windows across all modules. */
220
+ readonly windows: readonly WindowDefinition[];
221
+ /** All bridge methods (commands and queries) across all providers. */
222
+ readonly bridgeMethods: readonly BridgeMethodDefinition[];
223
+ /** All signal handlers across all providers. */
224
+ readonly signalHandlers: readonly SignalHandlerDefinition[];
225
+ /** All scheduled jobs across all providers. */
226
+ readonly jobs: readonly JobDefinition[];
227
+ }
228
+ /**
229
+ * Recursively walks the module graph starting from `rootModule`, reading `@Module()`,
230
+ * `@Injectable()`, `@View()`, `@Window()`, and method decorators to produce a complete
231
+ * {@link AppDefinition}.
232
+ *
233
+ * This is a pure metadata read -- no instances are created. The resulting definition
234
+ * is passed to {@link validateAppDefinition} and then to the instance loader.
235
+ *
236
+ * @throws {BootstrapError} If a module or provider is missing required decorator metadata,
237
+ * or if an imported class is not a valid module.
238
+ */
239
+ declare function scanModules(rootModule: Constructor): AppDefinition;
240
+ //#endregion
241
+ //#region src/modules/refs.d.ts
242
+ /**
243
+ * Optional lifecycle hooks that modules and providers can implement to participate
244
+ * in the application startup/shutdown sequence.
245
+ *
246
+ * Hooks are called per-module in dependency-first topological order during startup,
247
+ * and in reverse order during shutdown. Within each module, provider hooks run
248
+ * before the module's own hook.
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * @Injectable()
253
+ * class DatabaseService implements LifecycleTarget {
254
+ * async onInit() { await this.connect(); }
255
+ * async onShutdown() { await this.disconnect(); }
256
+ * }
257
+ * ```
258
+ *
259
+ * @remarks
260
+ * All hooks may be synchronous or asynchronous. A thrown error in any startup hook
261
+ * triggers automatic rollback of already-initialized modules.
262
+ */
263
+ interface LifecycleTarget {
264
+ /** Called during initialization phase. Use for setting up connections, state, etc. */
265
+ onInit?(): void | Promise<void>;
266
+ /** Called after all modules have been initialized. Use for cross-module coordination. */
267
+ onReady?(): void | Promise<void>;
268
+ /** Called during graceful shutdown. Use for releasing resources, closing connections. */
269
+ onShutdown?(): void | Promise<void>;
270
+ /** Called after shutdown completes. Use for final cleanup (file handles, timers, etc.). */
271
+ onDispose?(): void | Promise<void>;
272
+ }
273
+ /**
274
+ * Represents the current phase of a module's lifecycle.
275
+ *
276
+ * Transitions follow a strict state machine: creating -> ready -> started -> stopping -> stopped.
277
+ * Any state can also transition to "failed".
278
+ */
279
+ type ModuleStatus = "creating" | "ready" | "started" | "stopping" | "stopped" | "failed";
280
+ /**
281
+ * Live runtime representation of a provider (service, view, or window) within a module.
282
+ *
283
+ * Wraps the instantiated provider together with its static definition and the
284
+ * module-scoped injector it was resolved from. Used internally by the framework
285
+ * to invoke bridge handlers, lifecycle hooks, and capability installations.
286
+ */
287
+ declare class ProviderRef {
288
+ /** The static definition this provider was created from. */
289
+ readonly definition: ProviderDefinition;
290
+ /** The live provider instance, potentially implementing {@link LifecycleTarget}. */
291
+ readonly instance: LifecycleTarget;
292
+ /** The module-scoped injector that resolved this provider. */
293
+ readonly injector: Injector;
294
+ constructor(/** The static definition this provider was created from. */
295
+
296
+ definition: ProviderDefinition, /** The live provider instance, potentially implementing {@link LifecycleTarget}. */
297
+
298
+ instance: LifecycleTarget, /** The module-scoped injector that resolved this provider. */
299
+
300
+ injector: Injector);
301
+ get id(): string;
302
+ get target(): Constructor;
303
+ get ownerModuleId(): string;
304
+ /**
305
+ * Resolves a method on the provider instance by name.
306
+ * Returns `undefined` if the property does not exist or is not a function.
307
+ */
308
+ getMethod(methodName: string): ((...args: unknown[]) => unknown) | undefined;
309
+ }
310
+ /**
311
+ * Live runtime representation of a loaded module.
312
+ *
313
+ * Each `ModuleRef` holds the instantiated module class, its child injector, resolved
314
+ * providers, and lifecycle status. This is the second layer of the two-layer entity
315
+ * model: `ModuleDefinition` (static, serializable) is produced by the scanner, then
316
+ * `ModuleRef` is created during bootstrap when the module is actually instantiated.
317
+ *
318
+ * @remarks
319
+ * Status transitions are validated against an internal state machine and will throw
320
+ * {@link LifecycleError} on illegal transitions.
321
+ */
322
+ declare class ModuleRef {
323
+ /** Unique module identifier, derived from the class name or `@Module({ id })`. */
324
+ readonly id: string;
325
+ /** The decorated module class constructor. */
326
+ readonly target: Constructor;
327
+ /** Module-scoped child injector containing this module's providers. */
328
+ readonly injector: Injector;
329
+ /** The live module class instance, potentially implementing {@link LifecycleTarget}. */
330
+ readonly instance: LifecycleTarget;
331
+ /** All providers declared in this module. */
332
+ readonly providers: readonly ProviderRef[];
333
+ /** Set of provider constructors that this module exports to importing modules. */
334
+ readonly exportTargets: ReadonlySet<Constructor>;
335
+ private statusInternal;
336
+ private importsInternal;
337
+ constructor(/** Unique module identifier, derived from the class name or `@Module({ id })`. */
338
+
339
+ id: string, /** The decorated module class constructor. */
340
+
341
+ target: Constructor, /** Module-scoped child injector containing this module's providers. */
342
+
343
+ injector: Injector, /** The live module class instance, potentially implementing {@link LifecycleTarget}. */
344
+
345
+ instance: LifecycleTarget, /** All providers declared in this module. */
346
+
347
+ providers: readonly ProviderRef[], /** Set of provider constructors that this module exports to importing modules. */
348
+
349
+ exportTargets: ReadonlySet<Constructor>);
350
+ get status(): ModuleStatus;
351
+ get imports(): readonly ModuleRef[];
352
+ /** Subset of {@link providers} that are listed in this module's exports. */
353
+ get exportedProviders(): readonly ProviderRef[];
354
+ /**
355
+ * @internal Sets the resolved import references after all modules are loaded.
356
+ * Called once during bootstrap by the instance loader.
357
+ */
358
+ linkImports(imports: readonly ModuleRef[]): void;
359
+ /**
360
+ * @internal Advances the module to the next lifecycle state.
361
+ * @throws {LifecycleError} If the transition is not permitted by the state machine.
362
+ */
363
+ transitionTo(next: ModuleStatus): void;
364
+ }
365
+ //#endregion
366
+ //#region src/app/kernel.d.ts
367
+ /**
368
+ * Represents the current phase of the application kernel's lifecycle.
369
+ *
370
+ * The state machine follows a linear progression:
371
+ * `idle` -> `initializing` -> `initialized` -> `starting` -> `started` -> `stopping` -> `stopped`.
372
+ * Any state except `stopped` can also transition to `failed`.
373
+ */
374
+ type KernelState = "idle" | "initializing" | "initialized" | "starting" | "started" | "stopping" | "stopped" | "failed";
375
+ interface AppKernelOptions {
376
+ readonly logger?: ElectroLogger;
377
+ }
378
+ /**
379
+ * The main entry point for an `@electrojs/runtime` application.
380
+ *
381
+ * `AppKernel` orchestrates the full application lifecycle: scanning decorator metadata,
382
+ * validating the module graph, creating the DI container, loading modules, installing
383
+ * capabilities (bridge handlers, signals, jobs, desktop providers), and running
384
+ * lifecycle hooks in the correct order.
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * const kernel = AppKernel.create(AppModule);
389
+ * await kernel.start();
390
+ *
391
+ * // ... app is running ...
392
+ *
393
+ * await kernel.shutdown();
394
+ * ```
395
+ *
396
+ * @remarks
397
+ * - Calling {@link start} when already started is a no-op.
398
+ * - If startup fails, the kernel automatically rolls back initialized modules and
399
+ * transitions to `failed`.
400
+ * - {@link shutdown} can only be called from the `started` state.
401
+ */
402
+ declare class AppKernel {
403
+ private state;
404
+ private composition?;
405
+ private services?;
406
+ private readonly rootModule;
407
+ private readonly logger;
408
+ private readonly stateListeners;
409
+ private readonly disposers;
410
+ private constructor();
411
+ /**
412
+ * Creates a new kernel instance for the given root module.
413
+ * The kernel starts in the `idle` state -- call {@link start} to bootstrap the application.
414
+ */
415
+ static create(rootModule: Constructor, options?: AppKernelOptions): AppKernel;
416
+ /**
417
+ * Bootstraps and starts the application.
418
+ *
419
+ * Performs module scanning, validation, DI container creation, module instantiation,
420
+ * capability installation, and runs `onInit` / `onReady` lifecycle hooks.
421
+ * On failure, automatically rolls back and transitions to `failed`.
422
+ *
423
+ * @remarks No-op if already started. Must be called from `idle` state.
424
+ * @throws {BootstrapError} On invalid module graph or decorator metadata.
425
+ * @throws {LifecycleError} On lifecycle hook failure.
426
+ */
427
+ start(): Promise<void>;
428
+ /**
429
+ * Gracefully shuts down the application.
430
+ *
431
+ * Runs `onShutdown` / `onDispose` lifecycle hooks in reverse module order,
432
+ * then disposes framework services (jobs, windows, views).
433
+ *
434
+ * @remarks No-op if `idle` or already `stopped`. Throws if not in `started` state.
435
+ * @throws {LifecycleError} If the kernel is not in the `started` state.
436
+ */
437
+ shutdown(): Promise<void>;
438
+ /** Returns the current kernel lifecycle state. */
439
+ getState(): KernelState;
440
+ /** Convenience check: returns `true` only when the kernel is in the `started` state. */
441
+ isStarted(): boolean;
442
+ /** Returns the scanned app definition, or `undefined` if the kernel has not been started yet. */
443
+ getDefinition(): AppDefinition | undefined;
444
+ /** Returns the live module references, or an empty array if the kernel has not been started yet. */
445
+ getModuleRefs(): readonly ModuleRef[];
446
+ /** @internal Hook for subsystems that need to react to kernel state changes. */
447
+ onStateChange(callback: (state: KernelState) => void): void;
448
+ private registerFrameworkServices;
449
+ private disposeServices;
450
+ private transitionTo;
451
+ private safeDisposeServices;
452
+ }
453
+ //#endregion
454
+ //#region src/container/inject.d.ts
455
+ /**
456
+ * Resolve a dependency from the current injection context.
457
+ *
458
+ * This is the primary way framework-managed classes obtain their dependencies.
459
+ * It reads the active {@link Injector} from `AsyncLocalStorage` and delegates to
460
+ * {@link Injector.get}.
461
+ *
462
+ * @remarks
463
+ * `inject()` is only available inside a framework-managed execution scope:
464
+ * - **Construction** -- property initializers of `@Injectable()`, `@Module()`, `@View()`, or `@Window()` classes
465
+ * - **Lifecycle hooks** -- `onInit`, `onReady`, `onShutdown`, `onDispose`
466
+ * - **Capability handlers** -- methods decorated with `@command`, `@query`, `@signal`, or `@job`
467
+ *
468
+ * Calling it anywhere else (e.g. in a `setTimeout` callback or a plain function)
469
+ * throws {@link DIError} with code `ELECTRO_DI_NO_INJECTION_CONTEXT`.
470
+ *
471
+ * @example
472
+ * ```ts
473
+ * @Injectable()
474
+ * class MyService {
475
+ * private readonly config = inject(AppConfig);
476
+ * }
477
+ * ```
478
+ *
479
+ * @throws {@link DIError} if no injection context is active or the token cannot be resolved.
480
+ */
481
+ declare function inject<T>(token: InjectionToken<T>): T;
482
+ //#endregion
483
+ //#region src/container/injection-context.d.ts
484
+ /**
485
+ * Ambient injection context backed by `AsyncLocalStorage`.
486
+ *
487
+ * The framework uses `InjectionContext` to make the current {@link Injector} available
488
+ * to {@link inject} calls without requiring explicit injector references. It is set
489
+ * automatically during provider construction, lifecycle hooks, and capability handlers.
490
+ *
491
+ * @remarks
492
+ * This is a framework-internal API. Application code should use {@link inject} instead
493
+ * of interacting with `InjectionContext` directly.
494
+ *
495
+ * @internal
496
+ */
497
+ declare const InjectionContext: {
498
+ /**
499
+ * Execute `fn` within the scope of the given injector.
500
+ * Any {@link inject} call made synchronously inside `fn` will resolve from this injector.
501
+ */
502
+ readonly run: <T>(injector: Injector, fn: () => T) => T;
503
+ /**
504
+ * Execute `fn` within the scope of the given injector, additionally tracking `owner`
505
+ * as the object currently being constructed or invoked.
506
+ */
507
+ readonly runOwned: <T>(injector: Injector, owner: object, fn: () => T) => T; /** Return the injector for the current execution context, or `undefined` if none is active. */
508
+ readonly current: () => Injector | undefined; /** Return the owner object of the current execution context, or `undefined` if not set. */
509
+ readonly currentOwner: () => object | undefined; /** Whether a framework-managed injection context is currently active. */
510
+ readonly isActive: () => boolean;
511
+ };
512
+ //#endregion
513
+ //#region src/modules/registry.d.ts
514
+ /**
515
+ * Serializable point-in-time view of a provider's registration state.
516
+ * Produced by {@link ModuleRegistry.snapshot} for runtime introspection and tooling.
517
+ */
518
+ interface ProviderSnapshot {
519
+ readonly id: string;
520
+ readonly target: string;
521
+ readonly kind: "provider" | "view" | "window";
522
+ readonly scope: string;
523
+ /** Bridge channels this provider exposes (commands and queries). */
524
+ readonly bridgeChannels: readonly string[];
525
+ /** Signal IDs this provider subscribes to. */
526
+ readonly signalIds: readonly string[];
527
+ /** Scheduled job IDs registered by this provider. */
528
+ readonly jobIds: readonly string[];
529
+ }
530
+ /**
531
+ * Serializable point-in-time view of a module's registration and lifecycle state.
532
+ * Produced by {@link ModuleRegistry.snapshot} for runtime introspection and tooling (e.g. CLI module graph).
533
+ */
534
+ interface ModuleSnapshot {
535
+ readonly id: string;
536
+ readonly target: string;
537
+ readonly status: ModuleStatus;
538
+ /** IDs of modules this module imports. */
539
+ readonly imports: readonly string[];
540
+ /** Class names of providers this module exports. */
541
+ readonly exports: readonly string[];
542
+ readonly providers: readonly ProviderSnapshot[];
543
+ }
544
+ /**
545
+ * Central registry of all loaded modules in the application.
546
+ *
547
+ * Provides lookup by class constructor or module ID, and produces serializable
548
+ * snapshots for runtime introspection (e.g. CLI `inspect` commands, debug tooling).
549
+ * Populated once during bootstrap by the capability installer.
550
+ *
551
+ * @example
552
+ * ```ts
553
+ * const registry = injector.get(ModuleRegistry);
554
+ * const snapshot = registry.snapshot(); // serializable module graph
555
+ * ```
556
+ */
557
+ declare class ModuleRegistry {
558
+ private readonly modulesByTarget;
559
+ private readonly modulesById;
560
+ /** @internal Populate the registry from bootstrap. Called once by the capability installer. */
561
+ load(moduleRefs: readonly ModuleRef[]): void;
562
+ /** Looks up a module by its decorated class constructor. */
563
+ getByTarget(target: Constructor): ModuleRef | undefined;
564
+ /** Looks up a module by its unique string identifier. */
565
+ getById(moduleId: string): ModuleRef | undefined;
566
+ /** Returns all registered modules. */
567
+ getAll(): readonly ModuleRef[];
568
+ /** Produces a serializable snapshot of the entire module graph for introspection. */
569
+ snapshot(): readonly ModuleSnapshot[];
570
+ }
571
+ //#endregion
572
+ //#region src/modules/validator.d.ts
573
+ /**
574
+ * Validates a scanned {@link AppDefinition} for structural correctness before bootstrap.
575
+ *
576
+ * Checks performed:
577
+ * - Unique module IDs
578
+ * - Exports reference declared providers
579
+ * - No cyclic module imports
580
+ * - Unique view/window IDs
581
+ * - Unique bridge channel names
582
+ * - Unique job IDs
583
+ * - Provider role exclusivity (a class cannot be both a view and a window)
584
+ * - View access references point to existing bridge channels
585
+ *
586
+ * @throws {BootstrapError} On the first validation failure encountered.
587
+ */
588
+ declare function validateAppDefinition(definition: AppDefinition): void;
589
+ //#endregion
590
+ //#region src/signals/relay.d.ts
591
+ /**
592
+ * Callback invoked by {@link PublicationRelay} whenever a signal is published.
593
+ *
594
+ * Typically used by the renderer registry to forward signals from the main process
595
+ * to renderer processes that have opted in via `@View({ signals: [...] })`.
596
+ */
597
+ type SignalPublishListener = (signalId: string, payload: unknown) => void;
598
+ //#endregion
599
+ //#region src/signals/context.d.ts
600
+ /**
601
+ * Metadata object passed to {@link ContextualSignalHandler} callbacks when a signal is published.
602
+ *
603
+ * Provides contextual information about the publication event. Handlers that need
604
+ * access to this metadata should declare two parameters (context, payload) so the
605
+ * {@link SignalBus} treats them as contextual handlers.
606
+ */
607
+ declare class SignalContext {
608
+ /** Epoch timestamp (milliseconds) captured at the moment the signal was dispatched to this handler. */
609
+ readonly timestamp: number;
610
+ }
611
+ //#endregion
612
+ //#region src/signals/bus.d.ts
613
+ /**
614
+ * A callback that receives only the signal payload.
615
+ *
616
+ * Use this form when the handler does not need access to the {@link SignalContext}.
617
+ */
618
+ type SignalListener<T = unknown> = (payload: T) => void | Promise<void>;
619
+ /**
620
+ * A callback that receives both a {@link SignalContext} and the signal payload.
621
+ *
622
+ * Use this form when the handler needs metadata about the publication (e.g. timestamp).
623
+ */
624
+ type ContextualSignalHandler<T = unknown> = (context: SignalContext, payload: T) => void | Promise<void>;
625
+ /**
626
+ * Union of the two supported handler signatures for {@link SignalBus.subscribe}.
627
+ *
628
+ * The bus distinguishes between the two forms by arity: handlers with two or more
629
+ * parameters are treated as {@link ContextualSignalHandler}, all others as {@link SignalListener}.
630
+ */
631
+ type SignalHandler<T = unknown> = SignalListener<T> | ContextualSignalHandler<T>;
632
+ /**
633
+ * Fire-and-forget publish/subscribe signal bus for decoupled inter-module communication.
634
+ *
635
+ * Handlers are dispatched asynchronously via `queueMicrotask`, so `publish()` never blocks
636
+ * the caller. Each handler runs inside the dependency-injection context that was active at
637
+ * the time `subscribe()` was called, which means `inject()` works correctly inside handlers.
638
+ *
639
+ * @example
640
+ * ```ts
641
+ * // Subscribe to a signal (returns an unsubscribe function)
642
+ * const unsub = signalBus.subscribe('user:login', (payload) => {
643
+ * console.log('User logged in:', payload.userId);
644
+ * });
645
+ *
646
+ * // Publish a signal — all handlers run asynchronously
647
+ * signalBus.publish('user:login', { userId: '42' });
648
+ *
649
+ * // Unsubscribe when no longer needed
650
+ * unsub();
651
+ * ```
652
+ *
653
+ * @example
654
+ * ```ts
655
+ * // Contextual handler with access to SignalContext
656
+ * signalBus.subscribe('data:sync', (context, payload) => {
657
+ * console.log('Signal published at:', context.timestamp);
658
+ * });
659
+ * ```
660
+ */
661
+ declare class SignalBus {
662
+ private readonly handlers;
663
+ private readonly relay;
664
+ /**
665
+ * Register a handler for the given signal.
666
+ *
667
+ * The handler is bound to the current injection context at call time, so
668
+ * `inject()` resolves correctly even though the handler runs asynchronously.
669
+ *
670
+ * @returns A dispose function that removes the subscription.
671
+ */
672
+ subscribe<T>(signalId: string, handler: SignalHandler<T>): () => void;
673
+ /**
674
+ * Publish a signal to all registered handlers.
675
+ *
676
+ * Handlers are invoked asynchronously via `queueMicrotask` and their errors are
677
+ * logged but never propagated to the publisher. The signal is also forwarded to
678
+ * any connected {@link PublicationRelay} listeners (e.g. renderer processes).
679
+ *
680
+ * @remarks Payload is optional for signals that carry no data (`SignalBus.publish<void>('app:ready')`).
681
+ */
682
+ publish<T = void>(signalId: string, payload?: T): void;
683
+ /** @internal Connect a relay listener (used by renderer registry). */
684
+ connectRelay(listener: SignalPublishListener): () => void;
685
+ }
686
+ //#endregion
687
+ //#region src/jobs/context.d.ts
688
+ /**
689
+ * Execution context passed to every job handler invocation.
690
+ *
691
+ * Provides cooperative cancellation and progress reporting. The handler should
692
+ * periodically check {@link isCanceled} and abort work when it returns `true`.
693
+ *
694
+ * @example
695
+ * ```ts
696
+ * async function cleanupHandler(ctx: JobContext) {
697
+ * const items = await fetchItems();
698
+ * for (let i = 0; i < items.length; i++) {
699
+ * if (ctx.isCanceled) return;
700
+ * await processItem(items[i]);
701
+ * ctx.setProgress((i / items.length) * 100);
702
+ * }
703
+ * }
704
+ * ```
705
+ */
706
+ declare class JobContext {
707
+ private canceledInternal;
708
+ private progressInternal;
709
+ /** Whether cancellation has been requested for this execution. */
710
+ get isCanceled(): boolean;
711
+ /** Current progress value, clamped to 0-100. */
712
+ get progress(): number;
713
+ /**
714
+ * Report execution progress.
715
+ *
716
+ * @remarks Values are clamped to the 0-100 range.
717
+ */
718
+ setProgress(value: number): void;
719
+ /** @internal */
720
+ cancel(): void;
721
+ }
722
+ //#endregion
723
+ //#region src/jobs/registry.d.ts
724
+ type Awaitable$1<T> = T | PromiseLike<T>;
725
+ /**
726
+ * Describes a job as provided during module bootstrap.
727
+ *
728
+ * @internal Consumed by {@link JobRegistry.register}; not intended for direct consumer use.
729
+ */
730
+ interface JobDefinitionRecord {
731
+ readonly jobId: string;
732
+ /** Cron expression (Croner syntax). Omit for manually-triggered-only jobs. */
733
+ readonly cron?: string;
734
+ /** The handler to execute. Receives a {@link JobContext} for cancellation/progress, plus any extra args from manual runs. */
735
+ readonly handler: (context: JobContext, ...args: unknown[]) => Awaitable$1<unknown>;
736
+ /** Injector used to restore the DI context when the handler runs. */
737
+ readonly injector: Injector;
738
+ }
739
+ /** Lifecycle state of a registered job. */
740
+ type JobStatus = "idle" | "scheduled" | "running";
741
+ /** Read-only snapshot of a job's current runtime state. */
742
+ interface JobRuntimeState {
743
+ readonly jobId: string;
744
+ readonly status: JobStatus;
745
+ /** Last reported progress value (0-100). */
746
+ readonly progress: number;
747
+ /** Epoch timestamp of the last completed execution, if any. */
748
+ readonly lastRunAt?: number;
749
+ }
750
+ /**
751
+ * Manages the lifecycle of scheduled and manually-triggered jobs.
752
+ *
753
+ * Jobs are registered during bootstrap (via `@internal` {@link register}), then consumers
754
+ * interact through `start`, `stop`, `run`, and `cancel`. Scheduled jobs use Croner for
755
+ * cron-based timing; each execution receives a fresh {@link JobContext} for progress
756
+ * reporting and cooperative cancellation.
757
+ *
758
+ * @example
759
+ * ```ts
760
+ * // Start the cron scheduler for a registered job
761
+ * jobRegistry.start('data:cleanup');
762
+ *
763
+ * // Trigger an immediate (manual) execution
764
+ * await jobRegistry.run('data:cleanup');
765
+ *
766
+ * // Cancel a running execution cooperatively
767
+ * jobRegistry.cancel('data:cleanup');
768
+ *
769
+ * // Stop the cron scheduler and wait for any running execution to finish
770
+ * await jobRegistry.stop('data:cleanup');
771
+ * ```
772
+ */
773
+ declare class JobRegistry {
774
+ private readonly jobs;
775
+ /** @internal Register a job definition during bootstrap. */
776
+ register(definition: JobDefinitionRecord): void;
777
+ /** Return a snapshot of all registered jobs and their current state. */
778
+ list(): readonly JobRuntimeState[];
779
+ /** Return the current state of a single job, or `undefined` if not registered. */
780
+ getStatus(jobId: string): JobRuntimeState | undefined;
781
+ /**
782
+ * Start the cron scheduler for a job if it is not already scheduled.
783
+ *
784
+ * Unlike {@link start}, this is idempotent and will not throw if the scheduler
785
+ * is already running.
786
+ */
787
+ ensure(jobId: string): void;
788
+ /**
789
+ * Start the cron scheduler for a job.
790
+ *
791
+ * @throws {JobError} If the job already has an active scheduler.
792
+ */
793
+ start(jobId: string): void;
794
+ /**
795
+ * Trigger an immediate (manual) execution of a job, bypassing the cron schedule.
796
+ *
797
+ * @throws {JobError} If the job is already running.
798
+ * @returns The value returned by the job handler.
799
+ */
800
+ run(jobId: string, ...args: unknown[]): Promise<unknown>;
801
+ /**
802
+ * Stop the cron scheduler and cancel any in-flight execution.
803
+ *
804
+ * Waits for the running execution (if any) to settle before returning. The job
805
+ * transitions to `"idle"` once fully stopped.
806
+ */
807
+ stop(jobId: string): Promise<void>;
808
+ /**
809
+ * Request cooperative cancellation of the currently running execution.
810
+ *
811
+ * Sets the `isCanceled` flag on the job's {@link JobContext}. The handler is
812
+ * responsible for checking this flag and aborting work accordingly.
813
+ */
814
+ cancel(jobId: string): void;
815
+ /** @internal */
816
+ dispose(): Promise<void>;
817
+ private getJobOrThrow;
818
+ private startScheduler;
819
+ private executeJob;
820
+ }
821
+ //#endregion
822
+ //#region src/desktop/renderer-session.d.ts
823
+ /**
824
+ * Tracks the capabilities of a single renderer process (identified by `webContentsId`).
825
+ *
826
+ * Each session records which bridge channels the renderer may invoke and which signals
827
+ * it is allowed to receive, as declared in the `@View()` decorator metadata. The
828
+ * {@link BridgeAccessGuard} and signal relay use this information to enforce per-view
829
+ * access control.
830
+ *
831
+ * @internal Created and managed by {@link RendererRegistry}.
832
+ */
833
+ declare class RendererSession {
834
+ /** The Electron `webContents.id` that uniquely identifies this renderer process. */
835
+ readonly rendererId: number;
836
+ /** The view ID this renderer is associated with. */
837
+ readonly viewId: string;
838
+ /** Set of bridge channel names this renderer is allowed to invoke. */
839
+ readonly access: ReadonlySet<string>;
840
+ /** Set of signal IDs this renderer is allowed to receive. */
841
+ readonly allowedSignals: ReadonlySet<string>;
842
+ constructor(/** The Electron `webContents.id` that uniquely identifies this renderer process. */
843
+
844
+ rendererId: number, viewDef: ViewDefinition);
845
+ /** Check whether this renderer has access to the given bridge channel. */
846
+ hasAccess(channel: string): boolean;
847
+ /** Check whether this renderer is allowed to receive the given signal. */
848
+ canReceiveSignal(signalId: string): boolean;
849
+ }
850
+ //#endregion
851
+ //#region src/desktop/renderer-registry.d.ts
852
+ /**
853
+ * Maps Electron `webContentsId` values to {@link RendererSession} instances.
854
+ *
855
+ * Used by the bridge layer to look up which renderer process is making an IPC request
856
+ * and determine what channels and signals it is allowed to access. View definitions are
857
+ * registered at bootstrap time; sessions are created lazily when a renderer first
858
+ * communicates.
859
+ *
860
+ * @internal
861
+ */
862
+ declare class RendererRegistry {
863
+ private readonly sessions;
864
+ private readonly viewDefinitions;
865
+ /** Store a view definition so that sessions can be created for it later. */
866
+ registerView(viewDef: ViewDefinition): void;
867
+ /**
868
+ * Return the existing session for a `webContentsId`, or create one if this is
869
+ * the first request from that renderer.
870
+ *
871
+ * @throws {BridgeError} If the `viewId` does not match any registered view definition.
872
+ */
873
+ getOrCreateSession(webContentsId: number, viewId: string): RendererSession;
874
+ /** Look up an existing session by its `webContentsId`, or `undefined` if none exists. */
875
+ getSession(webContentsId: number): RendererSession | undefined;
876
+ /** Remove a session when its renderer process is destroyed. */
877
+ removeSession(webContentsId: number): void;
878
+ /** Return all active renderer sessions. */
879
+ getAllSessions(): readonly RendererSession[];
880
+ }
881
+ //#endregion
882
+ //#region src/desktop/view-manager.d.ts
883
+ /**
884
+ * Framework-internal registry that tracks all `@View()` providers in the application.
885
+ *
886
+ * Handles registration (including injecting the source URL into the base class)
887
+ * and provides lookup by view ID. Consumers typically interact with views through
888
+ * their {@link ViewProvider} subclass rather than this manager directly.
889
+ *
890
+ * @internal
891
+ */
892
+ declare class ViewManager {
893
+ private readonly views;
894
+ /**
895
+ * Register a view provider and apply its `@View()` source URL.
896
+ *
897
+ * @remarks Silently skips providers that do not have view metadata.
898
+ */
899
+ register(providerRef: ProviderRef): void;
900
+ /** Look up a registered view provider by its view ID. */
901
+ get(viewId: string): ProviderRef | undefined;
902
+ /** Return all registered view providers. */
903
+ list(): readonly ProviderRef[];
904
+ /** Clear the registry. Does not destroy any underlying web contents. */
905
+ dispose(): Promise<void>;
906
+ }
907
+ //#endregion
908
+ //#region src/desktop/view-provider.d.ts
909
+ declare const VIEW_STATE: unique symbol;
910
+ interface ViewAuthoringSurface {
911
+ readonly contentView: WebContentsView | undefined;
912
+ readonly webContents: WebContents | undefined;
913
+ load(): Promise<void>;
914
+ setBounds(bounds: Rectangle): void;
915
+ setBackgroundColor(color: string): void;
916
+ focus(): void;
917
+ setWindowButtonVisibility(visible: boolean): void;
918
+ }
919
+ /**
920
+ * Abstract base class for view providers decorated with `@View()`.
921
+ *
922
+ * Extend this class to define a renderable view in your application. The framework
923
+ * injects the source URL from the `@View()` decorator, and your subclass gains access
924
+ * to methods for loading content, positioning, and styling.
925
+ *
926
+ * Views are created with strict security defaults: `sandbox: true`,
927
+ * `contextIsolation: true`, and `nodeIntegration: false`.
928
+ *
929
+ * @remarks The `WebContentsView` is lazily created on the first call to {@link load}.
930
+ *
931
+ * @example
932
+ * ```ts
933
+ * @View({ source: 'view:main', access: ['app:getVersion'] })
934
+ * class MainView extends ViewProvider {
935
+ * async onReady() {
936
+ * await this.load();
937
+ * this.setBounds({ x: 0, y: 0, width: 800, height: 600 });
938
+ * }
939
+ * }
940
+ * ```
941
+ */
942
+ declare abstract class ViewProvider {
943
+ private [VIEW_STATE];
944
+ /** The underlying Electron `WebContentsView`, or `undefined` if not yet created. */
945
+ get contentView(): WebContentsView | undefined;
946
+ /** The `WebContents` associated with this view, or `undefined` if not yet created. */
947
+ get webContents(): WebContents | undefined;
948
+ /**
949
+ * Create the underlying `WebContentsView` (if needed) and load the configured source URL.
950
+ *
951
+ * The view is lazily created on the first call. Subsequent calls reload the source.
952
+ * If the previous view was destroyed (e.g. parent window closed), a new one is created.
953
+ * No-ops if no source URL has been configured.
954
+ */
955
+ load(): Promise<void>;
956
+ /** Set the position and size of this view within its parent window. */
957
+ setBounds(bounds: Rectangle): void;
958
+ /** Set the background color of the view (e.g. `"#ffffff"` or `"transparent"`). */
959
+ setBackgroundColor(color: string): void;
960
+ /** Give keyboard focus to this view's web contents. */
961
+ focus(): void;
962
+ /** Show or hide the native window traffic-light buttons for this view (macOS). */
963
+ setWindowButtonVisibility(visible: boolean): void;
964
+ private createView;
965
+ private static resolveSource;
966
+ /** @internal Called by the framework to set the view source from @View metadata. */
967
+ static __setSource(instance: ViewProvider, source: string): void;
968
+ /** @internal Called by the framework to set web preferences from @View metadata. */
969
+ static __setWebPreferences(instance: ViewProvider, webPreferences: WebPreferences): void;
970
+ }
971
+ //#endregion
972
+ //#region src/desktop/window-manager.d.ts
973
+ /**
974
+ * Framework-internal registry that tracks all `@Window()` providers in the application.
975
+ *
976
+ * Handles registration (including injecting `@Window()` configuration into the base class)
977
+ * and provides lookup by window ID. Consumers typically interact with windows through
978
+ * their {@link WindowProvider} subclass rather than this manager directly.
979
+ *
980
+ * @internal
981
+ */
982
+ declare class WindowManager {
983
+ private readonly windows;
984
+ /**
985
+ * Register a window provider and apply its `@Window()` configuration.
986
+ *
987
+ * @remarks Silently skips providers that do not have window metadata.
988
+ */
989
+ register(providerRef: ProviderRef): void;
990
+ /** Look up a registered window provider by its window ID. */
991
+ get(windowId: string): ProviderRef | undefined;
992
+ /** Return all registered window providers. */
993
+ list(): readonly ProviderRef[];
994
+ /** Close all managed windows and clear the registry. */
995
+ dispose(): Promise<void>;
996
+ }
997
+ //#endregion
998
+ //#region src/desktop/window-provider.d.ts
999
+ declare const WINDOW_STATE: unique symbol;
1000
+ interface WindowAuthoringSurface {
1001
+ readonly window: BaseWindow | undefined;
1002
+ create(): void;
1003
+ mount(view: Pick<ViewProvider, "contentView">): void;
1004
+ show(): void;
1005
+ hide(): void;
1006
+ focus(): void;
1007
+ close(): void;
1008
+ getBounds(): Rectangle | undefined;
1009
+ }
1010
+ /**
1011
+ * Abstract base class for window providers decorated with `@Window()`.
1012
+ *
1013
+ * Extend this class to define a window in your application. The framework injects
1014
+ * configuration from the `@Window()` decorator metadata, and your subclass gains
1015
+ * access to lifecycle methods like {@link create}, {@link show}, {@link mount}, and {@link close}.
1016
+ *
1017
+ * @remarks The native `BaseWindow` instance is only available after calling {@link create}.
1018
+ * Calling lifecycle methods before `create()` is safe (they no-op) but the window
1019
+ * will not exist on screen.
1020
+ *
1021
+ * @example
1022
+ * ```ts
1023
+ * @Window({ width: 800, height: 600, show: false })
1024
+ * class MainWindow extends WindowProvider {
1025
+ * async onReady() {
1026
+ * this.create();
1027
+ * this.mount(this.mainView);
1028
+ * this.show();
1029
+ * }
1030
+ * }
1031
+ * ```
1032
+ */
1033
+ declare abstract class WindowProvider {
1034
+ private [WINDOW_STATE];
1035
+ /** The underlying Electron `BaseWindow` instance, or `undefined` if not yet created. */
1036
+ get window(): BaseWindow | undefined;
1037
+ /** Create the native `BaseWindow` using configuration from the `@Window()` decorator. */
1038
+ create(): void;
1039
+ /**
1040
+ * Attach a view's content to this window.
1041
+ *
1042
+ * The view's `WebContentsView` is added as a child view of the window's content area.
1043
+ * No-ops silently if the window or view has not been created yet.
1044
+ */
1045
+ mount(view: ViewProvider): void;
1046
+ /** Show the window. No-ops if the window has not been created. */
1047
+ show(): void;
1048
+ /** Hide the window without destroying it. */
1049
+ hide(): void;
1050
+ /** Bring the window to the front and give it focus. */
1051
+ focus(): void;
1052
+ /** Close and destroy the native window, releasing its resources. */
1053
+ close(): void;
1054
+ /** Return the window's current screen bounds, or `undefined` if not created. */
1055
+ getBounds(): Rectangle | undefined;
1056
+ /** @internal Called by the framework to set the window configuration from @Window metadata. */
1057
+ static __setConfiguration(instance: WindowProvider, configuration?: BaseWindowConstructorOptions): void;
1058
+ }
1059
+ //#endregion
1060
+ //#region src/bridge/access-guard.d.ts
1061
+ /**
1062
+ * Enforces access control for bridge IPC calls.
1063
+ *
1064
+ * Checks two conditions before a bridge request is allowed through:
1065
+ * 1. The application kernel must be in the `"started"` state.
1066
+ * 2. The requesting renderer's {@link RendererSession} must have the target channel
1067
+ * in its access set (as declared in `@View({ access: [...] })`).
1068
+ *
1069
+ * @internal Used by {@link BridgeDispatcher}; not intended for direct consumer use.
1070
+ */
1071
+ declare class BridgeAccessGuard {
1072
+ private kernelState;
1073
+ /** Update the tracked kernel state. Called by the kernel during lifecycle transitions. */
1074
+ setKernelState(state: KernelState): void;
1075
+ /**
1076
+ * Assert that the kernel is in the `"started"` state.
1077
+ *
1078
+ * @throws {BridgeError} If the kernel is not ready to handle requests.
1079
+ */
1080
+ assertKernelReady(): void;
1081
+ /**
1082
+ * Assert that the renderer session has access to the given bridge channel.
1083
+ *
1084
+ * @throws {BridgeError} If the view's `access` list does not include the channel.
1085
+ */
1086
+ assertAccess(session: RendererSession, channel: string): void;
1087
+ }
1088
+ //#endregion
1089
+ //#region src/bridge/handler.d.ts
1090
+ type Awaitable<T> = T | PromiseLike<T>;
1091
+ /**
1092
+ * A bound function that executes a provider method with the given arguments.
1093
+ *
1094
+ * Created during bootstrap by binding the method to its provider instance.
1095
+ */
1096
+ type BridgeInvoker = (...args: unknown[]) => Awaitable<unknown>;
1097
+ /**
1098
+ * Wraps a provider method so it can be invoked via IPC from a renderer process.
1099
+ *
1100
+ * Each handler is bound to a specific bridge channel and restores the correct
1101
+ * dependency-injection context before calling the underlying provider method,
1102
+ * ensuring that `inject()` works as expected inside bridge handlers.
1103
+ *
1104
+ * @internal Created during module bootstrap; not instantiated by consumers.
1105
+ */
1106
+ declare class BridgeHandler {
1107
+ /** The bridge channel this handler responds to (e.g. `"app:getVersion"`). */
1108
+ readonly channel: string;
1109
+ /** Whether this bridge method is a `"command"` (mutating) or `"query"` (read-only). */
1110
+ readonly kind: "command" | "query";
1111
+ /** The ID of the module that owns this handler. */
1112
+ readonly moduleId: string;
1113
+ private readonly invoker;
1114
+ private readonly injector;
1115
+ constructor(definition: BridgeMethodDefinition, invoker: BridgeInvoker, injector: Injector);
1116
+ /**
1117
+ * Execute the underlying provider method within the correct injection context.
1118
+ *
1119
+ * @returns The value returned by the provider method.
1120
+ */
1121
+ invoke(args: unknown[]): Promise<unknown>;
1122
+ }
1123
+ //#endregion
1124
+ //#region src/bridge/dispatcher.d.ts
1125
+ /** Incoming IPC request from a renderer process. */
1126
+ interface BridgeRequest {
1127
+ /** Unique identifier for correlating request/response pairs. */
1128
+ readonly callId: string;
1129
+ /** The bridge channel name to invoke (e.g. `"app:getVersion"`). */
1130
+ readonly channel: string;
1131
+ /** Arguments to pass to the bridge handler. */
1132
+ readonly args: unknown[];
1133
+ }
1134
+ /** IPC response sent back to the renderer process. */
1135
+ interface BridgeResponse {
1136
+ /** Matches the `callId` of the originating {@link BridgeRequest}. */
1137
+ readonly callId: string;
1138
+ /** The handler's return value on success. */
1139
+ readonly result?: unknown;
1140
+ /** Serialized error information on failure. */
1141
+ readonly error?: {
1142
+ message: string;
1143
+ code?: string;
1144
+ context?: Record<string, unknown>;
1145
+ };
1146
+ }
1147
+ /**
1148
+ * Routes IPC requests from renderer processes to the appropriate {@link BridgeHandler}.
1149
+ *
1150
+ * For each incoming request the dispatcher verifies that the kernel is ready,
1151
+ * that the requesting renderer has an active session, and that the session grants
1152
+ * access to the requested channel. If all checks pass the corresponding handler
1153
+ * is invoked; otherwise a serialized error is returned. Errors never propagate as
1154
+ * exceptions -- they are always returned as part of the {@link BridgeResponse}.
1155
+ *
1156
+ * @internal
1157
+ */
1158
+ declare class BridgeDispatcher {
1159
+ private readonly rendererRegistry;
1160
+ private readonly accessGuard;
1161
+ private readonly handlers;
1162
+ constructor(rendererRegistry: RendererRegistry, accessGuard: BridgeAccessGuard);
1163
+ /** Register a handler for a bridge channel. */
1164
+ registerHandler(handler: BridgeHandler): void;
1165
+ /**
1166
+ * Process an IPC request from a renderer identified by its `webContentsId`.
1167
+ *
1168
+ * Performs kernel-readiness, session-existence, and channel-access checks before
1169
+ * delegating to the registered handler. All errors are caught and returned as
1170
+ * serialized error objects in the response.
1171
+ */
1172
+ dispatch(webContentsId: number, request: BridgeRequest): Promise<BridgeResponse>;
1173
+ }
1174
+ //#endregion
1175
+ //#region src/bridge/serializer.d.ts
1176
+ /**
1177
+ * Convert an error into a plain object suitable for IPC transport.
1178
+ *
1179
+ * Extracts `message`, optional `code`, and optional `context` from `Error` instances.
1180
+ * Non-Error values are coerced to a string message.
1181
+ */
1182
+ declare function serializeBridgeError(error: unknown): {
1183
+ message: string;
1184
+ code?: string;
1185
+ context?: Record<string, unknown>;
1186
+ };
1187
+ //#endregion
1188
+ //#region src/errors/runtime.d.ts
1189
+ /**
1190
+ * Abstract base class for all framework errors in `@electrojs/runtime`.
1191
+ *
1192
+ * Every concrete error subclass (e.g. {@link BootstrapError}, {@link DIError}) extends this class
1193
+ * and exposes static factory methods that produce pre-formatted, coded error instances.
1194
+ *
1195
+ * @remarks
1196
+ * Each error carries a unique {@link RuntimeError.code | code} string (e.g. `"ELECTRO_DI_PROVIDER_NOT_FOUND"`)
1197
+ * and an optional {@link RuntimeError.context | context} bag of structured data for programmatic inspection.
1198
+ * Application code should catch specific subclasses rather than `RuntimeError` directly.
1199
+ */
1200
+ declare abstract class RuntimeError extends Error {
1201
+ /** Machine-readable error code, unique per failure scenario (e.g. `"ELECTRO_DI_CIRCULAR_DEPENDENCY"`). */
1202
+ readonly code: string;
1203
+ /** Structured context data describing the error. Keys vary by error code. */
1204
+ readonly context?: Readonly<Record<string, unknown>>;
1205
+ protected constructor(message: string, code: string, context?: Readonly<Record<string, unknown>>);
1206
+ }
1207
+ //#endregion
1208
+ //#region src/errors/bootstrap.d.ts
1209
+ /**
1210
+ * Errors thrown during application bootstrap — the phase where modules, providers,
1211
+ * views, windows, and bridge channels are validated and assembled into the runtime graph.
1212
+ *
1213
+ * All instances are created through static factory methods; direct construction is not allowed.
1214
+ *
1215
+ * @remarks
1216
+ * Bootstrap errors indicate misconfiguration that must be fixed before the app can start.
1217
+ * They are always thrown synchronously during {@link Kernel.start} (or equivalent bootstrap entry point).
1218
+ */
1219
+ declare class BootstrapError extends RuntimeError {
1220
+ private constructor();
1221
+ /** The class passed as root module is missing the `@Module()` decorator. */
1222
+ static rootModuleNotDecorated(className: string): BootstrapError;
1223
+ /** A module's `imports` array contains a class that is not decorated with `@Module()`. */
1224
+ static invalidImportedModule(parentModule: string, importedName: string): BootstrapError;
1225
+ /** A module's `providers` array contains a class that is not decorated with `@Injectable()`. */
1226
+ static invalidModuleProvider(moduleName: string, providerName: string): BootstrapError;
1227
+ /** A module's `views` array contains a class that is not decorated with `@View()`. */
1228
+ static invalidModuleView(moduleName: string, viewName: string): BootstrapError;
1229
+ /** A module's `windows` array contains a class that is not decorated with `@Window()`. */
1230
+ static invalidModuleWindow(moduleName: string, windowName: string): BootstrapError;
1231
+ /**
1232
+ * Two or more modules import each other, forming a cycle.
1233
+ *
1234
+ * @remarks
1235
+ * The `cycle` context field contains the full import chain (e.g. `["A", "B", "C", "A"]`).
1236
+ */
1237
+ static circularModuleImport(cycle: readonly string[]): BootstrapError;
1238
+ /** Two modules resolved to the same module id. Module ids must be unique across the application. */
1239
+ static duplicateModuleId(moduleId: string): BootstrapError;
1240
+ /** A module exports a token that is not present in its own `providers` array. */
1241
+ static invalidExport(moduleName: string, exportName: string): BootstrapError;
1242
+ /** Two views resolved to the same view id. View ids must be unique across the application. */
1243
+ static duplicateViewId(viewId: string): BootstrapError;
1244
+ /** Two windows resolved to the same window id. Window ids must be unique across the application. */
1245
+ static duplicateWindowId(windowId: string): BootstrapError;
1246
+ /** Two bridge handlers registered the same channel name. Bridge channels must be unique. */
1247
+ static duplicateBridgeChannel(channel: string): BootstrapError;
1248
+ /** Two job handlers registered the same job id. Job ids must be unique across the application. */
1249
+ static duplicateJobId(jobId: string): BootstrapError;
1250
+ /** A provider is decorated with both `@View()` and `@Window()`. A provider can only have one role. */
1251
+ static invalidProviderRoleCombination(providerName: string): BootstrapError;
1252
+ /** A view's `access` list references a bridge channel that was not registered by any provider. */
1253
+ static invalidViewAccessReference(viewId: string, channel: string): BootstrapError;
1254
+ /** A view's `signals` list references a signal id that has no corresponding `@signal()` handler. */
1255
+ static invalidViewSignalReference(viewId: string, signalId: string): BootstrapError;
1256
+ /** A module imports another module that has not been loaded into the runtime graph yet. */
1257
+ static importedModuleNotLoaded(parentModule: string, importedModule: string): BootstrapError;
1258
+ /** A capability decorator (e.g. `@command`, `@query`) points to a property that is not a function. */
1259
+ static invalidCapabilityMethod(providerName: string, capability: string, methodName: string): BootstrapError;
1260
+ }
1261
+ //#endregion
1262
+ //#region src/errors/bridge.d.ts
1263
+ /**
1264
+ * Errors thrown by the IPC bridge subsystem when renderer-to-main communication fails.
1265
+ *
1266
+ * All instances are created through static factory methods; direct construction is not allowed.
1267
+ */
1268
+ declare class BridgeError extends RuntimeError {
1269
+ private constructor();
1270
+ /** The originating view is not whitelisted for the requested bridge channel. */
1271
+ static accessDenied(viewId: string, channel: string): BridgeError;
1272
+ /** No handler has been registered for the given bridge channel. */
1273
+ static routeNotFound(channel: string): BridgeError;
1274
+ /**
1275
+ * A bridge handler threw while processing a request.
1276
+ *
1277
+ * @remarks
1278
+ * The original error is attached as {@link Error.cause}.
1279
+ */
1280
+ static handlerFailed(channel: string, cause: unknown): BridgeError;
1281
+ /** A bridge call arrived before the kernel finished starting or after it began shutting down. */
1282
+ static kernelNotReady(): BridgeError;
1283
+ /** A bridge request came from a `webContents` that is not associated with any known view. */
1284
+ static unknownRenderer(webContentsId: number): BridgeError;
1285
+ }
1286
+ //#endregion
1287
+ //#region src/errors/di.d.ts
1288
+ /**
1289
+ * Errors thrown by the dependency injection container during provider resolution and registration.
1290
+ *
1291
+ * All instances are created through static factory methods; direct construction is not allowed.
1292
+ */
1293
+ declare class DIError extends RuntimeError {
1294
+ private constructor();
1295
+ /** The requested injection token has no matching provider in this injector or any ancestor. */
1296
+ static providerNotFound(token: string): DIError;
1297
+ /** A provider with the same token is already registered in this injector. */
1298
+ static duplicateProvider(token: string): DIError;
1299
+ /**
1300
+ * Two or more providers depend on each other, forming a cycle that cannot be resolved.
1301
+ *
1302
+ * @remarks
1303
+ * The `path` context field contains the full resolution chain (e.g. `["A", "B", "C", "A"]`).
1304
+ */
1305
+ static circularDependency(path: readonly string[]): DIError;
1306
+ /** A class was passed as a provider but is missing a framework decorator (`@Injectable()`, `@Module()`, `@View()`, or `@Window()`). */
1307
+ static invalidClassProvider(token: string): DIError;
1308
+ /**
1309
+ * {@link inject} was called outside of a framework-managed execution context.
1310
+ *
1311
+ * @remarks
1312
+ * `inject()` is only available during construction (property initializers),
1313
+ * lifecycle hooks (`onInit`/`onReady`/`onShutdown`/`onDispose`),
1314
+ * and capability handlers (`@command`, `@query`, `@signal`, `@job`).
1315
+ */
1316
+ static noInjectionContext(): DIError;
1317
+ }
1318
+ //#endregion
1319
+ //#region src/errors/job.d.ts
1320
+ /**
1321
+ * Errors thrown by the job scheduling and execution subsystem.
1322
+ *
1323
+ * All instances are created through static factory methods; direct construction is not allowed.
1324
+ */
1325
+ declare class JobError extends RuntimeError {
1326
+ private constructor();
1327
+ /** No job handler has been registered under the given job id. */
1328
+ static notFound(jobId: string): JobError;
1329
+ /** The job is already executing and does not support concurrent runs. */
1330
+ static alreadyRunning(jobId: string): JobError;
1331
+ /**
1332
+ * A job handler threw during execution.
1333
+ *
1334
+ * @remarks
1335
+ * The original error is attached as {@link Error.cause}.
1336
+ */
1337
+ static executionFailed(jobId: string, cause: unknown): JobError;
1338
+ }
1339
+ //#endregion
1340
+ //#region src/errors/lifecycle.d.ts
1341
+ /**
1342
+ * Errors thrown during kernel and module lifecycle transitions (start, shutdown, hook execution).
1343
+ *
1344
+ * All instances are created through static factory methods; direct construction is not allowed.
1345
+ */
1346
+ declare class LifecycleError extends RuntimeError {
1347
+ private constructor();
1348
+ /**
1349
+ * A lifecycle hook (`onInit`, `onReady`, etc.) threw during the startup sequence.
1350
+ *
1351
+ * @remarks
1352
+ * The original error is attached as {@link Error.cause}.
1353
+ */
1354
+ static startupFailed(hookName: string, targetName: string, cause: unknown): LifecycleError;
1355
+ /** The kernel was asked to move to a state that is not reachable from its current state. */
1356
+ static invalidKernelTransition(from: string, to: string): LifecycleError;
1357
+ /** A module was asked to move to a state that is not reachable from its current state. */
1358
+ static invalidModuleTransition(moduleId: string, from: string, to: string): LifecycleError;
1359
+ /** Shutdown was requested but the kernel has not been started yet. */
1360
+ static kernelNotStarted(): LifecycleError;
1361
+ /** Start was requested but the kernel is already started or in the process of starting. */
1362
+ static kernelAlreadyStarted(): LifecycleError;
1363
+ }
1364
+ //#endregion
1365
+ //#region src/errors/signal.d.ts
1366
+ /**
1367
+ * Errors thrown when signal dispatching or registration fails.
1368
+ *
1369
+ * All instances are created through static factory methods; direct construction is not allowed.
1370
+ */
1371
+ declare class SignalError extends RuntimeError {
1372
+ private constructor();
1373
+ /** The provided signal id is not a non-empty string. */
1374
+ static invalidSignalId(signalId: unknown): SignalError;
1375
+ }
1376
+ //#endregion
1377
+ //#region src/contracts/authoring.d.ts
1378
+ /**
1379
+ * Codegen contract types for `@electrojs/runtime`.
1380
+ *
1381
+ * These interfaces and types are used by `@electrojs/codegen` to generate
1382
+ * type-safe authoring APIs. The codegen augments the empty registry interfaces
1383
+ * via `declare module "@electro"` to populate them with app-specific types.
1384
+ *
1385
+ * @module contracts/authoring
1386
+ */
1387
+ /** Maps `"moduleId:methodId"` to the method's type reference. Augmented by codegen. */
1388
+ interface ModuleMethodMap {}
1389
+ /** Maps module IDs to their method type objects. Augmented by codegen. */
1390
+ interface ModuleApiRegistry {}
1391
+ /** Maps signal keys to their payload types. Augmented by codegen. */
1392
+ interface ModuleSignalPayloadMap {}
1393
+ /** Maps module IDs to their job ID unions. Augmented by codegen. */
1394
+ interface ModuleJobRegistry {}
1395
+ /** Maps injectable class names to their class types. Augmented by codegen. */
1396
+ interface InjectableClassRegistry {}
1397
+ /** Maps window IDs to their `@Window()` class types. Augmented by codegen. */
1398
+ interface WindowClassRegistry {}
1399
+ /** Maps view IDs to their `@View()` class types. Augmented by codegen. */
1400
+ interface ViewClassRegistry {}
1401
+ /** Union of all registered module IDs. Derived from `ModuleApiRegistry` keys. */
1402
+ type ModuleRegistryId = keyof ModuleApiRegistry;
1403
+ type JobIdFor<TModuleId extends ModuleRegistryId> = Extract<ModuleJobRegistry[TModuleId], string>;
1404
+ type SignalId = Extract<keyof ModuleSignalPayloadMap, string>;
1405
+ type VoidSignalId = { [TKey in SignalId]: ModuleSignalPayloadMap[TKey] extends void ? TKey : never }[SignalId];
1406
+ type NonVoidSignalId = Exclude<SignalId, VoidSignalId>;
1407
+ /** A class decorated with `@Module()`. Used in generated registry arrays. */
1408
+ type ModuleClass = Constructor;
1409
+ /** A class decorated with `@View()`. Used in generated registry arrays. */
1410
+ type ViewClass = Constructor;
1411
+ /** A class decorated with `@Window()`. Used in generated registry arrays. */
1412
+ type WindowClass = Constructor;
1413
+ /**
1414
+ * Shape of the static kernel definition object generated by codegen.
1415
+ *
1416
+ * Used by the generated `electroAppDefinition` constant which can be
1417
+ * passed to `AppKernel.create()` for fully typed bootstrapping.
1418
+ */
1419
+ interface AppKernelDefinition {
1420
+ readonly root: Constructor;
1421
+ readonly modules: readonly Constructor[];
1422
+ readonly windows: readonly Constructor[];
1423
+ readonly views: readonly Constructor[];
1424
+ }
1425
+ interface TypedSignalBus {
1426
+ publish<TSignalId extends VoidSignalId>(signalId: TSignalId): void;
1427
+ publish<TSignalId extends NonVoidSignalId>(signalId: TSignalId, payload: ModuleSignalPayloadMap[TSignalId]): void;
1428
+ subscribe<TSignalId extends SignalId>(signalId: TSignalId, handler: SignalHandler<ModuleSignalPayloadMap[TSignalId]>): () => void;
1429
+ }
1430
+ interface TypedJobRegistry<TJobId extends string = string> {
1431
+ ensure(jobId: TJobId): void;
1432
+ start(jobId: TJobId): void;
1433
+ run(jobId: TJobId, ...args: unknown[]): Promise<unknown>;
1434
+ stop(jobId: TJobId): Promise<void>;
1435
+ cancel(jobId: TJobId): void;
1436
+ getStatus(jobId: TJobId): JobRuntimeState | undefined;
1437
+ list(): readonly JobRuntimeState[];
1438
+ }
1439
+ /**
1440
+ * Base type augmented onto module and provider classes by codegen.
1441
+ *
1442
+ * Codegen generates `interface MyModule extends ModuleAuthoringApi<"myModuleId"> {}`
1443
+ * which gives the class access to typed methods based on the module's registered
1444
+ * commands, queries, signals, and jobs.
1445
+ *
1446
+ */
1447
+ interface ModuleAuthoringApi<TModuleId extends ModuleRegistryId> {
1448
+ readonly moduleId: TModuleId;
1449
+ readonly api: ModuleApiRegistry[TModuleId];
1450
+ readonly signals: TypedSignalBus;
1451
+ readonly jobs: TypedJobRegistry<JobIdFor<TModuleId>>;
1452
+ readonly modules: ModuleRegistry;
1453
+ readonly windows: WindowManager;
1454
+ readonly views: ViewManager;
1455
+ readonly logger: ElectroLogger;
1456
+ }
1457
+ /**
1458
+ * Base type augmented onto `@Window()` classes by codegen.
1459
+ *
1460
+ * Provides typed window management capabilities when extended by codegen-generated
1461
+ * interface augmentations.
1462
+ */
1463
+ interface WindowAuthoringApi extends WindowAuthoringSurface {
1464
+ readonly logger: ElectroLogger;
1465
+ }
1466
+ /**
1467
+ * Base type augmented onto `@View()` classes by codegen.
1468
+ *
1469
+ * Provides typed view management capabilities when extended by codegen-generated
1470
+ * interface augmentations.
1471
+ */
1472
+ interface ViewAuthoringApi extends ViewAuthoringSurface {
1473
+ readonly logger: ElectroLogger;
1474
+ }
1475
+ //#endregion
1476
+ export { type AppDefinition, AppKernel, type AppKernelDefinition, type AppKernelOptions, BootstrapError, BridgeAccessGuard, type BridgeClientConfig, BridgeDispatcher, BridgeError, BridgeHandler, type BridgeMethodDefinition, type BridgeMethodKind, type BridgeRequest, type BridgeResponse, type ContextualSignalHandler, DIError, type ElectroIpcRenderer, type ElectroLogBindings, type ElectroLogContext, type ElectroLogLevel, type ElectroLogger, IPC_CHANNELS, type InjectableClassRegistry, InjectionContext, Injector, JobContext, type JobDefinition, JobError, JobRegistry, type JobRuntimeState, type JobStatus, type KernelState, LifecycleError, type LifecycleTarget, type ModuleApiRegistry, type ModuleAuthoringApi, type ModuleClass, type ModuleDefinition, type ModuleJobRegistry, type ModuleMethodMap, ModuleRef, ModuleRegistry, type ModuleRegistryId, type ModuleSignalPayloadMap, type ModuleSnapshot, type ModuleStatus, type PreloadBridgeApi, type ProviderDefinition, type ProviderKind, ProviderRef, type ProviderSnapshot, RendererRegistry, RendererSession, RuntimeError, SignalBus, SignalContext, SignalError, type SignalHandler, type SignalHandlerDefinition, type SignalListener, type TypedJobRegistry, type TypedSignalBus, type ViewAuthoringApi, type ViewClass, type ViewClassRegistry, type ViewDefinition, ViewManager, ViewProvider, type WindowAuthoringApi, type WindowClass, type WindowClassRegistry, type WindowDefinition, WindowManager, WindowProvider, createBridgeClient, createConsoleLogger, inject, scanModules, serializeBridgeError, validateAppDefinition };