@electrojs/runtime 1.0.8 → 1.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.
Files changed (2) hide show
  1. package/dist/index.d.mts +498 -496
  2. package/package.json +5 -5
package/dist/index.d.mts CHANGED
@@ -473,64 +473,318 @@ declare class AppKernel {
473
473
  private safeDisposeServices;
474
474
  }
475
475
  //#endregion
476
- //#region src/container/inject.d.ts
476
+ //#region src/desktop/view-manager.d.ts
477
477
  /**
478
- * Resolve a dependency from the current injection context.
478
+ * Framework-internal registry that tracks all `@View()` providers in the application.
479
479
  *
480
- * This is the primary way framework-managed classes obtain their dependencies.
481
- * It reads the active {@link Injector} from `AsyncLocalStorage` and delegates to
482
- * {@link Injector.get}.
480
+ * Handles registration (including injecting the source URL into the base class)
481
+ * and provides lookup by view ID. Consumers typically interact with views through
482
+ * their {@link ViewProvider} subclass rather than this manager directly.
483
483
  *
484
- * @remarks
485
- * `inject()` is only available inside a framework-managed execution scope:
486
- * - **Construction** -- property initializers of `@Injectable()`, `@Module()`, `@View()`, or `@Window()` classes
487
- * - **Lifecycle hooks** -- `onInit`, `onStart`, `onReady`, `onShutdown`, `onDispose`
488
- * - **Capability handlers** -- methods decorated with `@command`, `@query`, `@signal`, or `@job`
484
+ * @internal
485
+ */
486
+ declare class ViewManager {
487
+ private readonly views;
488
+ /**
489
+ * Register a view provider and apply its `@View()` source URL.
490
+ *
491
+ * @remarks Silently skips providers that do not have view metadata.
492
+ */
493
+ register(providerRef: ProviderRef): void;
494
+ /** Look up a registered view provider by its view ID. */
495
+ get(viewId: string): ProviderRef | undefined;
496
+ /** Return all registered view providers. */
497
+ list(): readonly ProviderRef[];
498
+ /** Clear the registry. Does not destroy any underlying web contents. */
499
+ dispose(): Promise<void>;
500
+ }
501
+ //#endregion
502
+ //#region src/desktop/view-provider.d.ts
503
+ declare const VIEW_STATE: unique symbol;
504
+ interface ViewAuthoringSurface {
505
+ readonly contentView: WebContentsView | undefined;
506
+ readonly webContents: WebContents | undefined;
507
+ load(): Promise<void>;
508
+ setBounds(bounds: Rectangle): void;
509
+ setBackgroundColor(color: string): void;
510
+ focus(): void;
511
+ setWindowButtonVisibility(visible: boolean): void;
512
+ }
513
+ /**
514
+ * Abstract base class for view providers decorated with `@View()`.
489
515
  *
490
- * Calling it anywhere else (e.g. in a `setTimeout` callback or a plain function)
491
- * throws {@link DIError} with code `ELECTRO_DI_NO_INJECTION_CONTEXT`.
516
+ * Extend this class to define a renderable view in your application. The framework
517
+ * injects the source URL from the `@View()` decorator, and your subclass gains access
518
+ * to methods for loading content, positioning, and styling.
519
+ *
520
+ * Views are created with strict security defaults: `sandbox: true`,
521
+ * `contextIsolation: true`, and `nodeIntegration: false`.
522
+ *
523
+ * @remarks The `WebContentsView` is lazily created on the first call to {@link load}.
492
524
  *
493
525
  * @example
494
526
  * ```ts
495
- * @Injectable()
496
- * class MyService {
497
- * private readonly config = inject(AppConfig);
527
+ * @View({ source: 'view:main', access: ['app:getVersion'] })
528
+ * class MainView extends ViewProvider {
529
+ * async onStart() {
530
+ * await this.load();
531
+ * this.setBounds({ x: 0, y: 0, width: 800, height: 600 });
532
+ * }
498
533
  * }
499
534
  * ```
535
+ */
536
+ declare abstract class ViewProvider {
537
+ private [VIEW_STATE];
538
+ /** The underlying Electron `WebContentsView`, or `undefined` if not yet created. */
539
+ get contentView(): WebContentsView | undefined;
540
+ /** The `WebContents` associated with this view, or `undefined` if not yet created. */
541
+ get webContents(): WebContents | undefined;
542
+ /**
543
+ * Create the underlying `WebContentsView` (if needed) and load the configured source URL.
544
+ *
545
+ * The view is lazily created on the first call. Subsequent calls reload the source.
546
+ * If the previous view was destroyed (e.g. parent window closed), a new one is created.
547
+ * No-ops if no source URL has been configured.
548
+ */
549
+ load(): Promise<void>;
550
+ /** Set the position and size of this view within its parent window. */
551
+ setBounds(bounds: Rectangle): void;
552
+ /** Set the background color of the view (e.g. `"#ffffff"` or `"transparent"`). */
553
+ setBackgroundColor(color: string): void;
554
+ /** Give keyboard focus to this view's web contents. */
555
+ focus(): void;
556
+ /** Show or hide the native window traffic-light buttons for this view (macOS). */
557
+ setWindowButtonVisibility(visible: boolean): void;
558
+ private createView;
559
+ private static resolveSource;
560
+ /** @internal Called by the framework to set the view source from @View metadata. */
561
+ static __setSource(instance: ViewProvider, source: string): void;
562
+ /** @internal Called by the framework to set web preferences from @View metadata. */
563
+ static __setWebPreferences(instance: ViewProvider, webPreferences: WebPreferences): void;
564
+ }
565
+ //#endregion
566
+ //#region src/desktop/window-manager.d.ts
567
+ /**
568
+ * Framework-internal registry that tracks all `@Window()` providers in the application.
500
569
  *
501
- * @throws {@link DIError} if no injection context is active or the token cannot be resolved.
570
+ * Handles registration (including injecting `@Window()` configuration into the base class)
571
+ * and provides lookup by window ID. Consumers typically interact with windows through
572
+ * their {@link WindowProvider} subclass rather than this manager directly.
573
+ *
574
+ * @internal
502
575
  */
503
- declare function inject<T>(token: InjectionToken<T>): T;
576
+ declare class WindowManager {
577
+ private readonly windows;
578
+ /**
579
+ * Register a window provider and apply its `@Window()` configuration.
580
+ *
581
+ * @remarks Silently skips providers that do not have window metadata.
582
+ */
583
+ register(providerRef: ProviderRef): void;
584
+ /** Look up a registered window provider by its window ID. */
585
+ get(windowId: string): ProviderRef | undefined;
586
+ /** Return all registered window providers. */
587
+ list(): readonly ProviderRef[];
588
+ /** Close all managed windows and clear the registry. */
589
+ dispose(): Promise<void>;
590
+ }
504
591
  //#endregion
