@electrojs/runtime 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,10 +43,11 @@ class AppModule {}
43
43
  const kernel = AppKernel.create(AppModule, {
44
44
  logger: createConsoleLogger(),
45
45
  });
46
+ await kernel.initialize();
46
47
  await kernel.start();
47
48
  ```
48
49
 
49
- `AppKernel.create` scans `AppModule`, validates the module graph, creates the DI container, instantiates module declarations, and runs startup lifecycle hooks. That single call is enough to bootstrap a working application.
50
+ `AppKernel.initialize()` scans `AppModule`, validates the module graph, creates the DI container, instantiates module declarations, installs capabilities, and runs `onInit`. `kernel.start()` then runs `onStart` and `onReady`. Calling `start()` directly from `idle` still performs initialization automatically for backward compatibility.
50
51
 
51
52
  Modules, providers, windows, and views also receive `this.logger` through the authoring API, so app-level logs can use the same runtime logger contract and be redirected to a file, Sentry, or any other sink by passing a custom logger into `AppKernel.create(...)`.
52
53
 
@@ -101,7 +102,7 @@ class AuthService {
101
102
  `inject()` works inside:
102
103
 
103
104
  - **Property initializers** -- during construction of framework-managed classes
104
- - **Lifecycle hooks** -- `onInit`, `onReady`, `onShutdown`, `onDispose`
105
+ - **Lifecycle hooks** -- `onInit`, `onStart`, `onReady`, `onShutdown`, `onDispose`
105
106
  - **Capability handlers** -- methods decorated with `@command`, `@query`, `@signal`, `@job`
106
107
 
107
108
  Calling it outside these scopes throws a `DIError`.
@@ -129,6 +130,10 @@ class DatabaseService {
129
130
  await this.pool.connect();
130
131
  }
131
132
 
133
+ async onStart() {
134
+ await this.attachWindowListeners();
135
+ }
136
+
132
137
  async onReady() {
133
138
  await this.runMigrations();
134
139
  }
@@ -143,14 +148,15 @@ class DatabaseService {
143
148
  }
144
149
  ```
145
150
 
146
- | Hook | Phase | Purpose |
147
- | ------------ | -------- | ---------------------------------------------------- |
148
- | `onInit` | Startup | Set up resources (connections, state) |
149
- | `onReady` | Startup | Cross-module coordination, everything is initialized |
150
- | `onShutdown` | Shutdown | Release resources gracefully |
151
- | `onDispose` | Shutdown | Final cleanup (file handles, timers) |
151
+ | Hook | Phase | Purpose |
152
+ | ------------ | ---------- | ------------------------------------------------------------- |
153
+ | `onInit` | Initialize | Prepare bridge-safe state, handlers, and runtime dependencies |
154
+ | `onStart` | Startup | Start windows, jobs, network bootstrapping, launch flows |
155
+ | `onReady` | Startup | Final coordination before the kernel becomes `started` |
156
+ | `onShutdown` | Shutdown | Release resources gracefully |
157
+ | `onDispose` | Shutdown | Final cleanup (file handles, timers) |
152
158
 
153
- **Ordering:** Startup hooks run per-module in dependency-first order. Within each module, provider hooks run before the module's own hook. Shutdown runs in the reverse order -- module first, then its providers.
159
+ **Ordering:** `onInit`, `onStart`, and `onReady` all run per-module in dependency-first order. Within each module, provider hooks run before the module's own hook. Shutdown runs in the reverse order -- module first, then its providers.
154
160
 
155
161
  If a startup hook throws, the framework automatically rolls back already-initialized modules by calling their shutdown hooks.
156
162
 
@@ -284,7 +290,7 @@ Windows and views are first-class providers. Extend the base classes `WindowProv
284
290
  class MainWindow extends WindowProvider {
285
291
  private readonly mainView = inject(MainView);
286
292
 
287
- onReady() {
293
+ onStart() {
288
294
  this.create();
289
295
  this.mount(this.mainView);
290
296
  this.show();
@@ -303,7 +309,7 @@ class MainWindow extends WindowProvider {
303
309
  signals: ["user-logged-in"],
304
310
  })
305
311
  class MainView extends ViewProvider {
306
- async onReady() {
312
+ async onStart() {
307
313
  await this.load();
308
314
  this.setBounds({ x: 0, y: 0, width: 1280, height: 800 });
309
315
  this.setBackgroundColor("#00000000");
package/dist/index.d.mts CHANGED
@@ -252,6 +252,7 @@ declare function scanModules(rootModule: Constructor): AppDefinition;
252
252
  * @Injectable()
253
253
  * class DatabaseService implements LifecycleTarget {
254
254
  * async onInit() { await this.connect(); }
255
+ * async onStart() { await this.startReplication(); }
255
256
  * async onShutdown() { await this.disconnect(); }
256
257
  * }
257
258
  * ```