505
- //#region src/container/injection-context.d.ts
592
+ //#region src/desktop/window-provider.d.ts
593
+ declare const WINDOW_STATE: unique symbol;
594
+ interface WindowAuthoringSurface {
595
+ readonly window: BaseWindow | undefined;
596
+ create(): void;
597
+ mount(view: Pick<ViewProvider, "contentView">): void;
598
+ show(): void;
599
+ hide(): void;
600
+ focus(): void;
601
+ close(): void;
602
+ getBounds(): Rectangle | undefined;
603
+ }
506
604
  /**
507
- * Ambient injection context backed by `AsyncLocalStorage`.
605
+ * Abstract base class for window providers decorated with `@Window()`.
508
606
  *
509
- * The framework uses `InjectionContext` to make the current {@link Injector} available
510
- * to {@link inject} calls without requiring explicit injector references. It is set
511
- * automatically during provider construction, lifecycle hooks, and capability handlers.
607
+ * Extend this class to define a window in your application. The framework injects
608
+ * configuration from the `@Window()` decorator metadata, and your subclass gains
609
+ * access to lifecycle methods like {@link create}, {@link show}, {@link mount}, and {@link close}.
512
610
  *
513
- * @remarks
514
- * This is a framework-internal API. Application code should use {@link inject} instead
515
- * of interacting with `InjectionContext` directly.
611
+ * @remarks The native `BaseWindow` instance is only available after calling {@link create}.
612
+ * Calling lifecycle methods before `create()` is safe (they no-op) but the window
613
+ * will not exist on screen.
516
614
  *
517
- * @internal
615
+ * @example
616
+ * ```ts
617
+ * @Window({ width: 800, height: 600, show: false })
618
+ * class MainWindow extends WindowProvider {
619
+ * async onStart() {
620
+ * this.create();
621
+ * this.mount(this.mainView);
622
+ * this.show();
623
+ * }
624
+ * }
625
+ * ```
518
626
  */
519
- declare const InjectionContext: {
627
+ declare abstract class WindowProvider {
628
+ private [WINDOW_STATE];
629
+ /** The underlying Electron `BaseWindow` instance, or `undefined` if not yet created. */
630
+ get window(): BaseWindow | undefined;
631
+ /** Create the native `BaseWindow` using configuration from the `@Window()` decorator. */
632
+ create(): void;
520
633
  /**
521
- * Execute `fn` within the scope of the given injector.
522
- * Any {@link inject} call made synchronously inside `fn` will resolve from this injector.
634
+ * Attach a view's content to this window.
635
+ *
636
+ * The view's `WebContentsView` is added as a child view of the window's content area.
637
+ * No-ops silently if the window or view has not been created yet.
523
638
  */
524
- readonly run: <T>(injector: Injector, fn: () => T) => T;
639
+ mount(view: ViewProvider): void;
640
+ /** Show the window. No-ops if the window has not been created. */
641
+ show(): void;
642
+ /** Hide the window without destroying it. */
643
+ hide(): void;
644
+ /** Bring the window to the front and give it focus. */
645
+ focus(): void;
646
+ /** Close and destroy the native window, releasing its resources. */
647
+ close(): void;
648
+ /** Return the window's current screen bounds, or `undefined` if not created. */
649
+ getBounds(): Rectangle | undefined;
650
+ /** @internal Called by the framework to set the window configuration from @Window metadata. */
651
+ static __setConfiguration(instance: WindowProvider, configuration?: BaseWindowConstructorOptions): void;
652
+ }
653
+ //#endregion
654
+ //#region src/jobs/context.d.ts
655
+ /**
656
+ * Execution context passed to every job handler invocation.
657
+ *
658
+ * Provides cooperative cancellation and progress reporting. The handler should
659
+ * periodically check {@link isCanceled} and abort work when it returns `true`.
660
+ *
661
+ * @example
662
+ * ```ts
663
+ * async function cleanupHandler(ctx: JobContext) {
664
+ * const items = await fetchItems();
665
+ * for (let i = 0; i < items.length; i++) {
666
+ * if (ctx.isCanceled) return;
667
+ * await processItem(items[i]);
668
+ * ctx.setProgress((i / items.length) * 100);
669
+ * }
670
+ * }
671
+ * ```
672
+ */
673
+ declare class JobContext {
674
+ private canceledInternal;
675
+ private progressInternal;
676
+ /** Whether cancellation has been requested for this execution. */
677
+ get isCanceled(): boolean;
678
+ /** Current progress value, clamped to 0-100. */
679
+ get progress(): number;
525
680
  /**
526
- * Execute `fn` within the scope of the given injector, additionally tracking `owner`
527
- * as the object currently being constructed or invoked.
681
+ * Report execution progress.
682
+ *
683
+ * @remarks Values are clamped to the 0-100 range.
528
684
  */
529
- readonly runOwned: <T>(injector: Injector, owner: object, fn: () => T) => T; /** Return the injector for the current execution context, or `undefined` if none is active. */
530
- readonly current: () => Injector | undefined; /** Return the owner object of the current execution context, or `undefined` if not set. */
531
- readonly currentOwner: () => object | undefined; /** Whether a framework-managed injection context is currently active. */
532
- readonly isActive: () => boolean;
533
- };
685
+ setProgress(value: number): void;
686
+ /** @internal */
687
+ cancel(): void;
688
+ }
689
+ //#endregion
690
+ //#region src/jobs/registry.d.ts
691
+ type Awaitable$1<T> = T | PromiseLike<T>;
692
+ /**
693
+ * Describes a job as provided during module bootstrap.
694
+ *
695
+ * @internal Consumed by {@link JobRegistry.register}; not intended for direct consumer use.
696
+ */
697
+ interface JobDefinitionRecord {
698
+ readonly jobId: string;
699
+ /** Cron expression (Croner syntax). Omit for manually-triggered-only jobs. */
700
+ readonly cron?: string;
701
+ /** The handler to execute. Receives a {@link JobContext} for cancellation/progress, plus any extra args from manual runs. */
702
+ readonly handler: (context: JobContext, ...args: unknown[]) => Awaitable$1<unknown>;
703
+ /** Injector used to restore the DI context when the handler runs. */
704
+ readonly injector: Injector;
705
+ }
706
+ /** Lifecycle state of a registered job. */
707
+ type JobStatus = "idle" | "scheduled" | "running";
708
+ /** Read-only snapshot of a job's current runtime state. */
709
+ interface JobRuntimeState {
710
+ readonly jobId: string;
711
+ readonly status: JobStatus;
712
+ /** Last reported progress value (0-100). */
713
+ readonly progress: number;
714
+ /** Epoch timestamp of the last completed execution, if any. */
715
+ readonly lastRunAt?: number;
716
+ }
717
+ /**
718
+ * Manages the lifecycle of scheduled and manually-triggered jobs.
719
+ *
720
+ * Jobs are registered during bootstrap (via `@internal` {@link register}), then consumers
721
+ * interact through `start`, `stop`, `run`, and `cancel`. Scheduled jobs use Croner for
722
+ * cron-based timing; each execution receives a fresh {@link JobContext} for progress
723
+ * reporting and cooperative cancellation.
724
+ *
725
+ * @example
726
+ * ```ts
727
+ * // Start the cron scheduler for a registered job
728
+ * jobRegistry.start('data:cleanup');
729
+ *
730
+ * // Trigger an immediate (manual) execution
731
+ * await jobRegistry.run('data:cleanup');
732
+ *
733
+ * // Cancel a running execution cooperatively
734
+ * jobRegistry.cancel('data:cleanup');
735
+ *
736
+ * // Stop the cron scheduler and wait for any running execution to finish
737
+ * await jobRegistry.stop('data:cleanup');
738
+ * ```
739
+ */
740
+ declare class JobRegistry {
741
+ private readonly jobs;
742
+ /** @internal Register a job definition during bootstrap. */
743
+ register(definition: JobDefinitionRecord): void;
744
+ /** Return a snapshot of all registered jobs and their current state. */
745
+ list(): readonly JobRuntimeState[];
746
+ /** Return the current state of a single job, or `undefined` if not registered. */
747
+ getStatus(jobId: string): JobRuntimeState | undefined;
748
+ /**
749
+ * Start the cron scheduler for a job if it is not already scheduled.
750
+ *
751
+ * Unlike {@link start}, this is idempotent and will not throw if the scheduler
752
+ * is already running.
753
+ */
754
+ ensure(jobId: string): void;
755
+ /**
756
+ * Start the cron scheduler for a job.
757
+ *
758
+ * @throws {JobError} If the job already has an active scheduler.
759
+ */
760
+ start(jobId: string): void;
761
+ /**
762
+ * Trigger an immediate (manual) execution of a job, bypassing the cron schedule.
763
+ *
764
+ * @throws {JobError} If the job is already running.
765
+ * @returns The value returned by the job handler.
766
+ */
767
+ run(jobId: string, ...args: unknown[]): Promise<unknown>;
768
+ /**
769
+ * Stop the cron scheduler and cancel any in-flight execution.
770
+ *
771
+ * Waits for the running execution (if any) to settle before returning. The job
772
+ * transitions to `"idle"` once fully stopped.
773
+ */
774
+ stop(jobId: string): Promise<void>;
775
+ /**
776
+ * Request cooperative cancellation of the currently running execution.
777
+ *
778
+ * Sets the `isCanceled` flag on the job's {@link JobContext}. The handler is
779
+ * responsible for checking this flag and aborting work accordingly.
780
+ */
781
+ cancel(jobId: string): void;
782
+ /** @internal */
783
+ dispose(): Promise<void>;
784
+ private getJobOrThrow;
785
+ private startScheduler;
786
+ private executeJob;
787
+ }
534
788
  //#endregion
535
789
  //#region src/modules/registry.d.ts
536
790
  /**
@@ -591,24 +845,6 @@ declare class ModuleRegistry {
591
845
  snapshot(): readonly ModuleSnapshot[];
592
846
  }
593
847
  //#endregion
594
- //#region src/modules/validator.d.ts
595
- /**
596
- * Validates a scanned {@link AppDefinition} for structural correctness before bootstrap.
597
- *
598
- * Checks performed:
599
- * - Unique module IDs
600
- * - Exports reference declared providers
601
- * - No cyclic module imports
602
- * - Unique view/window IDs
603
- * - Unique bridge channel names
604
- * - Unique job IDs
605
- * - Provider role exclusivity (a class cannot be both a view and a window)
606
- * - View access references point to existing bridge channels
607
- *
608
- * @throws {BootstrapError} On the first validation failure encountered.
609
- */
610
- declare function validateAppDefinition(definition: AppDefinition): void;
611
- //#endregion
612
848
  //#region src/signals/relay.d.ts
613
849
  /**
614
850
  * Callback invoked by {@link PublicationRelay} whenever a signal is published.
@@ -684,399 +920,264 @@ declare class SignalBus {
684
920
  private readonly handlers;
685
921
  private readonly relay;
686
922
  /**
687
- * Register a handler for the given signal.
688
- *
689
- * The handler is bound to the current injection context at call time, so
690
- * `inject()` resolves correctly even though the handler runs asynchronously.
691
- *
692
- * @returns A dispose function that removes the subscription.
693
- */
694
- subscribe<T>(signalId: string, handler: SignalHandler<T>): () => void;
695
- /**
696
- * Publish a signal to all registered handlers.
697
- *
698
- * Handlers are invoked asynchronously via `queueMicrotask` and their errors are
699
- * logged but never propagated to the publisher. The signal is also forwarded to
700
- * any connected {@link PublicationRelay} listeners (e.g. renderer processes).
701
- *
702
- * @remarks Payload is optional for signals that carry no data (`SignalBus.publish<void>('app:ready')`).
703
- */
704
- publish<T = void>(signalId: string, payload?: T): void;
705
- /** @internal Connect a relay listener (used by renderer registry). */
706
- connectRelay(listener: SignalPublishListener): () => void;
707
- }
708
- //#endregion
709
- //#region src/jobs/context.d.ts
710
- /**
711
- * Execution context passed to every job handler invocation.
712
- *
713
- * Provides cooperative cancellation and progress reporting. The handler should
714
- * periodically check {@link isCanceled} and abort work when it returns `true`.
715
- *
716
- * @example
717
- * ```ts
718
- * async function cleanupHandler(ctx: JobContext) {
719
- * const items = await fetchItems();
720
- * for (let i = 0; i < items.length; i++) {
721
- * if (ctx.isCanceled) return;
722
- * await processItem(items[i]);
723
- * ctx.setProgress((i / items.length) * 100);
724
- * }
725
- * }
726
- * ```
727
- */
728
- declare class JobContext {
729
- private canceledInternal;
730
- private progressInternal;
731
- /** Whether cancellation has been requested for this execution. */
732
- get isCanceled(): boolean;
733
- /** Current progress value, clamped to 0-100. */
734
- get progress(): number;
735
- /**
736
- * Report execution progress.
737
- *
738
- * @remarks Values are clamped to the 0-100 range.
739
- */
740
- setProgress(value: number): void;
741
- /** @internal */
742
- cancel(): void;
743
- }
744
- //#endregion
745
- //#region src/jobs/registry.d.ts
746
- type Awaitable$1<T> = T | PromiseLike<T>;
747
- /**
748
- * Describes a job as provided during module bootstrap.
749
- *
750
- * @internal Consumed by {@link JobRegistry.register}; not intended for direct consumer use.
751
- */
752
- interface JobDefinitionRecord {
753
- readonly jobId: string;
754
- /** Cron expression (Croner syntax). Omit for manually-triggered-only jobs. */
755
- readonly cron?: string;
756
- /** The handler to execute. Receives a {@link JobContext} for cancellation/progress, plus any extra args from manual runs. */
757
- readonly handler: (context: JobContext, ...args: unknown[]) => Awaitable$1<unknown>;
758
- /** Injector used to restore the DI context when the handler runs. */
759
- readonly injector: Injector;
760
- }
761
- /** Lifecycle state of a registered job. */
762
- type JobStatus = "idle" | "scheduled" | "running";
763
- /** Read-only snapshot of a job's current runtime state. */
764
- interface JobRuntimeState {
765
- readonly jobId: string;
766
- readonly status: JobStatus;
767
- /** Last reported progress value (0-100). */
768
- readonly progress: number;
769
- /** Epoch timestamp of the last completed execution, if any. */
770
- readonly lastRunAt?: number;
771
- }
772
- /**
773
- * Manages the lifecycle of scheduled and manually-triggered jobs.
774
- *
775
- * Jobs are registered during bootstrap (via `@internal` {@link register}), then consumers
776
- * interact through `start`, `stop`, `run`, and `cancel`. Scheduled jobs use Croner for
777
- * cron-based timing; each execution receives a fresh {@link JobContext} for progress
778
- * reporting and cooperative cancellation.
779
- *
780
- * @example
781
- * ```ts
782
- * // Start the cron scheduler for a registered job
783
- * jobRegistry.start('data:cleanup');
784
- *
785
- * // Trigger an immediate (manual) execution
786
- * await jobRegistry.run('data:cleanup');
787
- *
788
- * // Cancel a running execution cooperatively
789
- * jobRegistry.cancel('data:cleanup');
790
- *
791
- * // Stop the cron scheduler and wait for any running execution to finish
792
- * await jobRegistry.stop('data:cleanup');
793
- * ```
794
- */
795
- declare class JobRegistry {
796
- private readonly jobs;
797
- /** @internal Register a job definition during bootstrap. */
798
- register(definition: JobDefinitionRecord): void;
799
- /** Return a snapshot of all registered jobs and their current state. */
800
- list(): readonly JobRuntimeState[];
801
- /** Return the current state of a single job, or `undefined` if not registered. */
802
- getStatus(jobId: string): JobRuntimeState | undefined;
803
- /**
804
- * Start the cron scheduler for a job if it is not already scheduled.
805
- *
806
- * Unlike {@link start}, this is idempotent and will not throw if the scheduler
807
- * is already running.
808
- */
809
- ensure(jobId: string): void;
810
- /**
811
- * Start the cron scheduler for a job.
812
- *
813
- * @throws {JobError} If the job already has an active scheduler.
814
- */
815
- start(jobId: string): void;
816
- /**
817
- * Trigger an immediate (manual) execution of a job, bypassing the cron schedule.
923
+ * Register a handler for the given signal.
818
924
  *
819
- * @throws {JobError} If the job is already running.
820
- * @returns The value returned by the job handler.
821
- */
822
- run(jobId: string, ...args: unknown[]): Promise<unknown>;
823
- /**
824
- * Stop the cron scheduler and cancel any in-flight execution.
925
+ * The handler is bound to the current injection context at call time, so
926
+ * `inject()` resolves correctly even though the handler runs asynchronously.
825
927
  *
826
- * Waits for the running execution (if any) to settle before returning. The job
827
- * transitions to `"idle"` once fully stopped.
928
+ * @returns A dispose function that removes the subscription.
828
929
  */
829
- stop(jobId: string): Promise<void>;
930
+ subscribe<T>(signalId: string, handler: SignalListener<T>): () => void;
931
+ subscribe<T>(signalId: string, handler: ContextualSignalHandler<T>): () => void;
830
932
  /**
831
- * Request cooperative cancellation of the currently running execution.
933
+ * Publish a signal to all registered handlers.
832
934
  *
833
- * Sets the `isCanceled` flag on the job's {@link JobContext}. The handler is
834
- * responsible for checking this flag and aborting work accordingly.
935
+ * Handlers are invoked asynchronously via `queueMicrotask` and their errors are
936
+ * logged but never propagated to the publisher. The signal is also forwarded to
937
+ * any connected {@link PublicationRelay} listeners (e.g. renderer processes).
938
+ *
939
+ * @remarks Payload is optional for signals that carry no data (`SignalBus.publish<void>('app:ready')`).
835
940
  */
836
- cancel(jobId: string): void;
837
- /** @internal */
838
- dispose(): Promise<void>;
839
- private getJobOrThrow;
840
- private startScheduler;
841
- private executeJob;
941
+ publish<T = void>(signalId: string, payload?: T): void;
942
+ /** @internal Connect a relay listener (used by renderer registry). */
943
+ connectRelay(listener: SignalPublishListener): () => void;
842
944
  }