@@ -263,7 +264,9 @@ declare function scanModules(rootModule: Constructor): AppDefinition;
263
264
  interface LifecycleTarget {
264
265
  /** Called during initialization phase. Use for setting up connections, state, etc. */
265
266
  onInit?(): void | Promise<void>;
266
- /** Called after all modules have been initialized. Use for cross-module coordination. */
267
+ /** Called after the Electron app is ready. Use for startup side effects such as windows, jobs, and launch flows. */
268
+ onStart?(): void | Promise<void>;
269
+ /** Called after startup work completes. Use for final coordination before the kernel becomes `started`. */
267
270
  onReady?(): void | Promise<void>;
268
271
  /** Called during graceful shutdown. Use for releasing resources, closing connections. */
269
272
  onShutdown?(): void | Promise<void>;
@@ -274,6 +277,8 @@ interface LifecycleTarget {
274
277
  * Represents the current phase of a module's lifecycle.
275
278
  *
276
279
  * Transitions follow a strict state machine: creating -> ready -> started -> stopping -> stopped.
280
+ * Modules may also transition directly from `ready` to `stopped` if the kernel is
281
+ * shut down after initialization but before startup completes.
277
282
  * Any state can also transition to "failed".
278
283
  */
279
284
  type ModuleStatus = "creating" | "ready" | "started" | "stopping" | "stopped" | "failed";
@@ -386,6 +391,7 @@ interface AppKernelOptions {
386
391
  * @example
387
392
  * ```ts
388
393
  * const kernel = AppKernel.create(AppModule);
394
+ * await kernel.initialize();
389
395
  * await kernel.start();
390
396
  *
391
397
  * // ... app is running ...
@@ -394,10 +400,10 @@ interface AppKernelOptions {
394
400
  * ```
395
401
  *
396
402
  * @remarks
397
- * - Calling {@link start} when already started is a no-op.
398
- * - If startup fails, the kernel automatically rolls back initialized modules and
403
+ * - Calling {@link initialize} when already initialized is a no-op.
404
+ * - Calling {@link start} from `idle` first performs {@link initialize} for backward compatibility.
405
+ * - If initialization or startup fails, the kernel automatically rolls back initialized modules and
399
406
  * transitions to `failed`.
400
- * - {@link shutdown} can only be called from the `started` state.
401
407
  */
402
408
  declare class AppKernel {
403
409
  private state;
@@ -407,44 +413,60 @@ declare class AppKernel {
407
413
  private readonly logger;
408
414
  private readonly stateListeners;
409
415
  private readonly disposers;
416
+ private initializeTask?;
417
+ private startTask?;
418
+ private shutdownTask?;
410
419
  private constructor();
411
420
  /**
412
421
  * 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.
422
+ * The kernel starts in the `idle` state -- call {@link initialize} and/or {@link start} to bootstrap the application.
414
423
  */
415
424
  static create(rootModule: Constructor, options?: AppKernelOptions): AppKernel;
416
425
  /**
417
- * Bootstraps and starts the application.
426
+ * Builds the application graph and runs the initialization lifecycle.
418
427
  *
419
428
  * 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`.
429
+ * capability installation, and runs `onInit`.
422
430
  *
423
- * @remarks No-op if already started. Must be called from `idle` state.
431
+ * @remarks Safe to call before `app.whenReady()`. No-op if already initialized or started.
424
432
  * @throws {BootstrapError} On invalid module graph or decorator metadata.
425
433
  * @throws {LifecycleError} On lifecycle hook failure.
426
434
  */
435
+ initialize(): Promise<void>;
436
+ /**
437
+ * Starts the application after initialization.
438
+ *
439
+ * Runs `onStart` and `onReady` lifecycle hooks. Bridge calls from renderer processes
440
+ * become available at the beginning of the `starting` phase.
441
+ *
442
+ * @remarks No-op if already started. Calling from `idle` first performs {@link initialize}.
443
+ * @throws {LifecycleError} On lifecycle hook failure.
444
+ */
427
445
  start(): Promise<void>;
428
446
  /**
429
447
  * Gracefully shuts down the application.
430
448
  *
431
- * Runs `onShutdown` / `onDispose` lifecycle hooks in reverse module order,
432
- * then disposes framework services (jobs, windows, views).
449
+ * Runs `onShutdown` / `onDispose` for started kernels, or only `onDispose` if the
450
+ * kernel was initialized but never started.
433
451
  *
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.
452
+ * @remarks No-op if `idle`, `stopped`, or already `failed`.
453
+ * @throws {LifecycleError} If shutdown is requested while startup is still in progress.
436
454
  */
437
455
  shutdown(): Promise<void>;
438
456
  /** Returns the current kernel lifecycle state. */
439
457
  getState(): KernelState;
440
458
  /** Convenience check: returns `true` only when the kernel is in the `started` state. */
441
459
  isStarted(): boolean;
442
- /** Returns the scanned app definition, or `undefined` if the kernel has not been started yet. */
460
+ /** Returns the scanned app definition, or `undefined` if the kernel has not been initialized yet. */
443
461
  getDefinition(): AppDefinition | undefined;
444
- /** Returns the live module references, or an empty array if the kernel has not been started yet. */
462
+ /** Returns the live module references, or an empty array if the kernel has not been initialized yet. */
445
463
  getModuleRefs(): readonly ModuleRef[];
446
464
  /** @internal Hook for subsystems that need to react to kernel state changes. */
447
465
  onStateChange(callback: (state: KernelState) => void): void;
466
+ private performInitialize;
467
+ private performStart;
468
+ private performShutdown;
469
+ private getPreviousRunningState;
448
470
  private registerFrameworkServices;
449
471
  private disposeServices;
450
472
  private transitionTo;
@@ -462,7 +484,7 @@ declare class AppKernel {
462
484
  * @remarks
463
485
  * `inject()` is only available inside a framework-managed execution scope:
464
486
  * - **Construction** -- property initializers of `@Injectable()`, `@Module()`, `@View()`, or `@Window()` classes
465
- * - **Lifecycle hooks** -- `onInit`, `onReady`, `onShutdown`, `onDispose`
487
+ * - **Lifecycle hooks** -- `onInit`, `onStart`, `onReady`, `onShutdown`, `onDispose`
466
488
  * - **Capability handlers** -- methods decorated with `@command`, `@query`, `@signal`, or `@job`
467
489
  *
468
490
  * Calling it anywhere else (e.g. in a `setTimeout` callback or a plain function)
@@ -932,7 +954,7 @@ interface ViewAuthoringSurface {
932
954
  * ```ts
933
955
  * @View({ source: 'view:main', access: ['app:getVersion'] })
934
956
  * class MainView extends ViewProvider {
935
- * async onReady() {
957
+ * async onStart() {
936
958
  * await this.load();
937
959
  * this.setBounds({ x: 0, y: 0, width: 800, height: 600 });
938
960
  * }
@@ -1022,7 +1044,7 @@ interface WindowAuthoringSurface {
1022
1044
  * ```ts
1023
1045
  * @Window({ width: 800, height: 600, show: false })
1024
1046
  * class MainWindow extends WindowProvider {
1025
- * async onReady() {
1047
+ * async onStart() {
1026
1048
  * this.create();
1027
1049
  * this.mount(this.mainView);
1028
1050
  * this.show();
@@ -1062,7 +1084,7 @@ declare abstract class WindowProvider {
1062
1084
  * Enforces access control for bridge IPC calls.
1063
1085
  *
1064
1086
  * Checks two conditions before a bridge request is allowed through:
1065
- * 1. The application kernel must be in the `"started"` state.
1087
+ * 1. The application kernel must be in the `"starting"` or `"started"` state.
1066
1088
  * 2. The requesting renderer's {@link RendererSession} must have the target channel
1067
1089
  * in its access set (as declared in `@View({ access: [...] })`).
1068
1090
  *
@@ -1073,7 +1095,7 @@ declare class BridgeAccessGuard {
1073
1095
  /** Update the tracked kernel state. Called by the kernel during lifecycle transitions. */
1074
1096
  setKernelState(state: KernelState): void;
1075
1097
  /**
1076
- * Assert that the kernel is in the `"started"` state.
1098
+ * Assert that the kernel is in a state where bridge calls are allowed.
1077
1099
  *
1078
1100
  * @throws {BridgeError} If the kernel is not ready to handle requests.
1079
1101
  */
@@ -1147,7 +1169,8 @@ interface BridgeResponse {
1147
1169
  /**
1148
1170
  * Routes IPC requests from renderer processes to the appropriate {@link BridgeHandler}.
1149
1171
  *
1150
- * For each incoming request the dispatcher verifies that the kernel is ready,
1172
+ * For each incoming request the dispatcher verifies that the kernel currently
1173
+ * accepts bridge calls,
1151
1174
  * that the requesting renderer has an active session, and that the session grants
1152
1175
  * access to the requested channel. If all checks pass the corresponding handler
1153
1176
  * is invoked; otherwise a serialized error is returned. Errors never propagate as
@@ -1165,7 +1188,7 @@ declare class BridgeDispatcher {
1165
1188
  /**
1166
1189
  * Process an IPC request from a renderer identified by its `webContentsId`.
1167
1190
  *
1168
- * Performs kernel-readiness, session-existence, and channel-access checks before
1191
+ * Performs kernel bridge-readiness, session-existence, and channel-access checks before
1169
1192
  * delegating to the registered handler. All errors are caught and returned as
1170
1193
  * serialized error objects in the response.
1171
1194
  */
@@ -1278,7 +1301,7 @@ declare class BridgeError extends RuntimeError {
1278
1301
  * The original error is attached as {@link Error.cause}.
1279
1302
  */
1280
1303
  static handlerFailed(channel: string, cause: unknown): BridgeError;
1281
- /** A bridge call arrived before the kernel finished starting or after it began shutting down. */
1304
+ /** A bridge call arrived before startup entered the `starting` phase or after shutdown began. */
1282
1305
  static kernelNotReady(): BridgeError;
1283
1306
  /** A bridge request came from a `webContents` that is not associated with any known view. */
1284
1307
  static unknownRenderer(webContentsId: number): BridgeError;
@@ -1310,7 +1333,7 @@ declare class DIError extends RuntimeError {
1310
1333
  *
1311
1334
  * @remarks
1312
1335
  * `inject()` is only available during construction (property initializers),
1313
- * lifecycle hooks (`onInit`/`onReady`/`onShutdown`/`onDispose`),
1336
+ * lifecycle hooks (`onInit`/`onStart`/`onReady`/`onShutdown`/`onDispose`),
1314
1337
  * and capability handlers (`@command`, `@query`, `@signal`, `@job`).
1315
1338
  */
1316
1339
  static noInjectionContext(): DIError;
@@ -1346,7 +1369,7 @@ declare class JobError extends RuntimeError {
1346
1369
  declare class LifecycleError extends RuntimeError {
1347
1370
  private constructor();
1348
1371
  /**
1349
- * A lifecycle hook (`onInit`, `onReady`, etc.) threw during the startup sequence.
1372
+ * A lifecycle hook (`onInit`, `onStart`, `onReady`, etc.) threw during the startup sequence.
1350
1373
  *
1351
1374
  * @remarks
1352
1375
  * The original error is attached as {@link Error.cause}.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./client-CD3ueTol.mjs";import{createRequire as n}from"node:module";import{Cron as r}from"croner";import{AsyncLocalStorage as i}from"node:async_hooks";import{Ref as a,describeInjectionToken as o,getInjectableMetadata as s,getMethodsMetadataByClass as c,getModuleMetadata as l,getViewMetadata as u,getWindowMetadata as d,isClassProvider as f,isInjectionTokenSymbol as p}from"@electrojs/common";var m=n(import.meta.url),h=class extends Error{constructor(e,t,n){super(e),this.name=new.target.name,this.code=t,this.context=n,Object.setPrototypeOf(this,new.target.prototype)}},g=class e extends h{constructor(e,t,n){super(e,t,n)}static accessDenied(t,n){return new e(`View "${t}" does not have access to bridge channel "${n}".`,`ELECTRO_BRIDGE_ACCESS_DENIED`,{viewId:t,channel:n})}static routeNotFound(t){return new e(`No bridge handler registered for channel "${t}".`,`ELECTRO_BRIDGE_ROUTE_NOT_FOUND`,{channel:t})}static handlerFailed(t,n){let r=new e(`Bridge handler for channel "${t}" threw an error.`,`ELECTRO_BRIDGE_HANDLER_FAILED`,{channel:t});return r.cause=n,r}static kernelNotReady(){return new e(`Bridge invocation rejected — kernel is not in started state.`,`ELECTRO_BRIDGE_KERNEL_NOT_READY`)}static unknownRenderer(t){return new e(`Received bridge request from unregistered renderer (webContents id: ${t}).`,`ELECTRO_BRIDGE_UNKNOWN_RENDERER`,{webContentsId:t})}},_=class{constructor(){this.kernelState=`idle`}setKernelState(e){this.kernelState=e}assertKernelReady(){if(this.kernelState!==`started`)throw g.kernelNotReady()}assertAccess(e,t){if(!e.hasAccess(t))throw g.accessDenied(e.viewId,t)}};function v(e){return e instanceof Error?{message:e.message,code:e.code,context:e.context}:{message:String(e)}}var y=class{constructor(e,t){this.rendererRegistry=e,this.accessGuard=t,this.handlers=new Map}registerHandler(e){this.handlers.set(e.channel,e)}async dispatch(e,t){try{this.accessGuard.assertKernelReady();let n=this.rendererRegistry.getSession(e);if(!n)throw g.unknownRenderer(e);this.accessGuard.assertAccess(n,t.channel);let r=this.handlers.get(t.channel);if(!r)throw g.routeNotFound(t.channel);let i=await r.invoke(t.args);return{callId:t.callId,result:i}}catch(e){return{callId:t.callId,error:v(e)}}}},ee=class{constructor(e,t){this.rendererId=e,this.viewId=t.id,this.access=new Set(t.access),this.allowedSignals=new Set(t.signals)}hasAccess(e){return this.access.has(e)}canReceiveSignal(e){return this.allowedSignals.has(e)}},b=class{constructor(){this.sessions=new Map,this.viewDefinitions=new Map}registerView(e){this.viewDefinitions.set(e.id,e)}getOrCreateSession(e,t){let n=this.sessions.get(e);if(n)return n;let r=this.viewDefinitions.get(t);if(!r)throw g.unknownRenderer(e);let i=new ee(e,r);return this.sessions.set(e,i),i}getSession(e){return this.sessions.get(e)}removeSession(e){this.sessions.delete(e)}getAllSessions(){return[...this.sessions.values()]}};function te(e){return e.toTimeString().slice(0,8)}function ne(e){return e===`electro`?`electro`:e}function re(e,t){return e===`warn`||e===`error`?!0:t.ELECTRO_DEV===`true`}function ie(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:e}function ae(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0);if(t.length===0)return``;try{return` ${JSON.stringify(Object.fromEntries(t.map(([e,t])=>[e,ie(t)])))}`}catch{return` [unserializable context]`}}function oe(e,t,n,r=new Date){return`${te(r)} [${ne(e)}] ${t} → ${n}`}function x(e,t=`Electro`){if(typeof e==`string`&&e.trim().length>0)return e;let n=e.constructor?.name?.trim();return n&&n.length>0?n:t}var S=class e{constructor(e={},t=process.env){this.bindings=e,this.env=t}debug(e,t){this.write(`debug`,e,t)}info(e,t){this.write(`info`,e,t)}warn(e,t){this.write(`warn`,e,t)}error(e,t){this.write(`error`,e,t)}child(t){return new e({...this.bindings,...t},this.env)}write(e,t,n){if(!re(e,this.env))return;let r=x(this.bindings.target??`Electro`),i=oe(e===`warn`?`warn`:e===`error`?`error`:`electro`,r,`${t}${ae(n)}`);console.log(i)}};const se=new S;let C;function w(){return new S}function T(){return C??se}function E(e){C=e}function D(e,t,n=`electro`){let r=T().child({target:e});switch(n){case`warn`:r.warn(t);return;case`error`:r.error(t);return;default:r.info(t)}}function O(e,t,n=`electro`){D(x(e),t,n)}function k(e,t,n){T().child({target:x(e)}).error(t,{error:n})}const A=Symbol(`electro.view-state`),ce=[`load`,`setBounds`,`setBackgroundColor`,`focus`,`setWindowButtonVisibility`];function j(e){return e[A]||Object.defineProperty(e,A,{value:{},configurable:!1,enumerable:!1,writable:!0}),e[A]}function le(){return typeof __ELECTRO_VIEW_REGISTRY__>`u`?[]:__ELECTRO_VIEW_REGISTRY__}function ue(e){let t=e.slice(5).trim(),n=le().find(e=>e.id===t)?.source;if(!n)throw Error(`Bundled view source "${e}" could not be resolved. Start the app through the ElectroJS CLI so the view registry is injected.`);return n}function de(e){let t=e.slice(5).trim();return le().find(e=>e.id===t)}function fe(){return Object.getOwnPropertyDescriptor(M.prototype,`contentView`)}function pe(){return Object.getOwnPropertyDescriptor(M.prototype,`webContents`)}function me(e,t,n){let r=e,i=j(r);t!==void 0&&(i.source=t),n!==void 0&&(i.webPreferences=n);let a=fe();!(`contentView`in r)&&a?.get&&Object.defineProperty(r,`contentView`,{configurable:!0,enumerable:!1,get(){return a.get?.call(this)}});let o=pe();!(`webContents`in r)&&o?.get&&Object.defineProperty(r,`webContents`,{configurable:!0,enumerable:!1,get(){return o.get?.call(this)}});for(let e of ce)e in r||Object.defineProperty(r,e,{configurable:!0,enumerable:!1,writable:!0,value:M.prototype[e]})}var M=class e{constructor(){this[A]={}}get contentView(){return this[A].view}get webContents(){return this[A].view?.webContents}async load(){(!this[A].view||this[A].view.webContents.isDestroyed())&&(this[A].view=void 0,this.createView());let t=this[A].source;if(!t||!this[A].view)return;let n=e.resolveSource(t);O(this,`loaded ${n}`),await this[A].view.webContents.loadURL(n)}setBounds(e){this[A].view?.setBounds(e)}setBackgroundColor(e){this[A].view?.setBackgroundColor(e)}focus(){this[A].view?.webContents.focus()}setWindowButtonVisibility(e){this[A].view?.setWindowButtonVisibility?.(e)}createView(){let{WebContentsView:e}=m(`electron`),t=this[A].webPreferences??{},n=typeof this[A].source==`string`&&this[A].source.startsWith(`view:`)?de(this[A].source):void 0;this[A].view=new e({webPreferences:{...t,...n?.preload?{preload:n.preload}:{},sandbox:!0,contextIsolation:!0,nodeIntegration:!1}}),O(this,`created`)}static resolveSource(e){return e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`file:`)?e:e.startsWith(`view:`)?ue(e):e}static __setSource(e,t){j(e).source=t}static __setWebPreferences(e,t){j(e).webPreferences=t}},N=class{constructor(){this.views=new Map}register(e){let t=e.definition.view;t&&(this.views.set(t.id,e),me(e.instance,t.source,t.configuration?.webPreferences))}get(e){return this.views.get(e)}list(){return[...this.views.values()]}async dispose(){this.views.clear()}};const P=Symbol(`electro.window-state`),he=[`create`,`mount`,`show`,`hide`,`focus`,`close`,`getBounds`];function F(e){return e[P]||Object.defineProperty(e,P,{value:{},configurable:!1,enumerable:!1,writable:!0}),e[P]}function ge(){return Object.getOwnPropertyDescriptor(I.prototype,`window`)}function _e(e,t){let n=e,r=F(n);t!==void 0&&(r.configuration=t);let i=ge();!(`window`in n)&&i?.get&&Object.defineProperty(n,`window`,{configurable:!0,enumerable:!1,get(){return i.get?.call(this)}});for(let e of he)e in n||Object.defineProperty(n,e,{configurable:!0,enumerable:!1,writable:!0,value:I.prototype[e]})}var I=class{constructor(){this[P]={}}get window(){return this[P].window}create(){if(this[P].window)return;let{BaseWindow:e}=m(`electron`),t=new e(this[P].configuration??{});this[P].window=t,t.on(`closed`,()=>{this[P].window=void 0,O(this,`closed`)}),O(this,`created`)}mount(e){let t=this[P].window;if(!t)return;let n=e.contentView;n&&(t.contentView.addChildView(n),O(this,`mounted ${e.constructor.name||`ViewProvider`}`))}show(){let e=this[P].window;e&&(e.show(),O(this,`shown`))}hide(){this[P].window?.hide()}focus(){this[P].window?.focus()}close(){let e=this[P].window;e&&e.destroy()}getBounds(){return this[P].window?.getBounds()}static __setConfiguration(e,t){F(e).configuration=t}},L=class{constructor(){this.windows=new Map}register(e){let t=e.definition.window;t&&(this.windows.set(t.id,e),_e(e.instance,t.configuration))}get(e){return this.windows.get(e)}list(){return[...this.windows.values()]}async dispose(){for(let e of this.windows.values())(e.instance instanceof I||`close`in e.instance)&&e.instance.close();this.windows.clear()}},R=class e extends h{constructor(e,t,n){super(e,t,n)}static startupFailed(t,n,r){let i=new e(`Lifecycle hook "${t}" failed in "${n}".`,`ELECTRO_LIFECYCLE_STARTUP_FAILED`,{hookName:t,targetName:n});return i.cause=r,i}static invalidKernelTransition(t,n){return new e(`Invalid kernel state transition from "${t}" to "${n}".`,`ELECTRO_LIFECYCLE_INVALID_KERNEL_TRANSITION`,{from:t,to:n})}static invalidModuleTransition(t,n,r){return new e(`Invalid module state transition for "${t}": "${n}" → "${r}".`,`ELECTRO_LIFECYCLE_INVALID_MODULE_TRANSITION`,{moduleId:t,from:n,to:r})}static kernelNotStarted(){return new e(`Cannot shut down kernel — it has not been started.`,`ELECTRO_LIFECYCLE_NOT_STARTED`)}static kernelAlreadyStarted(){return new e(`Cannot start kernel — it is already started or starting.`,`ELECTRO_LIFECYCLE_ALREADY_STARTED`)}};const z=new i,B={run(e,t){return z.run({injector:e},t)},runOwned(e,t,n){return z.run({injector:e,owner:t},n)},current(){return z.getStore()?.injector},currentOwner(){return z.getStore()?.owner},isActive(){return z.getStore()!==void 0}};var V=class e extends h{constructor(e,t,n){super(e,t,n)}static notFound(t){return new e(`Job "${t}" is not registered.`,`ELECTRO_JOB_NOT_FOUND`,{jobId:t})}static alreadyRunning(t){return new e(`Job "${t}" is already running.`,`ELECTRO_JOB_ALREADY_RUNNING`,{jobId:t})}static executionFailed(t,n){let r=new e(`Job "${t}" execution failed.`,`ELECTRO_JOB_EXECUTION_FAILED`,{jobId:t});return r.cause=n,r}},ve=class{constructor(){this.canceledInternal=!1,this.progressInternal=0}get isCanceled(){return this.canceledInternal}get progress(){return this.progressInternal}setProgress(e){this.progressInternal=Math.max(0,Math.min(100,e))}cancel(){this.canceledInternal=!0}},H=class{constructor(){this.jobs=new Map}register(e){this.jobs.set(e.jobId,{definition:e,status:`idle`,progress:0})}list(){return[...this.jobs.values()].map(e=>({jobId:e.definition.jobId,status:e.status,progress:e.progress,lastRunAt:e.lastRunAt}))}getStatus(e){let t=this.jobs.get(e);if(t)return{jobId:t.definition.jobId,status:t.status,progress:t.progress,lastRunAt:t.lastRunAt}}ensure(e){let t=this.getJobOrThrow(e);t.scheduler||this.startScheduler(t)}start(e){let t=this.getJobOrThrow(e);if(t.scheduler)throw V.alreadyRunning(e);this.startScheduler(t)}async run(e,...t){let n=this.getJobOrThrow(e);if(n.status===`running`)throw V.alreadyRunning(e);return this.executeJob(n,t)}async stop(e){let t=this.getJobOrThrow(e);if(t.scheduler?.stop(),t.scheduler=void 0,t.context&&t.context.cancel(),t.runningPromise)try{await t.runningPromise}catch{}t.status=`idle`}cancel(e){let t=this.getJobOrThrow(e);t.context&&t.context.cancel()}async dispose(){for(let[e]of this.jobs)await this.stop(e);this.jobs.clear()}getJobOrThrow(e){let t=this.jobs.get(e);if(!t)throw V.notFound(e);return t}startScheduler(e){e.definition.cron&&(e.scheduler=new r(e.definition.cron,()=>{e.status!==`running`&&this.executeJob(e,[])}),e.status=`scheduled`)}async executeJob(e,t){let n=new ve;e.context=n,e.status=`running`,e.progress=0;let r=(async()=>{try{return await B.run(e.definition.injector,()=>e.definition.handler(n,...t))}catch(t){throw V.executionFailed(e.definition.jobId,t)}finally{e.progress=n.progress,e.lastRunAt=Date.now(),e.status=e.scheduler?`scheduled`:`idle`,e.context=void 0,e.runningPromise=void 0}})();return e.runningPromise=r,r}};function ye(e){let t=e.definition;return{id:t.id,target:t.target.name,kind:t.kind,scope:t.scope,bridgeChannels:t.bridgeMethods.map(e=>e.channel),signalIds:t.signalHandlers.map(e=>e.signalId),jobIds:t.jobs.map(e=>e.jobId)}}function be(e){return{id:e.id,target:e.target.name,status:e.status,imports:e.imports.map(e=>e.id),exports:[...e.exportTargets].map(e=>e.name),providers:e.providers.map(ye)}}var U=class{constructor(){this.modulesByTarget=new Map,this.modulesById=new Map}load(e){for(let t of e)this.modulesByTarget.set(t.target,t),this.modulesById.set(t.id,t)}getByTarget(e){return this.modulesByTarget.get(e)}getById(e){return this.modulesById.get(e)}getAll(){return[...this.modulesById.values()]}snapshot(){return this.getAll().map(be)}},W=class e extends h{constructor(e,t,n){super(e,t,n)}static invalidSignalId(t){return new e(`Invalid signal id: expected a non-empty string, got ${typeof t==`string`?`"${t}"`:String(t)}.`,`ELECTRO_SIGNAL_INVALID_ID`,{signalId:String(t)})}},xe=class{constructor(){this.listeners=new Set}connect(e){return this.listeners.add(e),()=>this.listeners.delete(e)}publish(e,t){for(let n of this.listeners)try{n(e,t)}catch(t){k(`SignalRelay:${e}`,`publication failed`,t)}}},G=class{constructor(){this.timestamp=Date.now()}};function Se(e){return e.length>=2}function Ce(e){return Se(e)?e:(t,n)=>e(n)}function we(e){let t=B.current();if(!t)return e;let n=B.currentOwner();return(r,i)=>n?B.runOwned(t,n,()=>e(r,i)):B.run(t,()=>e(r,i))}function Te(e){if(typeof e!=`string`)throw W.invalidSignalId(e);let t=e.trim();if(t.length===0)throw W.invalidSignalId(e);return t}var K=class{constructor(){this.handlers=new Map,this.relay=new xe}subscribe(e,t){let n=Te(e),r=this.handlers.get(n)??new Set,i=we(Ce(t));return r.add(i),this.handlers.set(n,r),()=>{r.delete(i),r.size===0&&this.handlers.delete(n)}}publish(e,t){let n=Te(e),r=this.handlers.get(n);if(r)for(let e of r)queueMicrotask(()=>{Promise.resolve(e(new G,t)).catch(e=>{k(`SignalBus:${n}`,`handler failed`,e)})});this.relay.publish(n,t)}connectRelay(e){return this.relay.connect(e)}};function Ee(e,n){let{ipcMain:r}=m(`electron`);return r.handle(t.register,(e,t)=>(n.getOrCreateSession(e.sender.id,t.viewId),{ok:!0})),r.handle(t.bridge,(t,n)=>e.dispatch(t.sender.id,n)),()=>{r.removeHandler(t.register),r.removeHandler(t.bridge)}}var De=class{constructor(e,t,n){this.channel=e.channel,this.kind=e.kind,this.moduleId=e.moduleId,this.invoker=t,this.injector=n}async invoke(e){return B.run(this.injector,()=>this.invoker(...e))}};function Oe(e,t){t.moduleRegistry.load(e);for(let n of e){je(n,t);for(let e of n.providers)Ne(e,t.bridgeDispatcher),Pe(e,t.signalBus),Fe(e,t.jobRegistry),Le(e,t.windowManager,t.viewManager,t.rendererRegistry)}}function q(e,t,n){t in e||Object.defineProperty(e,t,{configurable:!0,enumerable:!1,get:n})}function ke(e){let t={};for(let n of c(e.target)){if(n.kind!==`command`&&n.kind!==`query`)continue;let r=Reflect.get(e.instance,n.methodName);typeof r==`function`&&(t[n.id]=r.bind(e.instance))}for(let n of e.providers)for(let r of n.definition.bridgeMethods){let i=n.getMethod(r.methodName);i&&(t[r.channel.slice(`${e.id}:`.length)]=i.bind(n.instance))}return t}function Ae(e,t,n,r){let i=r.logger.child({target:x(e,t.id)});q(e,`moduleId`,()=>t.id),q(e,`api`,()=>n),q(e,`signals`,()=>r.signalBus),q(e,`jobs`,()=>r.jobRegistry),q(e,`modules`,()=>r.moduleRegistry),q(e,`windows`,()=>r.windowManager),q(e,`views`,()=>r.viewManager),q(e,`logger`,()=>i)}function je(e,t){let n=ke(e);Ae(e.instance,e,n,t);for(let r of e.providers)Ae(r.instance,e,n,t)}function Me(e,t){t(t=>e.setKernelState(t))}function Ne(e,t){for(let n of e.definition.bridgeMethods){let r=e.getMethod(n.methodName);if(!r)continue;let i=new De(n,r.bind(e.instance),e.injector);t.registerHandler(i)}}function Pe(e,t){for(let n of e.definition.signalHandlers){let r=e.getMethod(n.methodName);if(!r)continue;let i=r.bind(e.instance);B.run(e.injector,()=>{t.subscribe(n.signalId,i)})}}function Fe(e,t){for(let n of e.definition.jobs){let r=e.getMethod(n.methodName);if(!r)continue;let i=r.bind(e.instance);t.register({jobId:n.jobId,cron:n.cron,handler:i,injector:e.injector})}}function Ie(e,n){return e.connectRelay((e,r)=>{let i=m(`electron`);for(let a of n.getAllSessions())a.canReceiveSignal(e)&&i.webContents.fromId(a.rendererId)?.send(t.signal,{signalId:e,payload:r})})}function Le(e,t,n,r){e.definition.kind===`window`&&t.register(e),e.definition.kind===`view`&&(n.register(e),e.definition.view&&r.registerView(e.definition.view))}var J=class e extends h{constructor(e,t,n){super(e,t,n)}static providerNotFound(t){return new e(`No provider found for "${t}".`,`ELECTRO_DI_PROVIDER_NOT_FOUND`,{token:t})}static duplicateProvider(t){return new e(`Provider "${t}" is already registered in this injector.`,`ELECTRO_DI_DUPLICATE_PROVIDER`,{token:t})}static circularDependency(t){return new e(`Circular dependency detected: ${t.join(` → `)}.`,`ELECTRO_DI_CIRCULAR_DEPENDENCY`,{path:t})}static invalidClassProvider(t){return new e(`"${t}" is not a framework-managed class. Ensure it is decorated with @Injectable(), @Module(), @View(), or @Window().`,`ELECTRO_DI_INVALID_CLASS_PROVIDER`,{token:t})}static noInjectionContext(){return new e(`inject() called outside of a framework-managed context. inject() is only available during construction (property initializers), lifecycle hooks (onInit/onReady/onShutdown/onDispose), and capability handlers (bridge, signal, job).`,`ELECTRO_DI_NO_INJECTION_CONTEXT`)}};function Y(e){return p(e)?e.key:e}function Re(e){return s(e)!==void 0||l(e)!==void 0||u(e)!==void 0||d(e)!==void 0}function ze(e){if(f(e)){let t=s(e.useClass);return{kind:`class`,provide:e.provide,useClass:e.useClass,scope:t?.scope??`singleton`}}let t=e;return{kind:`class`,provide:t,useClass:t,scope:s(t)?.scope??`singleton`}}var Be=class e{constructor(e){this.parent=e,this.providers=new Map,this.instances=new Map,this.resolutionPath=[]}createChild(){return new e(this)}provide(e){let t=ze(e),n=Y(t.provide),r=o(t.provide);if(this.providers.has(n))throw J.duplicateProvider(r);this.providers.set(n,t)}provideValue(e,t){let n=Y(e),r=o(e);if(this.providers.has(n))throw J.duplicateProvider(r);let i={kind:`value`,provide:e,useValue:t};this.providers.set(n,i)}has(e){let t=Y(e);return this.providers.has(t)||this.parent?.has(e)===!0}get(e){let t=o(e);return this.resolve(e,t)}resolve(e,t){let n=Y(e),r=this.providers.get(n);if(r)return this.resolveRecord(r,n,t);if(this.parent)return this.parent.resolve(e,t);throw J.providerNotFound(t)}resolveRecord(e,t,n){return e.kind===`value`?e.useValue:this.resolveWithPath(n,()=>e.scope===`transient`?this.instantiate(e.useClass,n):this.resolveSingleton(e,t,n))}resolveSingleton(e,t,n){let r=this.instances.get(t);if(r?.status===`resolved`)return r.value;if(r?.status===`resolving`)throw J.circularDependency([...this.resolutionPath,n]);this.instances.set(t,{status:`resolving`});try{let r=this.instantiate(e.useClass,n);return this.instances.set(t,{status:`resolved`,value:r}),r}catch(e){throw this.instances.delete(t),e}}instantiate(e,t){if(!Re(e))throw J.invalidClassProvider(t);return B.run(this,()=>new e)}resolveWithPath(e,t){if(this.resolutionPath.includes(e))throw J.circularDependency([...this.resolutionPath,e]);this.resolutionPath.push(e);try{return t()}finally{this.resolutionPath.pop()}}},X=class e extends h{constructor(e,t,n){super(e,t,n)}static rootModuleNotDecorated(t){return new e(`Class "${t}" is not decorated with @Module().`,`ELECTRO_BOOTSTRAP_ROOT_NOT_MODULE`,{className:t})}static invalidImportedModule(t,n){return new e(`Module "${t}" imports "${n}" which is not decorated with @Module().`,`ELECTRO_BOOTSTRAP_INVALID_IMPORT`,{parentModule:t,importedName:n})}static invalidModuleProvider(t,n){return new e(`Module "${t}" declares provider "${n}" which is not decorated with @Injectable().`,`ELECTRO_BOOTSTRAP_INVALID_PROVIDER`,{moduleName:t,providerName:n})}static invalidModuleView(t,n){return new e(`Module "${t}" declares view "${n}" which is not decorated with @View().`,`ELECTRO_BOOTSTRAP_INVALID_VIEW`,{moduleName:t,viewName:n})}static invalidModuleWindow(t,n){return new e(`Module "${t}" declares window "${n}" which is not decorated with @Window().`,`ELECTRO_BOOTSTRAP_INVALID_WINDOW`,{moduleName:t,windowName:n})}static circularModuleImport(t){return new e(`Circular module import detected: ${t.join(` → `)}.`,`ELECTRO_BOOTSTRAP_CIRCULAR_IMPORT`,{cycle:t})}static duplicateModuleId(t){return new e(`Duplicate module id "${t}". Module ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_MODULE_ID`,{moduleId:t})}static invalidExport(t,n){return new e(`Module "${t}" exports "${n}" which is not declared in its providers.`,`ELECTRO_BOOTSTRAP_INVALID_EXPORT`,{moduleName:t,exportName:n})}static duplicateViewId(t){return new e(`Duplicate view id "${t}". View ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_VIEW_ID`,{viewId:t})}static duplicateWindowId(t){return new e(`Duplicate window id "${t}". Window ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_WINDOW_ID`,{windowId:t})}static duplicateBridgeChannel(t){return new e(`Duplicate bridge channel "${t}". Bridge channels must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_BRIDGE_CHANNEL`,{channel:t})}static duplicateJobId(t){return new e(`Duplicate job id "${t}". Job ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_JOB_ID`,{jobId:t})}static invalidProviderRoleCombination(t){return new e(`Provider "${t}" has both @View() and @Window() — a provider can only have one role.`,`ELECTRO_BOOTSTRAP_INVALID_ROLE_COMBINATION`,{providerName:t})}static invalidViewAccessReference(t,n){return new e(`View "${t}" references bridge channel "${n}" in access, but no such channel exists.`,`ELECTRO_BOOTSTRAP_INVALID_VIEW_ACCESS`,{viewId:t,channel:n})}static invalidViewSignalReference(t,n){return new e(`View "${t}" references signal "${n}" in signals, but no such signal handler exists.`,`ELECTRO_BOOTSTRAP_INVALID_VIEW_SIGNAL`,{viewId:t,signalId:n})}static importedModuleNotLoaded(t,n){return new e(`Module "${t}" imports "${n}" which has not been loaded yet.`,`ELECTRO_BOOTSTRAP_IMPORT_NOT_LOADED`,{parentModule:t,importedModule:n})}static invalidCapabilityMethod(t,n,r){return new e(`Provider "${t}" declares ${n} method "${r}" which is not a function.`,`ELECTRO_BOOTSTRAP_INVALID_CAPABILITY_METHOD`,{providerName:t,capability:n,methodName:r})}};function Ve(e){let t=l(e);if(t?.id)return t.id;let n=e.name;return n.endsWith(`Module`)?n.slice(0,-6).toLowerCase():n.toLowerCase()}function He(e,t){return`${e}:${t.id}`}function Ue(e,t){return t.id}function We(e,t){return`${e}:${t.id}`}function Ge(e,t,n){let r=c(t),i=[],a=[],o=[];for(let t of r)switch(t.kind){case`command`:case`query`:i.push({channel:He(e,t),kind:t.kind,moduleId:e,providerName:n,methodName:t.methodName});break;case`signal`:a.push({signalId:Ue(e,t),moduleId:e,providerName:n,methodName:t.methodName});break;case`job`:o.push({jobId:We(e,t),moduleId:e,providerName:n,methodName:t.methodName,cron:t.cron});break}return{bridgeMethods:i,signalHandlers:a,jobs:o}}function Ke(e){let t=new Map,n=[],r=[],i=[],o=e=>{if(t.has(e))return;let c=l(e);if(!c)throw X.rootModuleNotDecorated(e.name);let f=Ve(e),p=(c.imports??[]).map(e=>a.resolve(e)),m=(c.providers??[]).map(e=>a.resolve(e)),h=(c.views??[]).map(e=>a.resolve(e)),g=(c.windows??[]).map(e=>a.resolve(e)),_=(c.exports??[]).map(e=>a.resolve(e));for(let t of p)if(!l(t))throw X.invalidImportedModule(e.name,t.name);let v=(t,n)=>{let a=s(t),o=u(t),c=d(t);if(n===`provider`&&!a)throw X.invalidModuleProvider(e.name,t.name);if(n===`view`&&!o)throw X.invalidModuleView(e.name,t.name);if(n===`window`&&!c)throw X.invalidModuleWindow(e.name,t.name);let l=o?{id:o.id,ownerModuleId:f,source:o.source,access:o.access??[],signals:o.signals??[],target:t,configuration:o.configuration}:void 0,p=c?{id:c.id,ownerModuleId:f,target:t,configuration:c.configuration}:void 0,m=Ge(f,t,t.name),h={id:t.name,target:t,ownerModuleId:f,scope:a?.scope??`singleton`,kind:n,view:l,window:p,bridgeMethods:m.bridgeMethods,signalHandlers:m.signalHandlers,jobs:m.jobs};return l&&r.push(l),p&&i.push(p),h},y=[...m.map(e=>v(e,`provider`)),...h.map(e=>v(e,`view`)),...g.map(e=>v(e,`window`))];n.push(...y),t.set(e,{id:f,target:e,imports:p,providers:y,exportTargets:_});for(let e of p)o(e)};return o(e),{rootModule:e,modules:[...t.values()],providers:n,views:r,windows:i,bridgeMethods:n.flatMap(e=>e.bridgeMethods),signalHandlers:n.flatMap(e=>e.signalHandlers),jobs:n.flatMap(e=>e.jobs)}}function qe(e){Je(e.modules),Ye(e),Xe(e),Ze(e),Qe(e),$e(e),et(e),tt(e),nt(e)}function Je(e){let t=new Set;for(let n of e){if(t.has(n.id))throw X.duplicateModuleId(n.id);t.add(n.id)}}function Ye(e){for(let t of e.modules){let e=new Set(t.providers.map(e=>e.target));for(let n of t.exportTargets)if(!e.has(n))throw X.invalidExport(t.id,n.name)}}function Xe(e){let t=new Map;for(let n of e.modules)t.set(n.target,n);let n=new Set,r=new Set,i=[],a=e=>{if(n.has(e))return;let o=t.get(e);if(o){if(r.has(e))throw X.circularModuleImport([...i,o.id]);r.add(e),i.push(o.id);for(let e of o.imports)a(e);i.pop(),r.delete(e),n.add(e)}};a(e.rootModule)}function Ze(e){let t=new Set;for(let n of e.views){if(t.has(n.id))throw X.duplicateViewId(n.id);t.add(n.id)}}function Qe(e){let t=new Set;for(let n of e.windows){if(t.has(n.id))throw X.duplicateWindowId(n.id);t.add(n.id)}}function $e(e){let t=new Set;for(let n of e.bridgeMethods){if(t.has(n.channel))throw X.duplicateBridgeChannel(n.channel);t.add(n.channel)}}function et(e){let t=new Set;for(let n of e.jobs){if(t.has(n.jobId))throw X.duplicateJobId(n.jobId);t.add(n.jobId)}}function tt(e){for(let t of e.providers){let e=u(t.target)!==void 0,n=d(t.target)!==void 0;if(e&&n)throw X.invalidProviderRoleCombination(t.target.name)}}function nt(e){let t=new Set(e.bridgeMethods.map(e=>e.channel));for(let n of e.views)for(let e of n.access)if(!t.has(e))throw X.invalidViewAccessReference(n.id,e)}const rt={creating:[`ready`,`failed`],ready:[`started`,`failed`],started:[`stopping`,`failed`],stopping:[`stopped`,`failed`],stopped:[],failed:[]};var it=class{constructor(e,t,n){this.definition=e,this.instance=t,this.injector=n}get id(){return this.definition.id}get target(){return this.definition.target}get ownerModuleId(){return this.definition.ownerModuleId}getMethod(e){let t=Reflect.get(this.instance,e);return typeof t==`function`?t:void 0}},at=class{constructor(e,t,n,r,i,a){this.id=e,this.target=t,this.injector=n,this.instance=r,this.providers=i,this.exportTargets=a,this.statusInternal=`creating`,this.importsInternal=[]}get status(){return this.statusInternal}get imports(){return this.importsInternal}get exportedProviders(){return this.providers.filter(e=>this.exportTargets.has(e.target))}linkImports(e){this.importsInternal=e}transitionTo(e){if(this.statusInternal!==e){if(!rt[this.statusInternal].includes(e))throw R.invalidModuleTransition(this.id,this.statusInternal,e);this.statusInternal=e}}};function ot(e){let t=new Map;for(let n of e.modules)t.set(n.target,n);let n=new Set,r=[],i=e=>{if(n.has(e))return;n.add(e);let a=t.get(e);if(a){for(let e of a.imports)i(e);r.push(a)}};return i(e.rootModule),r}function st(e,t){let n=ot(e),r=new Map;for(let e of n){let n=t.createChild(),i=e.providers;for(let t of e.imports){let i=r.get(t);if(!i)throw X.importedModuleNotLoaded(e.id,t.name);for(let e of i.exportedProviders)n.provideValue(e.target,i.injector.get(e.target))}for(let e of i)n.provide(e.target);n.provide(e.target);let a=n.get(e.target),o=i.map(e=>new it(e,n.get(e.target),n)),s=new at(e.id,e.target,n,a,o,new Set(e.exportTargets)),c=e.imports.map(e=>r.get(e)).filter(e=>e!==void 0);s.linkImports(c),r.set(e.target,s)}return n.map(e=>r.get(e.target))}var ct=class e{constructor(e,t,n){this.definition=e,this.rootInjector=t,this.moduleRefs=n}static create(t,n){let r=Ke(t);qe(r);let i=new Be;return n?.(i),new e(r,i,st(r,i))}};function lt(e,t){return typeof e[t]==`function`}function Z(e,t){let n=e.constructor?.name?.trim();return n&&n.length>0?n:t}async function Q(e,t,n){if(lt(e,t))try{await B.run(n,()=>e[t]())}catch(n){throw k(e,`${t} failed`,n),R.startupFailed(t,e.constructor.name,n)}}async function $(e,t,n){if(lt(e,t))try{await B.run(n,()=>e[t]())}catch(n){k(e,`${t} failed`,n)}}async function ut(e){let t=[],n=[];try{for(let n of e){let e=Z(n.instance,n.id);D(e,`initializing`);for(let e of n.providers)await Q(e.instance,`onInit`,e.injector);await Q(n.instance,`onInit`,n.injector),n.transitionTo(`ready`),D(e,`initialized`),t.push(n)}for(let t of e){let e=Z(t.instance,t.id);D(e,`starting`);for(let e of t.providers)await Q(e.instance,`onReady`,e.injector);await Q(t.instance,`onReady`,t.injector),t.transitionTo(`started`),D(e,`started`),n.push(t)}}catch(r){for(let t of e)if(t.status!==`stopped`&&t.status!==`failed`)try{t.transitionTo(`failed`),D(Z(t.instance,t.id),`failed`,`error`)}catch{}for(let e of[...n].reverse()){await $(e.instance,`onShutdown`,e.injector);for(let t of[...e.providers].reverse())await $(t.instance,`onShutdown`,t.injector)}for(let e of[...t].reverse()){await $(e.instance,`onDispose`,e.injector);for(let t of[...e.providers].reverse())await $(t.instance,`onDispose`,t.injector)}throw r}}async function dt(e){let t=[...e].reverse();for(let e of t){D(Z(e.instance,e.id),`stopping`),await $(e.instance,`onShutdown`,e.injector);for(let t of[...e.providers].reverse())await $(t.instance,`onShutdown`,t.injector);e.transitionTo(`stopping`)}for(let e of t){let t=Z(e.instance,e.id);await $(e.instance,`onDispose`,e.injector);for(let t of[...e.providers].reverse())await $(t.instance,`onDispose`,t.injector);e.transitionTo(`stopped`),D(t,`stopped`)}}const ft={idle:[`initializing`],initializing:[`initialized`,`failed`],initialized:[`starting`],starting:[`started`,`failed`],started:[`stopping`],stopping:[`stopped`,`failed`],stopped:[],failed:[]};var pt=class e{constructor(e,t={}){this.state=`idle`,this.stateListeners=[],this.disposers=[],this.rootModule=e,this.logger=t.logger??w()}static create(t,n={}){return new e(t,n)}async start(){if(this.state!==`started`){E(this.logger),this.transitionTo(`initializing`);try{this.composition=ct.create(this.rootModule,e=>this.registerFrameworkServices(e)),Oe(this.composition.moduleRefs,this.services),Me(this.services.bridgeAccessGuard,e=>this.onStateChange(e)),this.disposers.push(Ee(this.services.bridgeDispatcher,this.services.rendererRegistry)),this.disposers.push(Ie(this.services.signalBus,this.services.rendererRegistry)),this.transitionTo(`initialized`),this.transitionTo(`starting`),await ut(this.composition.moduleRefs),this.transitionTo(`started`)}catch(e){throw this.transitionTo(`failed`),await this.safeDisposeServices(),E(void 0),e}}}async shutdown(){if(!(this.state===`idle`||this.state===`stopped`)){if(this.state!==`started`)throw R.kernelNotStarted();this.transitionTo(`stopping`);try{await dt(this.composition.moduleRefs),await this.disposeServices(),this.transitionTo(`stopped`)}catch(e){throw this.transitionTo(`failed`),e}finally{E(void 0)}}}getState(){return this.state}isStarted(){return this.state===`started`}getDefinition(){return this.composition?.definition}getModuleRefs(){return this.composition?.moduleRefs??[]}onStateChange(e){this.stateListeners.push(e)}registerFrameworkServices(e){let t=new K,n=new H,r=new U,i=new b,a=new _,o=new y(i,a),s=new L,c=new N;e.provideValue(K,t),e.provideValue(H,n),e.provideValue(U,r),e.provideValue(b,i),e.provideValue(y,o),e.provideValue(_,a),e.provideValue(L,s),e.provideValue(N,c),this.services={signalBus:t,jobRegistry:n,moduleRegistry:r,bridgeDispatcher:o,bridgeAccessGuard:a,windowManager:s,viewManager:c,rendererRegistry:i,logger:this.logger}}async disposeServices(){for(let e of this.disposers)e();this.disposers.length=0,await this.services?.jobRegistry.dispose(),await this.services?.windowManager.dispose(),await this.services?.viewManager.dispose()}transitionTo(e){if(!ft[this.state].includes(e))throw R.invalidKernelTransition(this.state,e);this.state=e,D(`AppKernel`,e);for(let t of this.stateListeners)t(e)}async safeDisposeServices(){try{await this.disposeServices()}catch{}}};function mt(e){let t=B.current();if(!t)throw J.noInjectionContext();return t.get(e)}export{pt as AppKernel,X as BootstrapError,_ as BridgeAccessGuard,y as BridgeDispatcher,g as BridgeError,De as BridgeHandler,J as DIError,t as IPC_CHANNELS,B as InjectionContext,Be as Injector,ve as JobContext,V as JobError,H as JobRegistry,R as LifecycleError,at as ModuleRef,U as ModuleRegistry,it as ProviderRef,b as RendererRegistry,ee as RendererSession,h as RuntimeError,K as SignalBus,G as SignalContext,W as SignalError,N as ViewManager,M as ViewProvider,L as WindowManager,I as WindowProvider,e as createBridgeClient,w as createConsoleLogger,mt as inject,Ke as scanModules,v as serializeBridgeError,qe as validateAppDefinition};
1
+ import{n as e,t}from"./client-CD3ueTol.mjs";import{createRequire as n}from"node:module";import{Cron as r}from"croner";import{AsyncLocalStorage as i}from"node:async_hooks";import{Ref as a,describeInjectionToken as o,getInjectableMetadata as s,getMethodsMetadataByClass as c,getModuleMetadata as l,getViewMetadata as u,getWindowMetadata as d,isClassProvider as f,isInjectionTokenSymbol as p}from"@electrojs/common";var m=n(import.meta.url),h=class extends Error{constructor(e,t,n){super(e),this.name=new.target.name,this.code=t,this.context=n,Object.setPrototypeOf(this,new.target.prototype)}},g=class e extends h{constructor(e,t,n){super(e,t,n)}static accessDenied(t,n){return new e(`View "${t}" does not have access to bridge channel "${n}".`,`ELECTRO_BRIDGE_ACCESS_DENIED`,{viewId:t,channel:n})}static routeNotFound(t){return new e(`No bridge handler registered for channel "${t}".`,`ELECTRO_BRIDGE_ROUTE_NOT_FOUND`,{channel:t})}static handlerFailed(t,n){let r=new e(`Bridge handler for channel "${t}" threw an error.`,`ELECTRO_BRIDGE_HANDLER_FAILED`,{channel:t});return r.cause=n,r}static kernelNotReady(){return new e(`Bridge invocation rejected — kernel is not accepting bridge calls in its current state.`,`ELECTRO_BRIDGE_KERNEL_NOT_READY`)}static unknownRenderer(t){return new e(`Received bridge request from unregistered renderer (webContents id: ${t}).`,`ELECTRO_BRIDGE_UNKNOWN_RENDERER`,{webContentsId:t})}},_=class{constructor(){this.kernelState=`idle`}setKernelState(e){this.kernelState=e}assertKernelReady(){if(this.kernelState!==`starting`&&this.kernelState!==`started`)throw g.kernelNotReady()}assertAccess(e,t){if(!e.hasAccess(t))throw g.accessDenied(e.viewId,t)}};function v(e){return e instanceof Error?{message:e.message,code:e.code,context:e.context}:{message:String(e)}}var y=class{constructor(e,t){this.rendererRegistry=e,this.accessGuard=t,this.handlers=new Map}registerHandler(e){this.handlers.set(e.channel,e)}async dispatch(e,t){try{this.accessGuard.assertKernelReady();let n=this.rendererRegistry.getSession(e);if(!n)throw g.unknownRenderer(e);this.accessGuard.assertAccess(n,t.channel);let r=this.handlers.get(t.channel);if(!r)throw g.routeNotFound(t.channel);let i=await r.invoke(t.args);return{callId:t.callId,result:i}}catch(e){return{callId:t.callId,error:v(e)}}}};function ee(e,n){let{ipcMain:r}=m(`electron`);return r.handle(t.register,(e,t)=>(n.getOrCreateSession(e.sender.id,t.viewId),{ok:!0})),r.handle(t.bridge,(t,n)=>e.dispatch(t.sender.id,n)),()=>{r.removeHandler(t.register),r.removeHandler(t.bridge)}}var te=class{constructor(e,t){this.rendererId=e,this.viewId=t.id,this.access=new Set(t.access),this.allowedSignals=new Set(t.signals)}hasAccess(e){return this.access.has(e)}canReceiveSignal(e){return this.allowedSignals.has(e)}},b=class{constructor(){this.sessions=new Map,this.viewDefinitions=new Map}registerView(e){this.viewDefinitions.set(e.id,e)}getOrCreateSession(e,t){let n=this.sessions.get(e);if(n)return n;let r=this.viewDefinitions.get(t);if(!r)throw g.unknownRenderer(e);let i=new te(e,r);return this.sessions.set(e,i),i}getSession(e){return this.sessions.get(e)}removeSession(e){this.sessions.delete(e)}getAllSessions(){return[...this.sessions.values()]}};function ne(e){return e.toTimeString().slice(0,8)}function re(e){return e===`electro`?`electro`:e}function ie(e,t){return e===`warn`||e===`error`?!0:t.ELECTRO_DEV===`true`}function ae(e){return e instanceof Error?{name:e.name,message:e.message,stack:e.stack}:e}function oe(e){if(!e)return``;let t=Object.entries(e).filter(([,e])=>e!==void 0);if(t.length===0)return``;try{return` ${JSON.stringify(Object.fromEntries(t.map(([e,t])=>[e,ae(t)])))}`}catch{return` [unserializable context]`}}function se(e,t,n,r=new Date){return`${ne(r)} [${re(e)}] ${t} → ${n}`}function x(e,t=`Electro`){if(typeof e==`string`&&e.trim().length>0)return e;let n=e.constructor?.name?.trim();return n&&n.length>0?n:t}var ce=class e{constructor(e={},t=process.env){this.bindings=e,this.env=t}debug(e,t){this.write(`debug`,e,t)}info(e,t){this.write(`info`,e,t)}warn(e,t){this.write(`warn`,e,t)}error(e,t){this.write(`error`,e,t)}child(t){return new e({...this.bindings,...t},this.env)}write(e,t,n){if(!ie(e,this.env))return;let r=x(this.bindings.target??`Electro`),i=se(e===`warn`?`warn`:e===`error`?`error`:`electro`,r,`${t}${oe(n)}`);console.log(i)}};const le=new ce;let S;function C(){return new ce}function ue(){return S??le}function w(e){S=e}function T(e,t,n=`electro`){let r=ue().child({target:e});switch(n){case`warn`:r.warn(t);return;case`error`:r.error(t);return;default:r.info(t)}}function E(e,t,n=`electro`){T(x(e),t,n)}function D(e,t,n){ue().child({target:x(e)}).error(t,{error:n})}const O=Symbol(`electro.view-state`),de=[`load`,`setBounds`,`setBackgroundColor`,`focus`,`setWindowButtonVisibility`];function k(e){return e[O]||Object.defineProperty(e,O,{value:{},configurable:!1,enumerable:!1,writable:!0}),e[O]}function fe(){return typeof __ELECTRO_VIEW_REGISTRY__>`u`?[]:__ELECTRO_VIEW_REGISTRY__}function pe(e){let t=e.slice(5).trim(),n=fe().find(e=>e.id===t)?.source;if(!n)throw Error(`Bundled view source "${e}" could not be resolved. Start the app through the ElectroJS CLI so the view registry is injected.`);return n}function me(e){let t=e.slice(5).trim();return fe().find(e=>e.id===t)}function he(){return Object.getOwnPropertyDescriptor(A.prototype,`contentView`)}function ge(){return Object.getOwnPropertyDescriptor(A.prototype,`webContents`)}function _e(e,t,n){let r=e,i=k(r);t!==void 0&&(i.source=t),n!==void 0&&(i.webPreferences=n);let a=he();!(`contentView`in r)&&a?.get&&Object.defineProperty(r,`contentView`,{configurable:!0,enumerable:!1,get(){return a.get?.call(this)}});let o=ge();!(`webContents`in r)&&o?.get&&Object.defineProperty(r,`webContents`,{configurable:!0,enumerable:!1,get(){return o.get?.call(this)}});for(let e of de)e in r||Object.defineProperty(r,e,{configurable:!0,enumerable:!1,writable:!0,value:A.prototype[e]})}var A=class e{constructor(){this[O]={}}get contentView(){return this[O].view}get webContents(){return this[O].view?.webContents}async load(){(!this[O].view||this[O].view.webContents.isDestroyed())&&(this[O].view=void 0,this.createView());let t=this[O].source;if(!t||!this[O].view)return;let n=e.resolveSource(t);E(this,`loaded ${n}`),await this[O].view.webContents.loadURL(n)}setBounds(e){this[O].view?.setBounds(e)}setBackgroundColor(e){this[O].view?.setBackgroundColor(e)}focus(){this[O].view?.webContents.focus()}setWindowButtonVisibility(e){this[O].view?.setWindowButtonVisibility?.(e)}createView(){let{WebContentsView:e}=m(`electron`),t=this[O].webPreferences??{},n=typeof this[O].source==`string`&&this[O].source.startsWith(`view:`)?me(this[O].source):void 0;this[O].view=new e({webPreferences:{...t,...n?.preload?{preload:n.preload}:{},sandbox:!0,contextIsolation:!0,nodeIntegration:!1}}),E(this,`created`)}static resolveSource(e){return e.startsWith(`http://`)||e.startsWith(`https://`)||e.startsWith(`file:`)?e:e.startsWith(`view:`)?pe(e):e}static __setSource(e,t){k(e).source=t}static __setWebPreferences(e,t){k(e).webPreferences=t}},j=class{constructor(){this.views=new Map}register(e){let t=e.definition.view;t&&(this.views.set(t.id,e),_e(e.instance,t.source,t.configuration?.webPreferences))}get(e){return this.views.get(e)}list(){return[...this.views.values()]}async dispose(){this.views.clear()}};const M=Symbol(`electro.window-state`),ve=[`create`,`mount`,`show`,`hide`,`focus`,`close`,`getBounds`];function N(e){return e[M]||Object.defineProperty(e,M,{value:{},configurable:!1,enumerable:!1,writable:!0}),e[M]}function ye(){return Object.getOwnPropertyDescriptor(P.prototype,`window`)}function be(e,t){let n=e,r=N(n);t!==void 0&&(r.configuration=t);let i=ye();!(`window`in n)&&i?.get&&Object.defineProperty(n,`window`,{configurable:!0,enumerable:!1,get(){return i.get?.call(this)}});for(let e of ve)e in n||Object.defineProperty(n,e,{configurable:!0,enumerable:!1,writable:!0,value:P.prototype[e]})}var P=class{constructor(){this[M]={}}get window(){return this[M].window}create(){if(this[M].window)return;let{BaseWindow:e}=m(`electron`),t=new e(this[M].configuration??{});this[M].window=t,t.on(`closed`,()=>{this[M].window=void 0,E(this,`closed`)}),E(this,`created`)}mount(e){let t=this[M].window;if(!t)return;let n=e.contentView;n&&(t.contentView.addChildView(n),E(this,`mounted ${e.constructor.name||`ViewProvider`}`))}show(){let e=this[M].window;e&&(e.show(),E(this,`shown`))}hide(){this[M].window?.hide()}focus(){this[M].window?.focus()}close(){let e=this[M].window;e&&e.destroy()}getBounds(){return this[M].window?.getBounds()}static __setConfiguration(e,t){N(e).configuration=t}},F=class{constructor(){this.windows=new Map}register(e){let t=e.definition.window;t&&(this.windows.set(t.id,e),be(e.instance,t.configuration))}get(e){return this.windows.get(e)}list(){return[...this.windows.values()]}async dispose(){for(let e of this.windows.values())(e.instance instanceof P||`close`in e.instance)&&e.instance.close();this.windows.clear()}},I=class e extends h{constructor(e,t,n){super(e,t,n)}static startupFailed(t,n,r){let i=new e(`Lifecycle hook "${t}" failed in "${n}".`,`ELECTRO_LIFECYCLE_STARTUP_FAILED`,{hookName:t,targetName:n});return i.cause=r,i}static invalidKernelTransition(t,n){return new e(`Invalid kernel state transition from "${t}" to "${n}".`,`ELECTRO_LIFECYCLE_INVALID_KERNEL_TRANSITION`,{from:t,to:n})}static invalidModuleTransition(t,n,r){return new e(`Invalid module state transition for "${t}": "${n}" → "${r}".`,`ELECTRO_LIFECYCLE_INVALID_MODULE_TRANSITION`,{moduleId:t,from:n,to:r})}static kernelNotStarted(){return new e(`Cannot shut down kernel — it has not been started.`,`ELECTRO_LIFECYCLE_NOT_STARTED`)}static kernelAlreadyStarted(){return new e(`Cannot start kernel — it is already started or starting.`,`ELECTRO_LIFECYCLE_ALREADY_STARTED`)}};const L=new i,R={run(e,t){return L.run({injector:e},t)},runOwned(e,t,n){return L.run({injector:e,owner:t},n)},current(){return L.getStore()?.injector},currentOwner(){return L.getStore()?.owner},isActive(){return L.getStore()!==void 0}};var z=class e extends h{constructor(e,t,n){super(e,t,n)}static notFound(t){return new e(`Job "${t}" is not registered.`,`ELECTRO_JOB_NOT_FOUND`,{jobId:t})}static alreadyRunning(t){return new e(`Job "${t}" is already running.`,`ELECTRO_JOB_ALREADY_RUNNING`,{jobId:t})}static executionFailed(t,n){let r=new e(`Job "${t}" execution failed.`,`ELECTRO_JOB_EXECUTION_FAILED`,{jobId:t});return r.cause=n,r}},xe=class{constructor(){this.canceledInternal=!1,this.progressInternal=0}get isCanceled(){return this.canceledInternal}get progress(){return this.progressInternal}setProgress(e){this.progressInternal=Math.max(0,Math.min(100,e))}cancel(){this.canceledInternal=!0}},B=class{constructor(){this.jobs=new Map}register(e){this.jobs.set(e.jobId,{definition:e,status:`idle`,progress:0})}list(){return[...this.jobs.values()].map(e=>({jobId:e.definition.jobId,status:e.status,progress:e.progress,lastRunAt:e.lastRunAt}))}getStatus(e){let t=this.jobs.get(e);if(t)return{jobId:t.definition.jobId,status:t.status,progress:t.progress,lastRunAt:t.lastRunAt}}ensure(e){let t=this.getJobOrThrow(e);t.scheduler||this.startScheduler(t)}start(e){let t=this.getJobOrThrow(e);if(t.scheduler)throw z.alreadyRunning(e);this.startScheduler(t)}async run(e,...t){let n=this.getJobOrThrow(e);if(n.status===`running`)throw z.alreadyRunning(e);return this.executeJob(n,t)}async stop(e){let t=this.getJobOrThrow(e);if(t.scheduler?.stop(),t.scheduler=void 0,t.context&&t.context.cancel(),t.runningPromise)try{await t.runningPromise}catch{}t.status=`idle`}cancel(e){let t=this.getJobOrThrow(e);t.context&&t.context.cancel()}async dispose(){for(let[e]of this.jobs)await this.stop(e);this.jobs.clear()}getJobOrThrow(e){let t=this.jobs.get(e);if(!t)throw z.notFound(e);return t}startScheduler(e){e.definition.cron&&(e.scheduler=new r(e.definition.cron,()=>{e.status!==`running`&&this.executeJob(e,[])}),e.status=`scheduled`)}async executeJob(e,t){let n=new xe;e.context=n,e.status=`running`,e.progress=0;let r=(async()=>{try{return await R.run(e.definition.injector,()=>e.definition.handler(n,...t))}catch(t){throw z.executionFailed(e.definition.jobId,t)}finally{e.progress=n.progress,e.lastRunAt=Date.now(),e.status=e.scheduler?`scheduled`:`idle`,e.context=void 0,e.runningPromise=void 0}})();return e.runningPromise=r,r}};function Se(e){let t=e.definition;return{id:t.id,target:t.target.name,kind:t.kind,scope:t.scope,bridgeChannels:t.bridgeMethods.map(e=>e.channel),signalIds:t.signalHandlers.map(e=>e.signalId),jobIds:t.jobs.map(e=>e.jobId)}}function Ce(e){return{id:e.id,target:e.target.name,status:e.status,imports:e.imports.map(e=>e.id),exports:[...e.exportTargets].map(e=>e.name),providers:e.providers.map(Se)}}var V=class{constructor(){this.modulesByTarget=new Map,this.modulesById=new Map}load(e){for(let t of e)this.modulesByTarget.set(t.target,t),this.modulesById.set(t.id,t)}getByTarget(e){return this.modulesByTarget.get(e)}getById(e){return this.modulesById.get(e)}getAll(){return[...this.modulesById.values()]}snapshot(){return this.getAll().map(Ce)}},H=class e extends h{constructor(e,t,n){super(e,t,n)}static invalidSignalId(t){return new e(`Invalid signal id: expected a non-empty string, got ${typeof t==`string`?`"${t}"`:String(t)}.`,`ELECTRO_SIGNAL_INVALID_ID`,{signalId:String(t)})}},we=class{constructor(){this.listeners=new Set}connect(e){return this.listeners.add(e),()=>this.listeners.delete(e)}publish(e,t){for(let n of this.listeners)try{n(e,t)}catch(t){D(`SignalRelay:${e}`,`publication failed`,t)}}},Te=class{constructor(){this.timestamp=Date.now()}};function Ee(e){return e.length>=2}function De(e){return Ee(e)?e:(t,n)=>e(n)}function Oe(e){let t=R.current();if(!t)return e;let n=R.currentOwner();return(r,i)=>n?R.runOwned(t,n,()=>e(r,i)):R.run(t,()=>e(r,i))}function U(e){if(typeof e!=`string`)throw H.invalidSignalId(e);let t=e.trim();if(t.length===0)throw H.invalidSignalId(e);return t}var W=class{constructor(){this.handlers=new Map,this.relay=new we}subscribe(e,t){let n=U(e),r=this.handlers.get(n)??new Set,i=Oe(De(t));return r.add(i),this.handlers.set(n,r),()=>{r.delete(i),r.size===0&&this.handlers.delete(n)}}publish(e,t){let n=U(e),r=this.handlers.get(n);if(r)for(let e of r)queueMicrotask(()=>{Promise.resolve(e(new Te,t)).catch(e=>{D(`SignalBus:${n}`,`handler failed`,e)})});this.relay.publish(n,t)}connectRelay(e){return this.relay.connect(e)}},ke=class{constructor(e,t,n){this.channel=e.channel,this.kind=e.kind,this.moduleId=e.moduleId,this.invoker=t,this.injector=n}async invoke(e){return R.run(this.injector,()=>this.invoker(...e))}};function Ae(e,t){t.moduleRegistry.load(e);for(let n of e){Ne(n,t);for(let e of n.providers)Fe(e,t.bridgeDispatcher),Ie(e,t.signalBus),Le(e,t.jobRegistry),ze(e,t.windowManager,t.viewManager,t.rendererRegistry)}}function G(e,t,n){t in e||Object.defineProperty(e,t,{configurable:!0,enumerable:!1,get:n})}function je(e){let t={};for(let n of c(e.target)){if(n.kind!==`command`&&n.kind!==`query`)continue;let r=Reflect.get(e.instance,n.methodName);typeof r==`function`&&(t[n.id]=r.bind(e.instance))}for(let n of e.providers)for(let r of n.definition.bridgeMethods){let i=n.getMethod(r.methodName);i&&(t[r.channel.slice(`${e.id}:`.length)]=i.bind(n.instance))}return t}function Me(e,t,n,r){let i=r.logger.child({target:x(e,t.id)});G(e,`moduleId`,()=>t.id),G(e,`api`,()=>n),G(e,`signals`,()=>r.signalBus),G(e,`jobs`,()=>r.jobRegistry),G(e,`modules`,()=>r.moduleRegistry),G(e,`windows`,()=>r.windowManager),G(e,`views`,()=>r.viewManager),G(e,`logger`,()=>i)}function Ne(e,t){let n=je(e);Me(e.instance,e,n,t);for(let r of e.providers)Me(r.instance,e,n,t)}function Pe(e,t){t(t=>e.setKernelState(t))}function Fe(e,t){for(let n of e.definition.bridgeMethods){let r=e.getMethod(n.methodName);if(!r)continue;let i=new ke(n,r.bind(e.instance),e.injector);t.registerHandler(i)}}function Ie(e,t){for(let n of e.definition.signalHandlers){let r=e.getMethod(n.methodName);if(!r)continue;let i=r.bind(e.instance);R.run(e.injector,()=>{t.subscribe(n.signalId,i)})}}function Le(e,t){for(let n of e.definition.jobs){let r=e.getMethod(n.methodName);if(!r)continue;let i=r.bind(e.instance);t.register({jobId:n.jobId,cron:n.cron,handler:i,injector:e.injector})}}function Re(e,n){return e.connectRelay((e,r)=>{let i=m(`electron`);for(let a of n.getAllSessions())a.canReceiveSignal(e)&&i.webContents.fromId(a.rendererId)?.send(t.signal,{signalId:e,payload:r})})}function ze(e,t,n,r){e.definition.kind===`window`&&t.register(e),e.definition.kind===`view`&&(n.register(e),e.definition.view&&r.registerView(e.definition.view))}var K=class e extends h{constructor(e,t,n){super(e,t,n)}static providerNotFound(t){return new e(`No provider found for "${t}".`,`ELECTRO_DI_PROVIDER_NOT_FOUND`,{token:t})}static duplicateProvider(t){return new e(`Provider "${t}" is already registered in this injector.`,`ELECTRO_DI_DUPLICATE_PROVIDER`,{token:t})}static circularDependency(t){return new e(`Circular dependency detected: ${t.join(` → `)}.`,`ELECTRO_DI_CIRCULAR_DEPENDENCY`,{path:t})}static invalidClassProvider(t){return new e(`"${t}" is not a framework-managed class. Ensure it is decorated with @Injectable(), @Module(), @View(), or @Window().`,`ELECTRO_DI_INVALID_CLASS_PROVIDER`,{token:t})}static noInjectionContext(){return new e(`inject() called outside of a framework-managed context. inject() is only available during construction (property initializers), lifecycle hooks (onInit/onStart/onReady/onShutdown/onDispose), and capability handlers (bridge, signal, job).`,`ELECTRO_DI_NO_INJECTION_CONTEXT`)}};function q(e){return p(e)?e.key:e}function Be(e){return s(e)!==void 0||l(e)!==void 0||u(e)!==void 0||d(e)!==void 0}function Ve(e){if(f(e)){let t=s(e.useClass);return{kind:`class`,provide:e.provide,useClass:e.useClass,scope:t?.scope??`singleton`}}let t=e;return{kind:`class`,provide:t,useClass:t,scope:s(t)?.scope??`singleton`}}var He=class e{constructor(e){this.parent=e,this.providers=new Map,this.instances=new Map,this.resolutionPath=[]}createChild(){return new e(this)}provide(e){let t=Ve(e),n=q(t.provide),r=o(t.provide);if(this.providers.has(n))throw K.duplicateProvider(r);this.providers.set(n,t)}provideValue(e,t){let n=q(e),r=o(e);if(this.providers.has(n))throw K.duplicateProvider(r);let i={kind:`value`,provide:e,useValue:t};this.providers.set(n,i)}has(e){let t=q(e);return this.providers.has(t)||this.parent?.has(e)===!0}get(e){let t=o(e);return this.resolve(e,t)}resolve(e,t){let n=q(e),r=this.providers.get(n);if(r)return this.resolveRecord(r,n,t);if(this.parent)return this.parent.resolve(e,t);throw K.providerNotFound(t)}resolveRecord(e,t,n){return e.kind===`value`?e.useValue:this.resolveWithPath(n,()=>e.scope===`transient`?this.instantiate(e.useClass,n):this.resolveSingleton(e,t,n))}resolveSingleton(e,t,n){let r=this.instances.get(t);if(r?.status===`resolved`)return r.value;if(r?.status===`resolving`)throw K.circularDependency([...this.resolutionPath,n]);this.instances.set(t,{status:`resolving`});try{let r=this.instantiate(e.useClass,n);return this.instances.set(t,{status:`resolved`,value:r}),r}catch(e){throw this.instances.delete(t),e}}instantiate(e,t){if(!Be(e))throw K.invalidClassProvider(t);return R.run(this,()=>new e)}resolveWithPath(e,t){if(this.resolutionPath.includes(e))throw K.circularDependency([...this.resolutionPath,e]);this.resolutionPath.push(e);try{return t()}finally{this.resolutionPath.pop()}}},J=class e extends h{constructor(e,t,n){super(e,t,n)}static rootModuleNotDecorated(t){return new e(`Class "${t}" is not decorated with @Module().`,`ELECTRO_BOOTSTRAP_ROOT_NOT_MODULE`,{className:t})}static invalidImportedModule(t,n){return new e(`Module "${t}" imports "${n}" which is not decorated with @Module().`,`ELECTRO_BOOTSTRAP_INVALID_IMPORT`,{parentModule:t,importedName:n})}static invalidModuleProvider(t,n){return new e(`Module "${t}" declares provider "${n}" which is not decorated with @Injectable().`,`ELECTRO_BOOTSTRAP_INVALID_PROVIDER`,{moduleName:t,providerName:n})}static invalidModuleView(t,n){return new e(`Module "${t}" declares view "${n}" which is not decorated with @View().`,`ELECTRO_BOOTSTRAP_INVALID_VIEW`,{moduleName:t,viewName:n})}static invalidModuleWindow(t,n){return new e(`Module "${t}" declares window "${n}" which is not decorated with @Window().`,`ELECTRO_BOOTSTRAP_INVALID_WINDOW`,{moduleName:t,windowName:n})}static circularModuleImport(t){return new e(`Circular module import detected: ${t.join(` → `)}.`,`ELECTRO_BOOTSTRAP_CIRCULAR_IMPORT`,{cycle:t})}static duplicateModuleId(t){return new e(`Duplicate module id "${t}". Module ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_MODULE_ID`,{moduleId:t})}static invalidExport(t,n){return new e(`Module "${t}" exports "${n}" which is not declared in its providers.`,`ELECTRO_BOOTSTRAP_INVALID_EXPORT`,{moduleName:t,exportName:n})}static duplicateViewId(t){return new e(`Duplicate view id "${t}". View ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_VIEW_ID`,{viewId:t})}static duplicateWindowId(t){return new e(`Duplicate window id "${t}". Window ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_WINDOW_ID`,{windowId:t})}static duplicateBridgeChannel(t){return new e(`Duplicate bridge channel "${t}". Bridge channels must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_BRIDGE_CHANNEL`,{channel:t})}static duplicateJobId(t){return new e(`Duplicate job id "${t}". Job ids must be unique.`,`ELECTRO_BOOTSTRAP_DUPLICATE_JOB_ID`,{jobId:t})}static invalidProviderRoleCombination(t){return new e(`Provider "${t}" has both @View() and @Window() — a provider can only have one role.`,`ELECTRO_BOOTSTRAP_INVALID_ROLE_COMBINATION`,{providerName:t})}static invalidViewAccessReference(t,n){return new e(`View "${t}" references bridge channel "${n}" in access, but no such channel exists.`,`ELECTRO_BOOTSTRAP_INVALID_VIEW_ACCESS`,{viewId:t,channel:n})}static invalidViewSignalReference(t,n){return new e(`View "${t}" references signal "${n}" in signals, but no such signal handler exists.`,`ELECTRO_BOOTSTRAP_INVALID_VIEW_SIGNAL`,{viewId:t,signalId:n})}static importedModuleNotLoaded(t,n){return new e(`Module "${t}" imports "${n}" which has not been loaded yet.`,`ELECTRO_BOOTSTRAP_IMPORT_NOT_LOADED`,{parentModule:t,importedModule:n})}static invalidCapabilityMethod(t,n,r){return new e(`Provider "${t}" declares ${n} method "${r}" which is not a function.`,`ELECTRO_BOOTSTRAP_INVALID_CAPABILITY_METHOD`,{providerName:t,capability:n,methodName:r})}};function Ue(e){let t=l(e);if(t?.id)return t.id;let n=e.name;return n.endsWith(`Module`)?n.slice(0,-6).toLowerCase():n.toLowerCase()}function We(e,t){return`${e}:${t.id}`}function Ge(e,t){return t.id}function Ke(e,t){return`${e}:${t.id}`}function qe(e,t,n){let r=c(t),i=[],a=[],o=[];for(let t of r)switch(t.kind){case`command`:case`query`:i.push({channel:We(e,t),kind:t.kind,moduleId:e,providerName:n,methodName:t.methodName});break;case`signal`:a.push({signalId:Ge(e,t),moduleId:e,providerName:n,methodName:t.methodName});break;case`job`:o.push({jobId:Ke(e,t),moduleId:e,providerName:n,methodName:t.methodName,cron:t.cron});break}return{bridgeMethods:i,signalHandlers:a,jobs:o}}function Je(e){let t=new Map,n=[],r=[],i=[],o=e=>{if(t.has(e))return;let c=l(e);if(!c)throw J.rootModuleNotDecorated(e.name);let f=Ue(e),p=(c.imports??[]).map(e=>a.resolve(e)),m=(c.providers??[]).map(e=>a.resolve(e)),h=(c.views??[]).map(e=>a.resolve(e)),g=(c.windows??[]).map(e=>a.resolve(e)),_=(c.exports??[]).map(e=>a.resolve(e));for(let t of p)if(!l(t))throw J.invalidImportedModule(e.name,t.name);let v=(t,n)=>{let a=s(t),o=u(t),c=d(t);if(n===`provider`&&!a)throw J.invalidModuleProvider(e.name,t.name);if(n===`view`&&!o)throw J.invalidModuleView(e.name,t.name);if(n===`window`&&!c)throw J.invalidModuleWindow(e.name,t.name);let l=o?{id:o.id,ownerModuleId:f,source:o.source,access:o.access??[],signals:o.signals??[],target:t,configuration:o.configuration}:void 0,p=c?{id:c.id,ownerModuleId:f,target:t,configuration:c.configuration}:void 0,m=qe(f,t,t.name),h={id:t.name,target:t,ownerModuleId:f,scope:a?.scope??`singleton`,kind:n,view:l,window:p,bridgeMethods:m.bridgeMethods,signalHandlers:m.signalHandlers,jobs:m.jobs};return l&&r.push(l),p&&i.push(p),h},y=[...m.map(e=>v(e,`provider`)),...h.map(e=>v(e,`view`)),...g.map(e=>v(e,`window`))];n.push(...y),t.set(e,{id:f,target:e,imports:p,providers:y,exportTargets:_});for(let e of p)o(e)};return o(e),{rootModule:e,modules:[...t.values()],providers:n,views:r,windows:i,bridgeMethods:n.flatMap(e=>e.bridgeMethods),signalHandlers:n.flatMap(e=>e.signalHandlers),jobs:n.flatMap(e=>e.jobs)}}function Ye(e){Xe(e.modules),Ze(e),Qe(e),$e(e),et(e),tt(e),nt(e),rt(e),it(e)}function Xe(e){let t=new Set;for(let n of e){if(t.has(n.id))throw J.duplicateModuleId(n.id);t.add(n.id)}}function Ze(e){for(let t of e.modules){let e=new Set(t.providers.map(e=>e.target));for(let n of t.exportTargets)if(!e.has(n))throw J.invalidExport(t.id,n.name)}}function Qe(e){let t=new Map;for(let n of e.modules)t.set(n.target,n);let n=new Set,r=new Set,i=[],a=e=>{if(n.has(e))return;let o=t.get(e);if(o){if(r.has(e))throw J.circularModuleImport([...i,o.id]);r.add(e),i.push(o.id);for(let e of o.imports)a(e);i.pop(),r.delete(e),n.add(e)}};a(e.rootModule)}function $e(e){let t=new Set;for(let n of e.views){if(t.has(n.id))throw J.duplicateViewId(n.id);t.add(n.id)}}function et(e){let t=new Set;for(let n of e.windows){if(t.has(n.id))throw J.duplicateWindowId(n.id);t.add(n.id)}}function tt(e){let t=new Set;for(let n of e.bridgeMethods){if(t.has(n.channel))throw J.duplicateBridgeChannel(n.channel);t.add(n.channel)}}function nt(e){let t=new Set;for(let n of e.jobs){if(t.has(n.jobId))throw J.duplicateJobId(n.jobId);t.add(n.jobId)}}function rt(e){for(let t of e.providers){let e=u(t.target)!==void 0,n=d(t.target)!==void 0;if(e&&n)throw J.invalidProviderRoleCombination(t.target.name)}}function it(e){let t=new Set(e.bridgeMethods.map(e=>e.channel));for(let n of e.views)for(let e of n.access)if(!t.has(e))throw J.invalidViewAccessReference(n.id,e)}const at={creating:[`ready`,`failed`],ready:[`started`,`stopped`,`failed`],started:[`stopping`,`failed`],stopping:[`stopped`,`failed`],stopped:[],failed:[]};var ot=class{constructor(e,t,n){this.definition=e,this.instance=t,this.injector=n}get id(){return this.definition.id}get target(){return this.definition.target}get ownerModuleId(){return this.definition.ownerModuleId}getMethod(e){let t=Reflect.get(this.instance,e);return typeof t==`function`?t:void 0}},st=class{constructor(e,t,n,r,i,a){this.id=e,this.target=t,this.injector=n,this.instance=r,this.providers=i,this.exportTargets=a,this.statusInternal=`creating`,this.importsInternal=[]}get status(){return this.statusInternal}get imports(){return this.importsInternal}get exportedProviders(){return this.providers.filter(e=>this.exportTargets.has(e.target))}linkImports(e){this.importsInternal=e}transitionTo(e){if(this.statusInternal!==e){if(!at[this.statusInternal].includes(e))throw I.invalidModuleTransition(this.id,this.statusInternal,e);this.statusInternal=e}}};function ct(e){let t=new Map;for(let n of e.modules)t.set(n.target,n);let n=new Set,r=[],i=e=>{if(n.has(e))return;n.add(e);let a=t.get(e);if(a){for(let e of a.imports)i(e);r.push(a)}};return i(e.rootModule),r}function lt(e,t){let n=ct(e),r=new Map;for(let e of n){let n=t.createChild(),i=e.providers;for(let t of e.imports){let i=r.get(t);if(!i)throw J.importedModuleNotLoaded(e.id,t.name);for(let e of i.exportedProviders)n.provideValue(e.target,i.injector.get(e.target))}for(let e of i)n.provide(e.target);n.provide(e.target);let a=n.get(e.target),o=i.map(e=>new ot(e,n.get(e.target),n)),s=new st(e.id,e.target,n,a,o,new Set(e.exportTargets)),c=e.imports.map(e=>r.get(e)).filter(e=>e!==void 0);s.linkImports(c),r.set(e.target,s)}return n.map(e=>r.get(e.target))}var ut=class e{constructor(e,t,n){this.definition=e,this.rootInjector=t,this.moduleRefs=n}static create(t,n){let r=Je(t);Ye(r);let i=new He;return n?.(i),new e(r,i,lt(r,i))}};function Y(e,t){return typeof e[t]==`function`}function X(e,t){let n=e.constructor?.name?.trim();return n&&n.length>0?n:t}async function dt(e,t,n){if(Y(e,t))try{await R.run(n,()=>e[t]())}catch(n){throw D(e,`${t} failed`,n),I.startupFailed(t,e.constructor.name,n)}}async function Z(e,t,n){if(Y(e,t))try{await R.run(n,()=>e[t]())}catch(n){throw D(e,`${t} failed`,n),I.startupFailed(t,e.constructor.name,n)}}async function Q(e,t,n){if(Y(e,t))try{await R.run(n,()=>e[t]())}catch(n){D(e,`${t} failed`,n)}}async function ft(e){let t=[];try{for(let n of e){let e=X(n.instance,n.id);T(e,`initializing`);for(let e of n.providers)await dt(e.instance,`onInit`,e.injector);await dt(n.instance,`onInit`,n.injector),n.transitionTo(`ready`),T(e,`initialized`),t.push(n)}}catch(n){throw gt(e),await $(t),n}}async function pt(e){let t=[];try{for(let n of e){T(X(n.instance,n.id),`starting`);for(let e of n.providers)await Z(e.instance,`onStart`,e.injector);await Z(n.instance,`onStart`,n.injector),t.push(n)}for(let t of e){for(let e of t.providers)await Z(e.instance,`onReady`,e.injector);await Z(t.instance,`onReady`,t.injector),t.transitionTo(`started`),T(X(t.instance,t.id),`started`)}}catch(n){throw gt(e),await ht(t),await $(e),n}}async function mt(e){let t=[...e].reverse();for(let e of t){T(X(e.instance,e.id),`stopping`),await Q(e.instance,`onShutdown`,e.injector);for(let t of[...e.providers].reverse())await Q(t.instance,`onShutdown`,t.injector);e.transitionTo(`stopping`)}await $(e)}async function $(e){for(let t of[...e].reverse()){let e=X(t.instance,t.id);await Q(t.instance,`onDispose`,t.injector);for(let e of[...t.providers].reverse())await Q(e.instance,`onDispose`,e.injector);t.status!==`failed`&&t.status!==`stopped`&&(t.transitionTo(`stopped`),T(e,`stopped`))}}async function ht(e){for(let t of[...e].reverse()){await Q(t.instance,`onShutdown`,t.injector);for(let e of[...t.providers].reverse())await Q(e.instance,`onShutdown`,e.injector)}}function gt(e){for(let t of e)if(!(t.status===`stopped`||t.status===`failed`))try{t.transitionTo(`failed`),T(X(t.instance,t.id),`failed`,`error`)}catch{}}const _t={idle:[`initializing`],initializing:[`initialized`,`failed`],initialized:[`starting`,`stopping`],starting:[`started`,`failed`],started:[`stopping`],stopping:[`stopped`,`failed`],stopped:[],failed:[]};var vt=class e{constructor(e,t={}){this.state=`idle`,this.stateListeners=[],this.disposers=[],this.rootModule=e,this.logger=t.logger??C()}static create(t,n={}){return new e(t,n)}async initialize(){if(this.state===`initialized`||this.state===`starting`||this.state===`started`)return;if(this.initializeTask)return this.initializeTask;if(this.state!==`idle`)throw I.invalidKernelTransition(this.state,`initializing`);let e=this.performInitialize();this.initializeTask=e;try{await e}finally{this.initializeTask===e&&(this.initializeTask=void 0)}}async start(){if(this.state===`started`)return;if(this.startTask)return this.startTask;let e=this.performStart();this.startTask=e;try{await e}finally{this.startTask===e&&(this.startTask=void 0)}}async shutdown(){if(this.state===`idle`||this.state===`stopped`||this.state===`failed`)return;if(this.shutdownTask)return this.shutdownTask;let e=this.performShutdown();this.shutdownTask=e;try{await e}finally{this.shutdownTask===e&&(this.shutdownTask=void 0)}}getState(){return this.state}isStarted(){return this.state===`started`}getDefinition(){return this.composition?.definition}getModuleRefs(){return this.composition?.moduleRefs??[]}onStateChange(e){this.stateListeners.push(e)}async performInitialize(){w(this.logger),this.transitionTo(`initializing`);try{this.composition=ut.create(this.rootModule,e=>this.registerFrameworkServices(e)),Ae(this.composition.moduleRefs,this.services),Pe(this.services.bridgeAccessGuard,e=>this.onStateChange(e)),this.disposers.push(ee(this.services.bridgeDispatcher,this.services.rendererRegistry)),this.disposers.push(Re(this.services.signalBus,this.services.rendererRegistry)),await ft(this.composition.moduleRefs),this.transitionTo(`initialized`)}catch(e){throw this.transitionTo(`failed`),await this.safeDisposeServices(),w(void 0),e}}async performStart(){if(this.initializeTask?await this.initializeTask:this.state===`idle`&&await this.initialize(),this.state!==`started`){if(this.state!==`initialized`)throw I.invalidKernelTransition(this.state,`starting`);try{this.transitionTo(`starting`),await pt(this.composition.moduleRefs),this.transitionTo(`started`)}catch(e){throw this.transitionTo(`failed`),await this.safeDisposeServices(),w(void 0),e}}}async performShutdown(){if(this.startTask)try{await this.startTask}catch{return}else if(this.initializeTask)try{await this.initializeTask}catch{return}if(!(this.state===`idle`||this.state===`stopped`||this.state===`failed`)){if(this.state!==`initialized`&&this.state!==`started`)throw I.kernelNotStarted();this.transitionTo(`stopping`);try{this.composition&&(this.getPreviousRunningState()===`started`?await mt(this.composition.moduleRefs):await $(this.composition.moduleRefs)),await this.disposeServices(),this.transitionTo(`stopped`)}catch(e){throw this.transitionTo(`failed`),e}finally{w(void 0)}}}getPreviousRunningState(){return this.composition?.moduleRefs.some(e=>e.status===`started`)?`started`:`initialized`}registerFrameworkServices(e){let t=new W,n=new B,r=new V,i=new b,a=new _,o=new y(i,a),s=new F,c=new j;e.provideValue(W,t),e.provideValue(B,n),e.provideValue(V,r),e.provideValue(b,i),e.provideValue(y,o),e.provideValue(_,a),e.provideValue(F,s),e.provideValue(j,c),this.services={signalBus:t,jobRegistry:n,moduleRegistry:r,bridgeDispatcher:o,bridgeAccessGuard:a,windowManager:s,viewManager:c,rendererRegistry:i,logger:this.logger}}async disposeServices(){for(let e of this.disposers)e();this.disposers.length=0,await this.services?.jobRegistry.dispose(),await this.services?.windowManager.dispose(),await this.services?.viewManager.dispose()}transitionTo(e){if(!_t[this.state].includes(e))throw I.invalidKernelTransition(this.state,e);this.state=e,T(`AppKernel`,e);for(let t of this.stateListeners)t(e)}async safeDisposeServices(){try{await this.disposeServices()}catch{}}};function yt(e){let t=R.current();if(!t)throw K.noInjectionContext();return t.get(e)}export{vt as AppKernel,J as BootstrapError,_ as BridgeAccessGuard,y as BridgeDispatcher,g as BridgeError,ke as BridgeHandler,K as DIError,t as IPC_CHANNELS,R as InjectionContext,He as Injector,xe as JobContext,z as JobError,B as JobRegistry,I as LifecycleError,st as ModuleRef,V as ModuleRegistry,ot as ProviderRef,b as RendererRegistry,te as RendererSession,h as RuntimeError,W as SignalBus,Te as SignalContext,H as SignalError,j as ViewManager,A as ViewProvider,F as WindowManager,P as WindowProvider,e as createBridgeClient,C as createConsoleLogger,yt as inject,Je as scanModules,v as serializeBridgeError,Ye as validateAppDefinition};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electrojs/runtime",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
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.7",
53
- "@electrojs/config": "1.0.7"
52
+ "@electrojs/common": "1.0.8",
53
+ "@electrojs/config": "1.0.8"
54
54
  },
55
55
  "peerDependencies": {
56
- "@electrojs/common": "1.0.7",
57
- "@electrojs/config": "1.0.7",
56
+ "@electrojs/common": "1.0.8",
57
+ "@electrojs/config": "1.0.8",
58
58
  "@types/node": "^25.5.0",
59
59
  "electron": ">=41"
60
60
  },