843
945
  //#endregion
844
- //#region src/desktop/renderer-session.d.ts
946
+ //#region src/contracts/authoring.d.ts
845
947
  /**
846
- * Tracks the capabilities of a single renderer process (identified by `webContentsId`).
948
+ * Codegen contract types for `@electrojs/runtime`.
847
949
  *
848
- * Each session records which bridge channels the renderer may invoke and which signals
849
- * it is allowed to receive, as declared in the `@View()` decorator metadata. The
850
- * {@link BridgeAccessGuard} and signal relay use this information to enforce per-view
851
- * access control.
950
+ * These interfaces and types are used by `@electrojs/codegen` to generate
951
+ * type-safe authoring APIs. The codegen augments the empty registry interfaces
952
+ * via `declare module "@electro"` to populate them with app-specific types.
852
953
  *
853
- * @internal Created and managed by {@link RendererRegistry}.
954
+ * @module contracts/authoring
854
955
  */
855
- declare class RendererSession {
856
- /** The Electron `webContents.id` that uniquely identifies this renderer process. */
857
- readonly rendererId: number;
858
- /** The view ID this renderer is associated with. */
859
- readonly viewId: string;
860
- /** Set of bridge channel names this renderer is allowed to invoke. */
861
- readonly access: ReadonlySet<string>;
862
- /** Set of signal IDs this renderer is allowed to receive. */
863
- readonly allowedSignals: ReadonlySet<string>;
864
- constructor(/** The Electron `webContents.id` that uniquely identifies this renderer process. */
865
-
866
- rendererId: number, viewDef: ViewDefinition);
867
- /** Check whether this renderer has access to the given bridge channel. */
868
- hasAccess(channel: string): boolean;
869
- /** Check whether this renderer is allowed to receive the given signal. */
870
- canReceiveSignal(signalId: string): boolean;
956
+ /** Maps `"moduleId:methodId"` to the method's type reference. Augmented by codegen. */
957
+ interface ModuleMethodMap {}
958
+ /** Maps module IDs to their method type objects. Augmented by codegen. */
959
+ interface ModuleApiRegistry {}
960
+ /** Maps signal keys to their payload types. Augmented by codegen. */
961
+ interface ModuleSignalPayloadMap {}
962
+ /** Maps module IDs to their job ID unions. Augmented by codegen. */
963
+ interface ModuleJobRegistry {}
964
+ /** Maps injectable class names to their class types. Augmented by codegen. */
965
+ interface InjectableClassRegistry {}
966
+ /** Maps window IDs to their `@Window()` class types. Augmented by codegen. */
967
+ interface WindowClassRegistry {}
968
+ /** Maps view IDs to their `@View()` class types. Augmented by codegen. */
969
+ interface ViewClassRegistry {}
970
+ /** Union of all registered module IDs. Derived from `ModuleApiRegistry` keys. */
971
+ type ModuleRegistryId = keyof ModuleApiRegistry;
972
+ type JobIdFor<TModuleId extends ModuleRegistryId> = Extract<ModuleJobRegistry[TModuleId], string>;
973
+ type SignalId = Extract<keyof ModuleSignalPayloadMap, string>;
974
+ type VoidSignalId = { [TKey in SignalId]: ModuleSignalPayloadMap[TKey] extends void ? TKey : never }[SignalId];
975
+ type NonVoidSignalId = Exclude<SignalId, VoidSignalId>;
976
+ /** A class decorated with `@Module()`. Used in generated registry arrays. */
977
+ type ModuleClass = Constructor;
978
+ /** A class decorated with `@View()`. Used in generated registry arrays. */
979
+ type ViewClass = Constructor;
980
+ /** A class decorated with `@Window()`. Used in generated registry arrays. */
981
+ type WindowClass = Constructor;
982
+ /**
983
+ * Shape of the static kernel definition object generated by codegen.
984
+ *
985
+ * Used by the generated `electroAppDefinition` constant which can be
986
+ * passed to `AppKernel.create()` for fully typed bootstrapping.
987
+ */
988
+ interface AppKernelDefinition {
989
+ readonly root: Constructor;
990
+ readonly modules: readonly Constructor[];
991
+ readonly windows: readonly Constructor[];
992
+ readonly views: readonly Constructor[];
993
+ }
994
+ interface TypedSignalBus {
995
+ publish<TSignalId extends VoidSignalId>(signalId: TSignalId): void;
996
+ publish<TSignalId extends NonVoidSignalId>(signalId: TSignalId, payload: ModuleSignalPayloadMap[TSignalId]): void;
997
+ subscribe<TSignalId extends SignalId>(signalId: TSignalId, handler: SignalListener<ModuleSignalPayloadMap[TSignalId]>): () => void;
998
+ subscribe<TSignalId extends SignalId>(signalId: TSignalId, handler: ContextualSignalHandler<ModuleSignalPayloadMap[TSignalId]>): () => void;
999
+ }
1000
+ interface TypedJobRegistry<TJobId extends string = string> {
1001
+ ensure(jobId: TJobId): void;
1002
+ start(jobId: TJobId): void;
1003
+ run(jobId: TJobId, ...args: unknown[]): Promise<unknown>;
1004
+ stop(jobId: TJobId): Promise<void>;
1005
+ cancel(jobId: TJobId): void;
1006
+ getStatus(jobId: TJobId): JobRuntimeState | undefined;
1007
+ list(): readonly JobRuntimeState[];
871
1008
  }
872
- //#endregion
873
- //#region src/desktop/renderer-registry.d.ts
874
1009
  /**
875
- * Maps Electron `webContentsId` values to {@link RendererSession} instances.
1010
+ * Base type augmented onto module and provider classes by codegen.
876
1011
  *
877
- * Used by the bridge layer to look up which renderer process is making an IPC request
878
- * and determine what channels and signals it is allowed to access. View definitions are
879
- * registered at bootstrap time; sessions are created lazily when a renderer first
880
- * communicates.
1012
+ * Codegen generates `interface MyModule extends ModuleAuthoringApi<"myModuleId"> {}`
1013
+ * which gives the class access to typed methods based on the module's registered
1014
+ * commands, queries, signals, and jobs.
881
1015
  *
882
- * @internal
883
1016
  */
884
- declare class RendererRegistry {
885
- private readonly sessions;
886
- private readonly viewDefinitions;
887
- /** Store a view definition so that sessions can be created for it later. */
888
- registerView(viewDef: ViewDefinition): void;
889
- /**
890
- * Return the existing session for a `webContentsId`, or create one if this is
891
- * the first request from that renderer.
892
- *
893
- * @throws {BridgeError} If the `viewId` does not match any registered view definition.
894
- */
895
- getOrCreateSession(webContentsId: number, viewId: string): RendererSession;
896
- /** Look up an existing session by its `webContentsId`, or `undefined` if none exists. */
897
- getSession(webContentsId: number): RendererSession | undefined;
898
- /** Remove a session when its renderer process is destroyed. */
899
- removeSession(webContentsId: number): void;
900
- /** Return all active renderer sessions. */
901
- getAllSessions(): readonly RendererSession[];
1017
+ interface ModuleAuthoringApi<TModuleId extends ModuleRegistryId> {
1018
+ readonly moduleId: TModuleId;
1019
+ readonly api: ModuleApiRegistry[TModuleId];
1020
+ readonly signals: TypedSignalBus;
1021
+ readonly jobs: TypedJobRegistry<JobIdFor<TModuleId>>;
1022
+ readonly modules: ModuleRegistry;
1023
+ readonly windows: WindowManager;
1024
+ readonly views: ViewManager;
1025
+ readonly logger: ElectroLogger;
902
1026
  }
903
- //#endregion
904
- //#region src/desktop/view-manager.d.ts
905
1027
  /**
906
- * Framework-internal registry that tracks all `@View()` providers in the application.
1028
+ * Base type augmented onto `@Window()` classes by codegen.
907
1029
  *
908
- * Handles registration (including injecting the source URL into the base class)
909
- * and provides lookup by view ID. Consumers typically interact with views through
910
- * their {@link ViewProvider} subclass rather than this manager directly.
1030
+ * Provides typed window management capabilities when extended by codegen-generated
1031
+ * interface augmentations.
1032
+ */
1033
+ interface WindowAuthoringApi extends WindowAuthoringSurface {
1034
+ readonly logger: ElectroLogger;
1035
+ }
1036
+ /**
1037
+ * Base type augmented onto `@View()` classes by codegen.
911
1038
  *
912
- * @internal
1039
+ * Provides typed view management capabilities when extended by codegen-generated
1040
+ * interface augmentations.
913
1041
  */
914
- declare class ViewManager {
915
- private readonly views;
916
- /**
917
- * Register a view provider and apply its `@View()` source URL.
918
- *
919
- * @remarks Silently skips providers that do not have view metadata.
920
- */
921
- register(providerRef: ProviderRef): void;
922
- /** Look up a registered view provider by its view ID. */
923
- get(viewId: string): ProviderRef | undefined;
924
- /** Return all registered view providers. */
925
- list(): readonly ProviderRef[];
926
- /** Clear the registry. Does not destroy any underlying web contents. */
927
- dispose(): Promise<void>;
1042
+ interface ViewAuthoringApi extends ViewAuthoringSurface {
1043
+ readonly logger: ElectroLogger;
928
1044
  }
929
1045
  //#endregion
930
- //#region src/desktop/view-provider.d.ts
931
- declare const VIEW_STATE: unique symbol;
932
- interface ViewAuthoringSurface {
933
- readonly contentView: WebContentsView | undefined;
934
- readonly webContents: WebContents | undefined;
935
- load(): Promise<void>;
936
- setBounds(bounds: Rectangle): void;
937
- setBackgroundColor(color: string): void;
938
- focus(): void;
939
- setWindowButtonVisibility(visible: boolean): void;
940
- }
1046
+ //#region src/container/inject.d.ts
941
1047
  /**
942
- * Abstract base class for view providers decorated with `@View()`.
1048
+ * Resolve a dependency from the current injection context.
943
1049
  *
944
- * Extend this class to define a renderable view in your application. The framework
945
- * injects the source URL from the `@View()` decorator, and your subclass gains access
946
- * to methods for loading content, positioning, and styling.
1050
+ * This is the primary way framework-managed classes obtain their dependencies.
1051
+ * It reads the active {@link Injector} from `AsyncLocalStorage` and delegates to
1052
+ * {@link Injector.get}.
947
1053
  *
948
- * Views are created with strict security defaults: `sandbox: true`,
949
- * `contextIsolation: true`, and `nodeIntegration: false`.
1054
+ * @remarks
1055
+ * `inject()` is only available inside a framework-managed execution scope:
1056
+ * - **Construction** -- property initializers of `@Injectable()`, `@Module()`, `@View()`, or `@Window()` classes
1057
+ * - **Lifecycle hooks** -- `onInit`, `onStart`, `onReady`, `onShutdown`, `onDispose`
1058
+ * - **Capability handlers** -- methods decorated with `@command`, `@query`, `@signal`, or `@job`
950
1059
  *
951
- * @remarks The `WebContentsView` is lazily created on the first call to {@link load}.
1060
+ * Calling it anywhere else (e.g. in a `setTimeout` callback or a plain function)
1061
+ * throws {@link DIError} with code `ELECTRO_DI_NO_INJECTION_CONTEXT`.
952
1062
  *
953
1063
  * @example
954
1064
  * ```ts
955
- * @View({ source: 'view:main', access: ['app:getVersion'] })
956
- * class MainView extends ViewProvider {
957
- * async onStart() {
958
- * await this.load();
959
- * this.setBounds({ x: 0, y: 0, width: 800, height: 600 });
960
- * }
1065
+ * @Injectable()
1066
+ * class MyService {
1067
+ * private readonly config = inject(AppConfig);
961
1068
  * }
962
1069
  * ```
1070
+ *
1071
+ * @throws {@link DIError} if no injection context is active or the token cannot be resolved.
963
1072
  */
964
- declare abstract class ViewProvider {
965
- private [VIEW_STATE];
966
- /** The underlying Electron `WebContentsView`, or `undefined` if not yet created. */
967
- get contentView(): WebContentsView | undefined;
968
- /** The `WebContents` associated with this view, or `undefined` if not yet created. */
969
- get webContents(): WebContents | undefined;
970
- /**
971
- * Create the underlying `WebContentsView` (if needed) and load the configured source URL.
972
- *
973
- * The view is lazily created on the first call. Subsequent calls reload the source.
974
- * If the previous view was destroyed (e.g. parent window closed), a new one is created.
975
- * No-ops if no source URL has been configured.
976
- */
977
- load(): Promise<void>;
978
- /** Set the position and size of this view within its parent window. */
979
- setBounds(bounds: Rectangle): void;
980
- /** Set the background color of the view (e.g. `"#ffffff"` or `"transparent"`). */
981
- setBackgroundColor(color: string): void;
982
- /** Give keyboard focus to this view's web contents. */
983
- focus(): void;
984
- /** Show or hide the native window traffic-light buttons for this view (macOS). */
985
- setWindowButtonVisibility(visible: boolean): void;
986
- private createView;
987
- private static resolveSource;
988
- /** @internal Called by the framework to set the view source from @View metadata. */
989
- static __setSource(instance: ViewProvider, source: string): void;
990
- /** @internal Called by the framework to set web preferences from @View metadata. */
991
- static __setWebPreferences(instance: ViewProvider, webPreferences: WebPreferences): void;
992
- }
1073
+ declare function inject<T>(token: InjectionToken<T>): T extends SignalBus ? TypedSignalBus : T;
993
1074
  //#endregion
994
- //#region src/desktop/window-manager.d.ts
1075
+ //#region src/container/injection-context.d.ts
995
1076
  /**
996
- * Framework-internal registry that tracks all `@Window()` providers in the application.
1077
+ * Ambient injection context backed by `AsyncLocalStorage`.
997
1078
  *
998
- * Handles registration (including injecting `@Window()` configuration into the base class)
999
- * and provides lookup by window ID. Consumers typically interact with windows through
1000
- * their {@link WindowProvider} subclass rather than this manager directly.
1079
+ * The framework uses `InjectionContext` to make the current {@link Injector} available
1080
+ * to {@link inject} calls without requiring explicit injector references. It is set
1081
+ * automatically during provider construction, lifecycle hooks, and capability handlers.
1082
+ *
1083
+ * @remarks
1084
+ * This is a framework-internal API. Application code should use {@link inject} instead
1085
+ * of interacting with `InjectionContext` directly.
1001
1086
  *
1002
1087
  * @internal
1003
1088
  */
1004
- declare class WindowManager {
1005
- private readonly windows;
1089
+ declare const InjectionContext: {
1006
1090
  /**
1007
- * Register a window provider and apply its `@Window()` configuration.
1008
- *
1009
- * @remarks Silently skips providers that do not have window metadata.
1091
+ * Execute `fn` within the scope of the given injector.
1092
+ * Any {@link inject} call made synchronously inside `fn` will resolve from this injector.
1010
1093
  */
1011
- register(providerRef: ProviderRef): void;
1012
- /** Look up a registered window provider by its window ID. */
1013
- get(windowId: string): ProviderRef | undefined;
1014
- /** Return all registered window providers. */
1015
- list(): readonly ProviderRef[];
1016
- /** Close all managed windows and clear the registry. */
1017
- dispose(): Promise<void>;
1018
- }
1094
+ readonly run: <T>(injector: Injector, fn: () => T) => T;
1095
+ /**
1096
+ * Execute `fn` within the scope of the given injector, additionally tracking `owner`
1097
+ * as the object currently being constructed or invoked.
1098
+ */
1099
+ readonly runOwned: <T>(injector: Injector, owner: object, fn: () => T) => T; /** Return the injector for the current execution context, or `undefined` if none is active. */
1100
+ readonly current: () => Injector | undefined; /** Return the owner object of the current execution context, or `undefined` if not set. */
1101
+ readonly currentOwner: () => object | undefined; /** Whether a framework-managed injection context is currently active. */
1102
+ readonly isActive: () => boolean;
1103
+ };
1019
1104
  //#endregion
1020
- //#region src/desktop/window-provider.d.ts
1021
- declare const WINDOW_STATE: unique symbol;
1022
- interface WindowAuthoringSurface {
1023
- readonly window: BaseWindow | undefined;
1024
- create(): void;
1025
- mount(view: Pick<ViewProvider, "contentView">): void;
1026
- show(): void;
1027
- hide(): void;
1028
- focus(): void;
1029
- close(): void;
1030
- getBounds(): Rectangle | undefined;
1031
- }
1105
+ //#region src/modules/validator.d.ts
1032
1106
  /**
1033
- * Abstract base class for window providers decorated with `@Window()`.
1107
+ * Validates a scanned {@link AppDefinition} for structural correctness before bootstrap.
1034
1108
  *
1035
- * Extend this class to define a window in your application. The framework injects
1036
- * configuration from the `@Window()` decorator metadata, and your subclass gains
1037
- * access to lifecycle methods like {@link create}, {@link show}, {@link mount}, and {@link close}.
1109
+ * Checks performed:
1110
+ * - Unique module IDs
1111
+ * - Exports reference declared providers
1112
+ * - No cyclic module imports
1113
+ * - Unique view/window IDs
1114
+ * - Unique bridge channel names
1115
+ * - Unique job IDs
1116
+ * - Provider role exclusivity (a class cannot be both a view and a window)
1117
+ * - View access references point to existing bridge channels
1038
1118
  *
1039
- * @remarks The native `BaseWindow` instance is only available after calling {@link create}.
1040
- * Calling lifecycle methods before `create()` is safe (they no-op) but the window
1041
- * will not exist on screen.
1119
+ * @throws {BootstrapError} On the first validation failure encountered.
1120
+ */
1121
+ declare function validateAppDefinition(definition: AppDefinition): void;
1122
+ //#endregion
1123
+ //#region src/desktop/renderer-session.d.ts
1124
+ /**
1125
+ * Tracks the capabilities of a single renderer process (identified by `webContentsId`).
1042
1126
  *
1043
- * @example
1044
- * ```ts
1045
- * @Window({ width: 800, height: 600, show: false })
1046
- * class MainWindow extends WindowProvider {
1047
- * async onStart() {
1048
- * this.create();
1049
- * this.mount(this.mainView);
1050
- * this.show();
1051
- * }
1052
- * }
1053
- * ```
1127
+ * Each session records which bridge channels the renderer may invoke and which signals
1128
+ * it is allowed to receive, as declared in the `@View()` decorator metadata. The
1129
+ * {@link BridgeAccessGuard} and signal relay use this information to enforce per-view
1130
+ * access control.
1131
+ *
1132
+ * @internal Created and managed by {@link RendererRegistry}.
1054
1133
  */
1055
- declare abstract class WindowProvider {
1056
- private [WINDOW_STATE];
1057
- /** The underlying Electron `BaseWindow` instance, or `undefined` if not yet created. */
1058
- get window(): BaseWindow | undefined;
1059
- /** Create the native `BaseWindow` using configuration from the `@Window()` decorator. */
1060
- create(): void;
1134
+ declare class RendererSession {
1135
+ /** The Electron `webContents.id` that uniquely identifies this renderer process. */
1136
+ readonly rendererId: number;
1137
+ /** The view ID this renderer is associated with. */
1138
+ readonly viewId: string;
1139
+ /** Set of bridge channel names this renderer is allowed to invoke. */
1140
+ readonly access: ReadonlySet<string>;
1141
+ /** Set of signal IDs this renderer is allowed to receive. */
1142
+ readonly allowedSignals: ReadonlySet<string>;
1143
+ constructor(/** The Electron `webContents.id` that uniquely identifies this renderer process. */
1144
+
1145
+ rendererId: number, viewDef: ViewDefinition);
1146
+ /** Check whether this renderer has access to the given bridge channel. */
1147
+ hasAccess(channel: string): boolean;
1148
+ /** Check whether this renderer is allowed to receive the given signal. */
1149
+ canReceiveSignal(signalId: string): boolean;
1150
+ }
1151
+ //#endregion
1152
+ //#region src/desktop/renderer-registry.d.ts
1153
+ /**
1154
+ * Maps Electron `webContentsId` values to {@link RendererSession} instances.
1155
+ *
1156
+ * Used by the bridge layer to look up which renderer process is making an IPC request
1157
+ * and determine what channels and signals it is allowed to access. View definitions are
1158
+ * registered at bootstrap time; sessions are created lazily when a renderer first
1159
+ * communicates.
1160
+ *
1161
+ * @internal
1162
+ */
1163
+ declare class RendererRegistry {
1164
+ private readonly sessions;
1165
+ private readonly viewDefinitions;
1166
+ /** Store a view definition so that sessions can be created for it later. */
1167
+ registerView(viewDef: ViewDefinition): void;
1061
1168
  /**
1062
- * Attach a view's content to this window.
1169
+ * Return the existing session for a `webContentsId`, or create one if this is
1170
+ * the first request from that renderer.
1063
1171
  *
1064
- * The view's `WebContentsView` is added as a child view of the window's content area.
1065
- * No-ops silently if the window or view has not been created yet.
1172
+ * @throws {BridgeError} If the `viewId` does not match any registered view definition.
1066
1173
  */
1067
- mount(view: ViewProvider): void;
1068
- /** Show the window. No-ops if the window has not been created. */
1069
- show(): void;
1070
- /** Hide the window without destroying it. */
1071
- hide(): void;
1072
- /** Bring the window to the front and give it focus. */
1073
- focus(): void;
1074
- /** Close and destroy the native window, releasing its resources. */
1075
- close(): void;
1076
- /** Return the window's current screen bounds, or `undefined` if not created. */
1077
- getBounds(): Rectangle | undefined;
1078
- /** @internal Called by the framework to set the window configuration from @Window metadata. */
1079
- static __setConfiguration(instance: WindowProvider, configuration?: BaseWindowConstructorOptions): void;
1174
+ getOrCreateSession(webContentsId: number, viewId: string): RendererSession;
1175
+ /** Look up an existing session by its `webContentsId`, or `undefined` if none exists. */
1176
+ getSession(webContentsId: number): RendererSession | undefined;
1177
+ /** Remove a session when its renderer process is destroyed. */
1178
+ removeSession(webContentsId: number): void;
1179
+ /** Return all active renderer sessions. */
1180
+ getAllSessions(): readonly RendererSession[];
1080
1181
  }
1081
1182
  //#endregion
1082
1183
  //#region src/bridge/access-guard.d.ts
@@ -1397,103 +1498,4 @@ declare class SignalError extends RuntimeError {
1397
1498
  static invalidSignalId(signalId: unknown): SignalError;
1398
1499
  }
1399
1500
  //#endregion
1400
- //#region src/contracts/authoring.d.ts
1401
- /**
1402
- * Codegen contract types for `@electrojs/runtime`.
1403
- *
1404
- * These interfaces and types are used by `@electrojs/codegen` to generate
1405
- * type-safe authoring APIs. The codegen augments the empty registry interfaces
1406
- * via `declare module "@electro"` to populate them with app-specific types.
1407
- *
1408
- * @module contracts/authoring
1409
- */
1410
- /** Maps `"moduleId:methodId"` to the method's type reference. Augmented by codegen. */
1411
- interface ModuleMethodMap {}
1412
- /** Maps module IDs to their method type objects. Augmented by codegen. */
1413
- interface ModuleApiRegistry {}
1414
- /** Maps signal keys to their payload types. Augmented by codegen. */
1415
- interface ModuleSignalPayloadMap {}
1416
- /** Maps module IDs to their job ID unions. Augmented by codegen. */
1417
- interface ModuleJobRegistry {}
1418
- /** Maps injectable class names to their class types. Augmented by codegen. */
1419
- interface InjectableClassRegistry {}
1420
- /** Maps window IDs to their `@Window()` class types. Augmented by codegen. */
1421
- interface WindowClassRegistry {}
1422
- /** Maps view IDs to their `@View()` class types. Augmented by codegen. */
1423
- interface ViewClassRegistry {}
1424
- /** Union of all registered module IDs. Derived from `ModuleApiRegistry` keys. */
1425
- type ModuleRegistryId = keyof ModuleApiRegistry;
1426
- type JobIdFor<TModuleId extends ModuleRegistryId> = Extract<ModuleJobRegistry[TModuleId], string>;
1427
- type SignalId = Extract<keyof ModuleSignalPayloadMap, string>;
1428
- type VoidSignalId = { [TKey in SignalId]: ModuleSignalPayloadMap[TKey] extends void ? TKey : never }[SignalId];
1429
- type NonVoidSignalId = Exclude<SignalId, VoidSignalId>;
1430
- /** A class decorated with `@Module()`. Used in generated registry arrays. */
1431
- type ModuleClass = Constructor;
1432
- /** A class decorated with `@View()`. Used in generated registry arrays. */
1433
- type ViewClass = Constructor;
1434
- /** A class decorated with `@Window()`. Used in generated registry arrays. */
1435
- type WindowClass = Constructor;
1436
- /**
1437
- * Shape of the static kernel definition object generated by codegen.
1438
- *
1439
- * Used by the generated `electroAppDefinition` constant which can be
1440
- * passed to `AppKernel.create()` for fully typed bootstrapping.
1441
- */
1442
- interface AppKernelDefinition {
1443
- readonly root: Constructor;
1444
- readonly modules: readonly Constructor[];
1445
- readonly windows: readonly Constructor[];
1446
- readonly views: readonly Constructor[];
1447
- }
1448
- interface TypedSignalBus {
1449
- publish<TSignalId extends VoidSignalId>(signalId: TSignalId): void;
1450
- publish<TSignalId extends NonVoidSignalId>(signalId: TSignalId, payload: ModuleSignalPayloadMap[TSignalId]): void;
1451
- subscribe<TSignalId extends SignalId>(signalId: TSignalId, handler: SignalHandler<ModuleSignalPayloadMap[TSignalId]>): () => void;
1452
- }
1453
- interface TypedJobRegistry<TJobId extends string = string> {
1454
- ensure(jobId: TJobId): void;
1455
- start(jobId: TJobId): void;
1456
- run(jobId: TJobId, ...args: unknown[]): Promise<unknown>;
1457
- stop(jobId: TJobId): Promise<void>;
1458
- cancel(jobId: TJobId): void;
1459
- getStatus(jobId: TJobId): JobRuntimeState | undefined;
1460
- list(): readonly JobRuntimeState[];
1461
- }
1462
- /**
1463
- * Base type augmented onto module and provider classes by codegen.
1464
- *
1465
- * Codegen generates `interface MyModule extends ModuleAuthoringApi<"myModuleId"> {}`
1466
- * which gives the class access to typed methods based on the module's registered
1467
- * commands, queries, signals, and jobs.
1468
- *
1469
- */
1470
- interface ModuleAuthoringApi<TModuleId extends ModuleRegistryId> {
1471
- readonly moduleId: TModuleId;
1472
- readonly api: ModuleApiRegistry[TModuleId];
1473
- readonly signals: TypedSignalBus;
1474
- readonly jobs: TypedJobRegistry<JobIdFor<TModuleId>>;
1475
- readonly modules: ModuleRegistry;
1476
- readonly windows: WindowManager;
1477
- readonly views: ViewManager;
1478
- readonly logger: ElectroLogger;
1479
- }
1480
- /**
1481
- * Base type augmented onto `@Window()` classes by codegen.
1482
- *
1483
- * Provides typed window management capabilities when extended by codegen-generated
1484
- * interface augmentations.
1485
- */
1486
- interface WindowAuthoringApi extends WindowAuthoringSurface {
1487
- readonly logger: ElectroLogger;
1488
- }
1489
- /**
1490
- * Base type augmented onto `@View()` classes by codegen.
1491
- *
1492
- * Provides typed view management capabilities when extended by codegen-generated
1493
- * interface augmentations.
1494
- */
1495
- interface ViewAuthoringApi extends ViewAuthoringSurface {
1496
- readonly logger: ElectroLogger;
1497
- }
1498
- //#endregion
1499
1501
  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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electrojs/runtime",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Electron main-process runtime for ElectroJS with DI, lifecycle hooks, typed IPC, and jobs",
5
5
  "keywords": [
6
6
  "dependency-injection",
@@ -49,12 +49,12 @@
49
49
  "publint": "^0.3.18",
50
50
  "tsdown": "^0.21.4",
51
51
  "vitest": "^4.1.1",
52
- "@electrojs/common": "1.0.8",
53
- "@electrojs/config": "1.0.8"
52
+ "@electrojs/common": "1.0.9",
53
+ "@electrojs/config": "1.0.9"
54
54
  },
55
55
  "peerDependencies": {
56
- "@electrojs/common": "1.0.8",
57
- "@electrojs/config": "1.0.8",
56
+ "@electrojs/common": "1.0.9",
57
+ "@electrojs/config": "1.0.9",
58
58
  "@types/node": "^25.5.0",
59
59
  "electron": ">=41"
60
60
  },