@zeltjs/adapter-electron 0.9.1-canary.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  [![Documentation](https://img.shields.io/badge/docs-zeltjs.com-blue)](https://zeltjs.com)
4
4
 
5
- Electron adapter for Zelt applications.
5
+ Electron adapter for Zelt applications. Your Zelt app runs in the main process; the renderer calls it over IPC with the standard Fetch API shape.
6
6
 
7
- **[Read the Documentation](https://zeltjs.com)**
7
+ **[Read the Documentation](https://zeltjs.com/docs/getting-started/electron)**
8
8
 
9
9
  ## Installation
10
10
 
@@ -14,8 +14,10 @@ npm install @zeltjs/adapter-electron @zeltjs/core
14
14
 
15
15
  ## Usage
16
16
 
17
+ ### Main process
18
+
17
19
  ```typescript
18
- import { createApp, Controller, Get } from '@zeltjs/core';
20
+ import { createApp, http, Controller, Get } from '@zeltjs/core';
19
21
  import { onElectron } from '@zeltjs/adapter-electron';
20
22
 
21
23
  @Controller('/api')
@@ -26,9 +28,61 @@ class ApiController {
26
28
  }
27
29
  }
28
30
 
29
- const app = createApp({
30
- http: { controllers: [ApiController] },
31
+ const app = createApp([http({ controllers: [ApiController] })]);
32
+
33
+ const electronZelt = await onElectron(app, { ipcChannel: 'http://zelt-app' });
34
+ ```
35
+
36
+ ### Preload script
37
+
38
+ ```typescript
39
+ import { exposeIpc } from '@zeltjs/adapter-electron/preload';
40
+
41
+ exposeIpc({ channel: 'http://zelt-app' });
42
+ ```
43
+
44
+ ### Renderer
45
+
46
+ ```typescript
47
+ import { ipcFetch } from '@zeltjs/adapter-electron/renderer';
48
+
49
+ const response = await ipcFetch('http://zelt-app/api/status', undefined, {
50
+ channel: 'http://zelt-app',
31
51
  });
52
+ const data = await response.json();
53
+ ```
54
+
55
+ The channel string must match across all three layers.
56
+
57
+ ### Multiple HTTP features
32
58
 
33
- const electron = await onElectron(app);
59
+ Configure additional named `http()` features alongside the renderer-facing one:
60
+
61
+ ```typescript
62
+ const app = createApp([
63
+ http({ controllers: [ApiController] }),
64
+ http({ name: 'mcp', controllers: [McpController] }),
65
+ ]);
66
+
67
+ const electronZelt = await onElectron(app);
68
+ ```
69
+
70
+ By default the `http` feature is bound to the IPC bridge; pass `ipcFeature` to bind a different one instead:
71
+
72
+ ```typescript
73
+ const electronZelt = await onElectron(app, { ipcFeature: 'mcp' });
34
74
  ```
75
+
76
+ Any other feature can be served over TCP instead of IPC — handy for exposing an MCP server or other external API from the same runtime and shared services, keeping only the router and trust boundary separate from the renderer-facing API:
77
+
78
+ ```typescript
79
+ await electronZelt.mcp.listen({ port: 8765, hostname: '127.0.0.1' });
80
+ ```
81
+
82
+ Breaking change: the old `electronZelt.fetch` shorthand is gone — use `electronZelt.http.fetch` instead.
83
+
84
+ ## Learn More
85
+
86
+ - [Getting Started with Electron](https://zeltjs.com/docs/getting-started/electron) — full walkthrough with electron-vite
87
+ - [IPC Bridge](https://zeltjs.com/docs/electron/ipc-bridge) — channel configuration, `ipcEvent()` access to the underlying `IpcMainInvokeEvent`, type-safe clients with `@zeltjs/hono-client`, shutdown wiring
88
+ - [Window Management](https://zeltjs.com/docs/electron/window-management) — managing BrowserWindows through Zelt DI
@@ -1,6 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let _zeltjs_core = require("@zeltjs/core");
3
3
  let ts_pattern = require("ts-pattern");
4
+ let _zeltjs_adapter_node = require("@zeltjs/adapter-node");
4
5
  //#region src/main/electron.adaptor.ts
5
6
  function _ts_decorate$3(decorators, target, key, desc) {
6
7
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -218,26 +219,68 @@ const toIpcResponse = async (response, method) => {
218
219
  };
219
220
  };
220
221
  //#endregion
222
+ //#region src/main/on-electron.exceptions.ts
223
+ /** No HttpFeature matches the `ipcFeature` key requested for IPC binding. */ var ZeltElectronIpcFeatureNotFoundError = class extends Error {
224
+ constructor(context) {
225
+ super(`No HttpFeature registered with key "${context.ipcFeature}" to bind to the IPC bridge`), this.name = "ZeltElectronIpcFeatureNotFoundError";
226
+ this.context = context;
227
+ Object.setPrototypeOf(this, new.target.prototype);
228
+ }
229
+ };
230
+ //#endregion
221
231
  //#region src/main/on-electron.ts
222
232
  const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
223
- /** @throws {ZeltContextNotAvailableError} */ const onElectron = async (app, options = {}) => {
233
+ /** @throws {AggregateError} */ const withCleanupOnError = async (cleanup, body) => {
234
+ try {
235
+ return await body();
236
+ } catch (error) {
237
+ try {
238
+ await cleanup();
239
+ } catch (cleanupError) {
240
+ throw new AggregateError([error, cleanupError], "onElectron setup failed and runtime shutdown also failed");
241
+ }
242
+ throw error;
243
+ }
244
+ };
245
+ const createElectronApp = (readyApp, shutdown) => {
246
+ const electronApp = {
247
+ ...readyApp,
248
+ shutdown
249
+ };
250
+ for (const entry of readyApp.getFeatureEntries(_zeltjs_core.HttpFeature)) Object.defineProperty(electronApp, entry.key, {
251
+ value: {
252
+ ...entry.capabilities,
253
+ listen: (0, _zeltjs_adapter_node.createListenForHttp)(entry.capabilities.fetch, (callback) => entry.feature.registerShutdown(callback))
254
+ },
255
+ configurable: true,
256
+ enumerable: true
257
+ });
258
+ return electronApp;
259
+ };
260
+ /** @throws {ZeltContextNotAvailableError | ZeltElectronIpcFeatureNotFoundError | AggregateError} */ async function onElectron(app, options = {}) {
224
261
  const readyApp = await app.createRuntime({
225
262
  ...options.configs === void 0 ? {} : { configs: options.configs },
226
263
  fallbackConfigs: [ElectronEnvAdaptor],
227
264
  warmup: options.warmup ?? true
228
265
  });
229
- const electronApp = await readyApp.get(ElectronAdaptor);
230
- const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
231
- const removeIpcHandler = setupIpcBridge(electronApp.ready.ipcMain, readyApp.http.fetch, channel);
232
- return {
233
- get: readyApp.get,
234
- fetch: readyApp.http.fetch,
235
- shutdown: async () => {
236
- removeIpcHandler();
266
+ let removeIpcHandler;
267
+ return withCleanupOnError(async () => {
268
+ removeIpcHandler?.();
269
+ await readyApp.shutdown();
270
+ }, async () => {
271
+ const ipcFeature = options.ipcFeature ?? _zeltjs_core.HTTP_FEATURE_KEY;
272
+ const ipcEntry = readyApp.getFeatureEntries(_zeltjs_core.HttpFeature).find((entry) => entry.key === ipcFeature);
273
+ if (ipcEntry === void 0) throw new ZeltElectronIpcFeatureNotFoundError({ ipcFeature });
274
+ const electronAdaptor = await readyApp.get(ElectronAdaptor);
275
+ const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
276
+ removeIpcHandler = setupIpcBridge(electronAdaptor.ready.ipcMain, ipcEntry.capabilities.fetch, channel);
277
+ const shutdown = async () => {
278
+ removeIpcHandler?.();
237
279
  await readyApp.shutdown();
238
- }
239
- };
240
- };
280
+ };
281
+ return createElectronApp(readyApp, shutdown);
282
+ });
283
+ }
241
284
  //#endregion
242
285
  Object.defineProperty(exports, "ElectronAdaptor", {
243
286
  enumerable: true,
@@ -263,6 +306,7 @@ Object.defineProperty(exports, "ElectronWindowRuntimeService", {
263
306
  return ElectronWindowRuntimeService;
264
307
  }
265
308
  });
309
+ exports.ZeltElectronIpcFeatureNotFoundError = ZeltElectronIpcFeatureNotFoundError;
266
310
  exports.ipcEvent = ipcEvent;
267
311
  exports.onElectron = onElectron;
268
312
  exports.setupIpcBridge = setupIpcBridge;
@@ -1,6 +1,7 @@
1
1
  import { n as IpcFetchResponse, t as IpcFetchRequest } from "../ipc.types-DgxeccV3.cjs";
2
- import { ConfigClass, ConfiguredFeature, CreateRuntimeOptions, EnvAdaptor, HttpCapabilities, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
2
+ import { ConfigClass, ConfiguredFeature, EnvAdaptor, FeatureApp, FeatureReadyCapabilities, HttpFeature, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
3
3
  import { App, BrowserWindow, BrowserWindowConstructorOptions, Dialog, IpcMain, IpcMainInvokeEvent, Menu, Protocol, Rectangle, Screen, Shell, WebContents } from "electron";
4
+ import { ListenOptions, ServerHandle } from "@zeltjs/adapter-node";
4
5
 
5
6
  //#region src/main/electron.adaptor.d.ts
6
7
  type ElectronReady = {
@@ -107,26 +108,37 @@ declare const ipcEvent: () => IpcMainInvokeEvent | undefined;
107
108
  /** @throws {ZeltContextNotAvailableError} */
108
109
  declare const setupIpcBridge: (ipcMain: IpcMainLike, fetch: (request: Request) => Promise<Response>, channel: string) => (() => void);
109
110
  //#endregion
111
+ //#region src/main/on-electron.exceptions.d.ts
112
+ type ZeltElectronIpcFeatureNotFoundContext = {
113
+ readonly ipcFeature: string;
114
+ };
115
+ /** No HttpFeature matches the `ipcFeature` key requested for IPC binding. */
116
+ declare class ZeltElectronIpcFeatureNotFoundError extends Error {
117
+ readonly name = "ZeltElectronIpcFeatureNotFoundError";
118
+ readonly context: ZeltElectronIpcFeatureNotFoundContext;
119
+ constructor(context: ZeltElectronIpcFeatureNotFoundContext);
120
+ }
121
+ //#endregion
110
122
  //#region src/main/on-electron.d.ts
111
123
  type IpcChannel = `http://${string}` | `https://${string}`;
112
- type ElectronAppOptions = {
124
+ type ElectronAppOptions<TIpcFeature extends string = string> = {
113
125
  readonly configs?: readonly ConfigClass<object>[];
114
126
  readonly warmup?: boolean;
115
127
  readonly ipcChannel?: IpcChannel;
128
+ readonly ipcFeature?: TIpcFeature;
116
129
  };
117
- type HttpRuntimeApp = RuntimeApp<readonly ConfiguredFeature[]> & {
118
- readonly http: HttpCapabilities;
119
- };
120
- type HttpApp = {
121
- readonly createRuntime: (options?: CreateRuntimeOptions) => Promise<HttpRuntimeApp>;
122
- };
123
- type OnElectronApp = {
124
- readonly get: HttpRuntimeApp['get'];
125
- readonly fetch: (request: Request) => Promise<Response>;
130
+ type HttpFeatureKeys<F extends readonly ConfiguredFeature[]> = Extract<F[number], HttpFeature<string>>['key'];
131
+ type EnvironmentElectronAppPart = {
126
132
  readonly shutdown: () => Promise<void>;
127
133
  };
128
- /** @throws {ZeltContextNotAvailableError} */
129
- declare const onElectron: (app: HttpApp, options?: ElectronAppOptions) => Promise<OnElectronApp>;
134
+ type HttpElectronAppPart = {
135
+ readonly listen: (portOrOptions?: number | ListenOptions) => Promise<ServerHandle>;
136
+ };
137
+ type ElectronFeatureCapabilities<TFeature extends ConfiguredFeature> = FeatureReadyCapabilities<TFeature> & (TFeature extends HttpFeature<string> ? HttpElectronAppPart : unknown);
138
+ type ElectronNamespacedCapabilities<F extends readonly ConfiguredFeature[]> = { readonly [TFeature in F[number] as TFeature['key']]: ElectronFeatureCapabilities<TFeature> };
139
+ type OnElectronApp = RuntimeApp<readonly ConfiguredFeature[]> & EnvironmentElectronAppPart;
140
+ type ElectronAppForFeatures<F extends readonly ConfiguredFeature[]> = RuntimeApp<F> & EnvironmentElectronAppPart & ElectronNamespacedCapabilities<F>;
141
+ declare function onElectron<const F extends readonly ConfiguredFeature[]>(app: FeatureApp<F>, options?: ElectronAppOptions<HttpFeatureKeys<F>>): Promise<ElectronAppForFeatures<F>>;
130
142
  //#endregion
131
- export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
143
+ export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, ZeltElectronIpcFeatureNotFoundError, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
132
144
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/window.types.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.ts"],"mappings":";;;;;KAeY,aAAA;EAAA,SACD,GAAA,EAAK,GAAA;EAAA,SACL,OAAA,EAAS,OAAA;EAAA,SACT,QAAA,EAAU,QAAA;EAAA,SACV,KAAA,EAAO,KAAA;EAAA,SACP,MAAA,EAAQ,MAAA;EAAA,SACR,MAAA,EAAQ,MAAA;EAAA,SACR,IAAA,SAAa,IAAA;EAAA,SACb,mBAAA,GAAsB,OAAA,EAAS,+BAAA,KAAoC,aAAA;EAAA,SACnE,aAAA,QAAqB,aAAA;EAAA,SACrB,eAAA,GAAkB,WAAA,EAAa,WAAA,KAAgB,aAAA;EAAA,SAC/C,MAAA,GAAS,EAAA,aAAe,aAAA;EAAA,SACxB,gBAAA,QAAwB,aAAA;AAAA;AAAA,cAItB,eAAA,YAA2B,SAAA,CAAU,aAAA;EAAA,SACvC,KAAA,EAAO,UAAA,CAAW,aAAA;cAEf,gBAAA,GAAgB,gBAAA;EAItB,OAAA,CAAA,GAAW,OAAA,CAAQ,aAAA;EA8BzB,QAAA,CAAA;AAAA;;;cCjEW,kBAAA,SAA2B,UAAA;EAC7B,GAAA,CAAI,GAAA;AAAA;;;KCFH,QAAA;AAAA,KAEA,uBAAA;EAAA,SAAqC,MAAA;AAAA;AAAA,KAErC,YAAA;EAAA,SACD,EAAA;EAAA,SACA,MAAA,EAAQ,aAAA;EACjB,KAAA;EACA,KAAA;EACA,IAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA,IAAa,SAAA;EACb,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,SAAA;EAC1B,QAAA,CAAS,IAAA;EACT,OAAA,CAAQ,GAAA;EACR,EAAA,CAAG,KAAA,8BAAmC,OAAA;EACtC,cAAA,CAAe,KAAA,8BAAmC,OAAA,MAAa,IAAA;EAC/D,WAAA;IACE,IAAA,CAAK,OAAA,aAAoB,IAAA;IACzB,oBAAA,CAAqB,OAAA,GAAU,OAAA;MAAW,GAAA;IAAA,MAAkB,uBAAA;EAAA;AAAA;AAAA,KAIpD,gBAAA;EACN,IAAA;EAAA,SAAuB,IAAA;AAAA;EACvB,IAAA;EAAA,SAAsB,GAAA;AAAA;AAAA,KAEhB,gBAAA;EAAA,SACD,EAAA,EAAI,QAAA;EAAA,SACJ,OAAA,EAAS,+BAAA;EAAA,SACT,UAAA,EAAY,gBAAA;AAAA;AAAA,KAGX,aAAA;EACV,IAAA,CAAK,UAAA,EAAY,gBAAA,GAAmB,YAAA;AAAA;;;cC9BzB,4BAAA,YAAwC,aAAA;EAAA,iBACtB,WAAA;cAAA,WAAA,GAAa,eAAA;EAE1C,IAAA,CAAK,UAAA,EAAY,gBAAA,GAAmB,YAAA;EAcpC,kBAAA,CAAmB,GAAA,EAAK,aAAA,GAAgB,YAAA;AAAA;;;cCnB7B,6BAAA;EAAA,iBAGkB,OAAA;EAAA,iBAFZ,OAAA;cAEY,OAAA,GAAO,4BAAA;EAEpC,IAAA,CAAK,UAAA,EAAY,gBAAA,GAAmB,YAAA;EAiBpC,KAAA,CAAM,EAAA,EAAI,QAAA;EAOV,QAAA,CAAA;EAQA,KAAA,CAAA;AAAA;;;cChBW,SAAA,GAAa,OAAA,EAAS,eAAA,EAAiB,OAAA,aAAkB,OAAA;AAAA,cASzD,aAAA,GACX,QAAA,EAAU,QAAA,EACV,MAAA,aACC,OAAA,CAAQ,gBAAA;AAAA;EAAA,UA2BC,oBAAA;IACR,QAAA,EAAU,kBAAA;EAAA;AAAA;AAAA,KAIT,WAAA;EACH,MAAA,CACE,OAAA,UACA,QAAA,GAAW,KAAA,EAAO,kBAAA,EAAoB,OAAA,EAAS,eAAA;EAEjD,aAAA,CAAc,OAAA;AAAA;;cAIH,QAAA,QAAe,kBAAA;;cAGf,cAAA,GACX,OAAA,EAAS,WAAA,EACT,KAAA,GAAQ,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA,GACrC,OAAA;;;KC1EG,UAAA;AAAA,KAEO,kBAAA;EAAA,SACD,OAAA,YAAmB,WAAA;EAAA,SACnB,MAAA;EAAA,SACA,UAAA,GAAa,UAAA;AAAA;AAAA,KAGnB,cAAA,GAAiB,UAAA,UAAoB,iBAAA;EAAA,SAC/B,IAAA,EAAM,gBAAA;AAAA;AAAA,KAGZ,OAAA;EAAA,SACM,aAAA,GAAgB,OAAA,GAAU,oBAAA,KAAyB,OAAA,CAAQ,cAAA;AAAA;AAAA,KAG1D,aAAA;EAAA,SACD,GAAA,EAAK,cAAA;EAAA,SACL,KAAA,GAAQ,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA;EAAA,SACrC,QAAA,QAAgB,OAAA;AAAA;;cAMd,UAAA,GACX,GAAA,EAAK,OAAA,EACL,OAAA,GAAS,kBAAA,KACR,OAAA,CAAQ,aAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/window.types.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.exceptions.ts","../../src/main/on-electron.ts"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { n as IpcFetchResponse, t as IpcFetchRequest } from "../ipc.types-OYZhXKH2.js";
2
- import { ConfigClass, ConfiguredFeature, CreateRuntimeOptions, EnvAdaptor, HttpCapabilities, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
2
+ import { ConfigClass, ConfiguredFeature, EnvAdaptor, FeatureApp, FeatureReadyCapabilities, HttpFeature, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
3
+ import { ListenOptions, ServerHandle } from "@zeltjs/adapter-node";
3
4
  import { App, BrowserWindow, BrowserWindowConstructorOptions, Dialog, IpcMain, IpcMainInvokeEvent, Menu, Protocol, Rectangle, Screen, Shell, WebContents } from "electron";
4
5
 
5
6
  //#region src/main/electron.adaptor.d.ts
@@ -107,26 +108,37 @@ declare const ipcEvent: () => IpcMainInvokeEvent | undefined;
107
108
  /** @throws {ZeltContextNotAvailableError} */
108
109
  declare const setupIpcBridge: (ipcMain: IpcMainLike, fetch: (request: Request) => Promise<Response>, channel: string) => (() => void);
109
110
  //#endregion
111
+ //#region src/main/on-electron.exceptions.d.ts
112
+ type ZeltElectronIpcFeatureNotFoundContext = {
113
+ readonly ipcFeature: string;
114
+ };
115
+ /** No HttpFeature matches the `ipcFeature` key requested for IPC binding. */
116
+ declare class ZeltElectronIpcFeatureNotFoundError extends Error {
117
+ readonly name = "ZeltElectronIpcFeatureNotFoundError";
118
+ readonly context: ZeltElectronIpcFeatureNotFoundContext;
119
+ constructor(context: ZeltElectronIpcFeatureNotFoundContext);
120
+ }
121
+ //#endregion
110
122
  //#region src/main/on-electron.d.ts
111
123
  type IpcChannel = `http://${string}` | `https://${string}`;
112
- type ElectronAppOptions = {
124
+ type ElectronAppOptions<TIpcFeature extends string = string> = {
113
125
  readonly configs?: readonly ConfigClass<object>[];
114
126
  readonly warmup?: boolean;
115
127
  readonly ipcChannel?: IpcChannel;
128
+ readonly ipcFeature?: TIpcFeature;
116
129
  };
117
- type HttpRuntimeApp = RuntimeApp<readonly ConfiguredFeature[]> & {
118
- readonly http: HttpCapabilities;
119
- };
120
- type HttpApp = {
121
- readonly createRuntime: (options?: CreateRuntimeOptions) => Promise<HttpRuntimeApp>;
122
- };
123
- type OnElectronApp = {
124
- readonly get: HttpRuntimeApp['get'];
125
- readonly fetch: (request: Request) => Promise<Response>;
130
+ type HttpFeatureKeys<F extends readonly ConfiguredFeature[]> = Extract<F[number], HttpFeature<string>>['key'];
131
+ type EnvironmentElectronAppPart = {
126
132
  readonly shutdown: () => Promise<void>;
127
133
  };
128
- /** @throws {ZeltContextNotAvailableError} */
129
- declare const onElectron: (app: HttpApp, options?: ElectronAppOptions) => Promise<OnElectronApp>;
134
+ type HttpElectronAppPart = {
135
+ readonly listen: (portOrOptions?: number | ListenOptions) => Promise<ServerHandle>;
136
+ };
137
+ type ElectronFeatureCapabilities<TFeature1 extends ConfiguredFeature> = FeatureReadyCapabilities<TFeature1> & (TFeature1 extends HttpFeature<string> ? HttpElectronAppPart : unknown);
138
+ type ElectronNamespacedCapabilities<F extends readonly ConfiguredFeature[]> = { readonly [TFeature in F[number] as TFeature['key']]: ElectronFeatureCapabilities<TFeature> };
139
+ type OnElectronApp = RuntimeApp<readonly ConfiguredFeature[]> & EnvironmentElectronAppPart;
140
+ type ElectronAppForFeatures<F extends readonly ConfiguredFeature[]> = RuntimeApp<F> & EnvironmentElectronAppPart & ElectronNamespacedCapabilities<F>;
141
+ declare function onElectron<const F extends readonly ConfiguredFeature[]>(app: FeatureApp<F>, options?: ElectronAppOptions<HttpFeatureKeys<F>>): Promise<ElectronAppForFeatures<F>>;
130
142
  //#endregion
131
- export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
143
+ export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, ZeltElectronIpcFeatureNotFoundError, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
132
144
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/window.types.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/window.types.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.exceptions.ts","../../src/main/on-electron.ts"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { Config, EnvAdaptor, Injectable, LifecycleManager, getContext, inject, runInContext, setContext } from "@zeltjs/core";
1
+ import { Config, EnvAdaptor, HTTP_FEATURE_KEY, HttpFeature, Injectable, LifecycleManager, getContext, inject, runInContext, setContext } from "@zeltjs/core";
2
2
  import { match } from "ts-pattern";
3
+ import { createListenForHttp } from "@zeltjs/adapter-node";
3
4
  //#region src/main/electron.adaptor.ts
4
5
  function _ts_decorate$3(decorators, target, key, desc) {
5
6
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -217,27 +218,69 @@ const toIpcResponse = async (response, method) => {
217
218
  };
218
219
  };
219
220
  //#endregion
221
+ //#region src/main/on-electron.exceptions.ts
222
+ /** No HttpFeature matches the `ipcFeature` key requested for IPC binding. */ var ZeltElectronIpcFeatureNotFoundError = class extends Error {
223
+ constructor(context) {
224
+ super(`No HttpFeature registered with key "${context.ipcFeature}" to bind to the IPC bridge`), this.name = "ZeltElectronIpcFeatureNotFoundError";
225
+ this.context = context;
226
+ Object.setPrototypeOf(this, new.target.prototype);
227
+ }
228
+ };
229
+ //#endregion
220
230
  //#region src/main/on-electron.ts
221
231
  const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
222
- /** @throws {ZeltContextNotAvailableError} */ const onElectron = async (app, options = {}) => {
232
+ /** @throws {AggregateError} */ const withCleanupOnError = async (cleanup, body) => {
233
+ try {
234
+ return await body();
235
+ } catch (error) {
236
+ try {
237
+ await cleanup();
238
+ } catch (cleanupError) {
239
+ throw new AggregateError([error, cleanupError], "onElectron setup failed and runtime shutdown also failed");
240
+ }
241
+ throw error;
242
+ }
243
+ };
244
+ const createElectronApp = (readyApp, shutdown) => {
245
+ const electronApp = {
246
+ ...readyApp,
247
+ shutdown
248
+ };
249
+ for (const entry of readyApp.getFeatureEntries(HttpFeature)) Object.defineProperty(electronApp, entry.key, {
250
+ value: {
251
+ ...entry.capabilities,
252
+ listen: createListenForHttp(entry.capabilities.fetch, (callback) => entry.feature.registerShutdown(callback))
253
+ },
254
+ configurable: true,
255
+ enumerable: true
256
+ });
257
+ return electronApp;
258
+ };
259
+ /** @throws {ZeltContextNotAvailableError | ZeltElectronIpcFeatureNotFoundError | AggregateError} */ async function onElectron(app, options = {}) {
223
260
  const readyApp = await app.createRuntime({
224
261
  ...options.configs === void 0 ? {} : { configs: options.configs },
225
262
  fallbackConfigs: [ElectronEnvAdaptor],
226
263
  warmup: options.warmup ?? true
227
264
  });
228
- const electronApp = await readyApp.get(ElectronAdaptor);
229
- const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
230
- const removeIpcHandler = setupIpcBridge(electronApp.ready.ipcMain, readyApp.http.fetch, channel);
231
- return {
232
- get: readyApp.get,
233
- fetch: readyApp.http.fetch,
234
- shutdown: async () => {
235
- removeIpcHandler();
265
+ let removeIpcHandler;
266
+ return withCleanupOnError(async () => {
267
+ removeIpcHandler?.();
268
+ await readyApp.shutdown();
269
+ }, async () => {
270
+ const ipcFeature = options.ipcFeature ?? HTTP_FEATURE_KEY;
271
+ const ipcEntry = readyApp.getFeatureEntries(HttpFeature).find((entry) => entry.key === ipcFeature);
272
+ if (ipcEntry === void 0) throw new ZeltElectronIpcFeatureNotFoundError({ ipcFeature });
273
+ const electronAdaptor = await readyApp.get(ElectronAdaptor);
274
+ const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
275
+ removeIpcHandler = setupIpcBridge(electronAdaptor.ready.ipcMain, ipcEntry.capabilities.fetch, channel);
276
+ const shutdown = async () => {
277
+ removeIpcHandler?.();
236
278
  await readyApp.shutdown();
237
- }
238
- };
239
- };
279
+ };
280
+ return createElectronApp(readyApp, shutdown);
281
+ });
282
+ }
240
283
  //#endregion
241
- export { ElectronAdaptor, ElectronEnvAdaptor, ElectronWindowRegistryService, ElectronWindowRuntimeService, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
284
+ export { ElectronAdaptor, ElectronEnvAdaptor, ElectronWindowRegistryService, ElectronWindowRuntimeService, ZeltElectronIpcFeatureNotFoundError, ipcEvent, onElectron, setupIpcBridge, toIpcResponse, toRequest };
242
285
 
243
286
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Injectable","inject","LifecycleManager","ElectronAdaptor","startup","app","BrowserWindow","BW","dialog","ipcMain","Menu","protocol","screen","shell","whenReady","createBrowserWindow","options","getAllWindows","fromWebContents","wc","fromId","id","getFocusedWindow","shutdown","ready","quit","lifecycleManager","register","Config","EnvAdaptor","ElectronEnvAdaptor","get","key","process","env","Injectable","inject","match","ElectronAdaptor","ElectronWindowRuntimeService","open","definition","handle","createWindowHandle","electronApp","ready","createBrowserWindow","options","loadTarget","type","loadURL","url","loadFile","path","win","id","native","close","focus","show","isDestroyed","getTitle","getBounds","setBounds","bounds","on","event","handler","with","e","exhaustive","removeListener","webContents","send","channel","args","setWindowOpenHandler","Injectable","inject","ElectronWindowRuntimeService","ElectronWindowRegistryService","open","definition","existing","windows","get","id","isDestroyed","focus","handle","runtime","set","on","delete","close","closeAll","values","count","size","Map","getContext","runInContext","setContext","match","BODY_FORBIDDEN_METHODS","Set","NO_BODY_STATUSES","TEXT_CONTENT_TYPE_PREFIXES","isTextContentType","contentType","some","prefix","startsWith","toBody","body","with","kind","value","exhaustive","toRequest","payload","baseUrl","headers","map","k","v","Request","replace","path","method","has","toIpcResponse","response","forEach","key","push","status","get","text","arrayBuffer","statusText","ipcEvent","setupIpcBridge","ipcMain","fetch","channel","handle","event","request","removeHandler","ElectronAdaptor","ElectronEnvAdaptor","setupIpcBridge","DEFAULT_IPC_CHANNEL","onElectron","app","options","readyApp","createRuntime","configs","undefined","fallbackConfigs","warmup","electronApp","get","channel","ipcChannel","removeIpcHandler","ready","ipcMain","http","fetch","shutdown"],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.ts"],"sourcesContent":["import type { Lifecycle, ReadyValue } from '@zeltjs/core';\nimport { Injectable, inject, LifecycleManager } from '@zeltjs/core';\nimport type {\n App,\n BrowserWindow,\n BrowserWindowConstructorOptions,\n Dialog,\n IpcMain,\n Menu,\n Protocol,\n Screen,\n Shell,\n WebContents,\n} from 'electron';\n\nexport type ElectronReady = {\n readonly app: App;\n readonly ipcMain: IpcMain;\n readonly protocol: Protocol;\n readonly shell: Shell;\n readonly screen: Screen;\n readonly dialog: Dialog;\n readonly Menu: typeof Menu;\n readonly createBrowserWindow: (options: BrowserWindowConstructorOptions) => BrowserWindow;\n readonly getAllWindows: () => BrowserWindow[];\n readonly fromWebContents: (webContents: WebContents) => BrowserWindow | null;\n readonly fromId: (id: number) => BrowserWindow | null;\n readonly getFocusedWindow: () => BrowserWindow | null;\n};\n\n@Injectable()\nexport class ElectronAdaptor implements Lifecycle<ElectronReady> {\n readonly ready: ReadyValue<ElectronReady>;\n\n constructor(lifecycleManager = inject(LifecycleManager)) {\n this.ready = lifecycleManager.register(this);\n }\n\n async startup(): Promise<ElectronReady> {\n const {\n app,\n BrowserWindow: BW,\n dialog,\n ipcMain,\n Menu,\n protocol,\n screen,\n shell,\n } = await import('electron');\n\n await app.whenReady();\n\n return {\n app,\n ipcMain,\n protocol,\n shell,\n screen,\n dialog,\n Menu,\n createBrowserWindow: (options: BrowserWindowConstructorOptions) => new BW(options),\n getAllWindows: () => BW.getAllWindows(),\n fromWebContents: (wc: WebContents) => BW.fromWebContents(wc),\n fromId: (id: number) => BW.fromId(id),\n getFocusedWindow: () => BW.getFocusedWindow(),\n };\n }\n\n shutdown(): void {\n this.ready.app.quit();\n }\n}\n","import { Config, EnvAdaptor } from '@zeltjs/core';\n\n@Config\nexport class ElectronEnvAdaptor extends EnvAdaptor {\n override get(key: string): string | undefined {\n return process.env[key];\n }\n}\n","import { Injectable, inject } from '@zeltjs/core';\nimport type { BrowserWindow } from 'electron';\nimport { match } from 'ts-pattern';\nimport { ElectronAdaptor } from './electron.adaptor';\nimport type { WindowDefinition, WindowHandle, WindowRuntime } from './window.types';\n\n@Injectable()\nexport class ElectronWindowRuntimeService implements WindowRuntime {\n constructor(private readonly electronApp: ElectronAdaptor = inject(ElectronAdaptor)) {}\n\n open(definition: WindowDefinition): WindowHandle {\n const handle = this.createWindowHandle(\n this.electronApp.ready.createBrowserWindow(definition.options),\n );\n\n if (definition.loadTarget.type === 'url') {\n handle.loadURL(definition.loadTarget.url);\n } else {\n handle.loadFile(definition.loadTarget.path);\n }\n\n return handle;\n }\n\n createWindowHandle(win: BrowserWindow): WindowHandle {\n return {\n id: win.id,\n native: win,\n close: () => win.close(),\n focus: () => win.focus(),\n show: () => win.show(),\n isDestroyed: () => win.isDestroyed(),\n getTitle: () => win.getTitle(),\n getBounds: () => win.getBounds(),\n setBounds: (bounds) => win.setBounds(bounds),\n loadFile: (path) => {\n void win.loadFile(path);\n },\n loadURL: (url) => {\n void win.loadURL(url);\n },\n on: (event, handler) => {\n match(event)\n .with('closed', (e) => win.on(e, handler))\n .with('ready-to-show', (e) => win.on(e, handler))\n .exhaustive();\n },\n removeListener: (event, handler) => {\n match(event)\n .with('closed', (e) => win.removeListener(e, handler))\n .with('ready-to-show', (e) => win.removeListener(e, handler))\n .exhaustive();\n },\n webContents: {\n send: (channel, ...args) => win.webContents.send(channel, ...args),\n setWindowOpenHandler: (handler) => win.webContents.setWindowOpenHandler(handler),\n },\n };\n }\n}\n","import { Injectable, inject } from '@zeltjs/core';\nimport { ElectronWindowRuntimeService } from './electron-window-runtime.service';\nimport type { WindowDefinition, WindowHandle, WindowId } from './window.types';\n\n@Injectable()\nexport class ElectronWindowRegistryService {\n private readonly windows = new Map<WindowId, WindowHandle>();\n\n constructor(private readonly runtime = inject(ElectronWindowRuntimeService)) {}\n\n open(definition: WindowDefinition): WindowHandle {\n const existing = this.windows.get(definition.id);\n if (existing && !existing.isDestroyed()) {\n existing.focus();\n return existing;\n }\n\n const handle = this.runtime.open(definition);\n this.windows.set(definition.id, handle);\n\n handle.on('closed', () => {\n this.windows.delete(definition.id);\n });\n\n return handle;\n }\n\n close(id: WindowId): void {\n const handle = this.windows.get(id);\n if (handle && !handle.isDestroyed()) {\n handle.close();\n }\n }\n\n closeAll(): void {\n for (const handle of this.windows.values()) {\n if (!handle.isDestroyed()) {\n handle.close();\n }\n }\n }\n\n count(): number {\n return this.windows.size;\n }\n}\n","import { getContext, runInContext, setContext } from '@zeltjs/core';\nimport type { IpcMainInvokeEvent } from 'electron';\nimport { match } from 'ts-pattern';\n\nimport type { IpcBody, IpcFetchRequest, IpcFetchResponse } from '../shared/ipc.types';\n\nconst BODY_FORBIDDEN_METHODS = new Set(['GET', 'HEAD']);\nconst NO_BODY_STATUSES = new Set([204, 205, 304]);\nconst TEXT_CONTENT_TYPE_PREFIXES = [\n 'text/',\n 'application/json',\n 'application/xml',\n 'application/javascript',\n 'application/x-www-form-urlencoded',\n];\n\nconst isTextContentType = (contentType: string): boolean =>\n TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));\n\nconst toBody = (body: IpcBody): BodyInit | null =>\n match(body)\n .with({ kind: 'none' }, () => null)\n .with({ kind: 'text' }, ({ value }) => value)\n .with({ kind: 'arrayBuffer' }, ({ value }) => value)\n .exhaustive();\n\nexport const toRequest = (payload: IpcFetchRequest, baseUrl: string): Request => {\n const headers: [string, string][] = payload.headers.map(([k, v]) => [k, v]);\n return new Request(baseUrl.replace(/\\/+$/, '') + payload.path, {\n method: payload.method,\n headers,\n body: BODY_FORBIDDEN_METHODS.has(payload.method) ? null : toBody(payload.body),\n });\n};\n\nexport const toIpcResponse = async (\n response: Response,\n method: string,\n): Promise<IpcFetchResponse> => {\n const headers: [string, string][] = [];\n response.headers.forEach((value, key) => {\n headers.push([key, value]);\n });\n\n let body: IpcBody;\n if (NO_BODY_STATUSES.has(response.status) || method === 'HEAD') {\n body = { kind: 'none' };\n } else {\n const contentType = response.headers.get('content-type');\n if (contentType && isTextContentType(contentType)) {\n body = { kind: 'text', value: await response.text() };\n } else {\n body = { kind: 'arrayBuffer', value: await response.arrayBuffer() };\n }\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n };\n};\n\ndeclare module '@zeltjs/core' {\n interface RequestContextSchema {\n ipcEvent: IpcMainInvokeEvent;\n }\n}\n\ntype IpcMainLike = {\n handle(\n channel: string,\n listener: (event: IpcMainInvokeEvent, payload: IpcFetchRequest) => unknown,\n ): void;\n removeHandler(channel: string): void;\n};\n\n/** @throws {ZeltContextNotAvailableError} */\nexport const ipcEvent = (): IpcMainInvokeEvent | undefined => getContext('ipcEvent');\n\n/** @throws {ZeltContextNotAvailableError} */\nexport const setupIpcBridge = (\n ipcMain: IpcMainLike,\n fetch: (request: Request) => Promise<Response>,\n channel: string,\n): (() => void) => {\n ipcMain.handle(channel, async (event, payload) =>\n runInContext(async () => {\n setContext('ipcEvent', event);\n const request = toRequest(payload, channel);\n const response = await fetch(request);\n return toIpcResponse(response, payload.method);\n }),\n );\n\n return () => {\n ipcMain.removeHandler(channel);\n };\n};\n","import type {\n ConfigClass,\n ConfiguredFeature,\n CreateRuntimeOptions,\n HttpCapabilities,\n RuntimeApp,\n} from '@zeltjs/core';\nimport { ElectronAdaptor } from './electron.adaptor';\nimport { ElectronEnvAdaptor } from './electron-env.adaptor';\nimport { setupIpcBridge } from './ipc-bridge';\n\ntype IpcChannel = `http://${string}` | `https://${string}`;\n\nexport type ElectronAppOptions = {\n readonly configs?: readonly ConfigClass<object>[];\n readonly warmup?: boolean;\n readonly ipcChannel?: IpcChannel;\n};\n\ntype HttpRuntimeApp = RuntimeApp<readonly ConfiguredFeature[]> & {\n readonly http: HttpCapabilities;\n};\n\ntype HttpApp = {\n readonly createRuntime: (options?: CreateRuntimeOptions) => Promise<HttpRuntimeApp>;\n};\n\nexport type OnElectronApp = {\n readonly get: HttpRuntimeApp['get'];\n readonly fetch: (request: Request) => Promise<Response>;\n readonly shutdown: () => Promise<void>;\n};\n\nconst DEFAULT_IPC_CHANNEL = 'http://zelt-ipc';\n\n/** @throws {ZeltContextNotAvailableError} */\nexport const onElectron = async (\n app: HttpApp,\n options: ElectronAppOptions = {},\n): Promise<OnElectronApp> => {\n const readyApp = await app.createRuntime({\n ...(options.configs === undefined ? {} : { configs: options.configs }),\n fallbackConfigs: [ElectronEnvAdaptor],\n warmup: options.warmup ?? true,\n });\n\n const electronApp = await readyApp.get(ElectronAdaptor);\n const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;\n\n const removeIpcHandler = setupIpcBridge(electronApp.ready.ipcMain, readyApp.http.fetch, channel);\n\n return {\n get: readyApp.get,\n fetch: readyApp.http.fetch,\n shutdown: async () => {\n removeIpcHandler();\n await readyApp.shutdown();\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Injectable","inject","LifecycleManager","ElectronAdaptor","startup","app","BrowserWindow","BW","dialog","ipcMain","Menu","protocol","screen","shell","whenReady","createBrowserWindow","options","getAllWindows","fromWebContents","wc","fromId","id","getFocusedWindow","shutdown","ready","quit","lifecycleManager","register","Config","EnvAdaptor","ElectronEnvAdaptor","get","key","process","env","Injectable","inject","match","ElectronAdaptor","ElectronWindowRuntimeService","open","definition","handle","createWindowHandle","electronApp","ready","createBrowserWindow","options","loadTarget","type","loadURL","url","loadFile","path","win","id","native","close","focus","show","isDestroyed","getTitle","getBounds","setBounds","bounds","on","event","handler","with","e","exhaustive","removeListener","webContents","send","channel","args","setWindowOpenHandler","Injectable","inject","ElectronWindowRuntimeService","ElectronWindowRegistryService","open","definition","existing","windows","get","id","isDestroyed","focus","handle","runtime","set","on","delete","close","closeAll","values","count","size","Map","getContext","runInContext","setContext","match","BODY_FORBIDDEN_METHODS","Set","NO_BODY_STATUSES","TEXT_CONTENT_TYPE_PREFIXES","isTextContentType","contentType","some","prefix","startsWith","toBody","body","with","kind","value","exhaustive","toRequest","payload","baseUrl","headers","map","k","v","Request","replace","path","method","has","toIpcResponse","response","forEach","key","push","status","get","text","arrayBuffer","statusText","ipcEvent","setupIpcBridge","ipcMain","fetch","channel","handle","event","request","removeHandler","ZeltElectronIpcFeatureNotFoundError","Error","context","ipcFeature","name","Object","setPrototypeOf","prototype","createListenForHttp","HTTP_FEATURE_KEY","HttpFeature","ElectronAdaptor","ElectronEnvAdaptor","setupIpcBridge","ZeltElectronIpcFeatureNotFoundError","DEFAULT_IPC_CHANNEL","withCleanupOnError","cleanup","body","error","cleanupError","AggregateError","createElectronApp","readyApp","shutdown","base","electronApp","entry","getFeatureEntries","Object","defineProperty","key","value","capabilities","listen","fetch","callback","feature","registerShutdown","configurable","enumerable","onElectron","app","options","createRuntime","configs","undefined","fallbackConfigs","warmup","removeIpcHandler","ipcFeature","ipcEntry","find","electronAdaptor","get","channel","ipcChannel","ready","ipcMain"],"sources":["../../src/main/electron.adaptor.ts","../../src/main/electron-env.adaptor.ts","../../src/main/electron-window-runtime.service.ts","../../src/main/electron-window-registry.service.ts","../../src/main/ipc-bridge.ts","../../src/main/on-electron.exceptions.ts","../../src/main/on-electron.ts"],"sourcesContent":["import type { Lifecycle, ReadyValue } from '@zeltjs/core';\nimport { Injectable, inject, LifecycleManager } from '@zeltjs/core';\nimport type {\n App,\n BrowserWindow,\n BrowserWindowConstructorOptions,\n Dialog,\n IpcMain,\n Menu,\n Protocol,\n Screen,\n Shell,\n WebContents,\n} from 'electron';\n\nexport type ElectronReady = {\n readonly app: App;\n readonly ipcMain: IpcMain;\n readonly protocol: Protocol;\n readonly shell: Shell;\n readonly screen: Screen;\n readonly dialog: Dialog;\n readonly Menu: typeof Menu;\n readonly createBrowserWindow: (options: BrowserWindowConstructorOptions) => BrowserWindow;\n readonly getAllWindows: () => BrowserWindow[];\n readonly fromWebContents: (webContents: WebContents) => BrowserWindow | null;\n readonly fromId: (id: number) => BrowserWindow | null;\n readonly getFocusedWindow: () => BrowserWindow | null;\n};\n\n@Injectable()\nexport class ElectronAdaptor implements Lifecycle<ElectronReady> {\n readonly ready: ReadyValue<ElectronReady>;\n\n constructor(lifecycleManager = inject(LifecycleManager)) {\n this.ready = lifecycleManager.register(this);\n }\n\n async startup(): Promise<ElectronReady> {\n const {\n app,\n BrowserWindow: BW,\n dialog,\n ipcMain,\n Menu,\n protocol,\n screen,\n shell,\n } = await import('electron');\n\n await app.whenReady();\n\n return {\n app,\n ipcMain,\n protocol,\n shell,\n screen,\n dialog,\n Menu,\n createBrowserWindow: (options: BrowserWindowConstructorOptions) => new BW(options),\n getAllWindows: () => BW.getAllWindows(),\n fromWebContents: (wc: WebContents) => BW.fromWebContents(wc),\n fromId: (id: number) => BW.fromId(id),\n getFocusedWindow: () => BW.getFocusedWindow(),\n };\n }\n\n shutdown(): void {\n this.ready.app.quit();\n }\n}\n","import { Config, EnvAdaptor } from '@zeltjs/core';\n\n@Config\nexport class ElectronEnvAdaptor extends EnvAdaptor {\n override get(key: string): string | undefined {\n return process.env[key];\n }\n}\n","import { Injectable, inject } from '@zeltjs/core';\nimport type { BrowserWindow } from 'electron';\nimport { match } from 'ts-pattern';\nimport { ElectronAdaptor } from './electron.adaptor';\nimport type { WindowDefinition, WindowHandle, WindowRuntime } from './window.types';\n\n@Injectable()\nexport class ElectronWindowRuntimeService implements WindowRuntime {\n constructor(private readonly electronApp: ElectronAdaptor = inject(ElectronAdaptor)) {}\n\n open(definition: WindowDefinition): WindowHandle {\n const handle = this.createWindowHandle(\n this.electronApp.ready.createBrowserWindow(definition.options),\n );\n\n if (definition.loadTarget.type === 'url') {\n handle.loadURL(definition.loadTarget.url);\n } else {\n handle.loadFile(definition.loadTarget.path);\n }\n\n return handle;\n }\n\n createWindowHandle(win: BrowserWindow): WindowHandle {\n return {\n id: win.id,\n native: win,\n close: () => win.close(),\n focus: () => win.focus(),\n show: () => win.show(),\n isDestroyed: () => win.isDestroyed(),\n getTitle: () => win.getTitle(),\n getBounds: () => win.getBounds(),\n setBounds: (bounds) => win.setBounds(bounds),\n loadFile: (path) => {\n void win.loadFile(path);\n },\n loadURL: (url) => {\n void win.loadURL(url);\n },\n on: (event, handler) => {\n match(event)\n .with('closed', (e) => win.on(e, handler))\n .with('ready-to-show', (e) => win.on(e, handler))\n .exhaustive();\n },\n removeListener: (event, handler) => {\n match(event)\n .with('closed', (e) => win.removeListener(e, handler))\n .with('ready-to-show', (e) => win.removeListener(e, handler))\n .exhaustive();\n },\n webContents: {\n send: (channel, ...args) => win.webContents.send(channel, ...args),\n setWindowOpenHandler: (handler) => win.webContents.setWindowOpenHandler(handler),\n },\n };\n }\n}\n","import { Injectable, inject } from '@zeltjs/core';\nimport { ElectronWindowRuntimeService } from './electron-window-runtime.service';\nimport type { WindowDefinition, WindowHandle, WindowId } from './window.types';\n\n@Injectable()\nexport class ElectronWindowRegistryService {\n private readonly windows = new Map<WindowId, WindowHandle>();\n\n constructor(private readonly runtime = inject(ElectronWindowRuntimeService)) {}\n\n open(definition: WindowDefinition): WindowHandle {\n const existing = this.windows.get(definition.id);\n if (existing && !existing.isDestroyed()) {\n existing.focus();\n return existing;\n }\n\n const handle = this.runtime.open(definition);\n this.windows.set(definition.id, handle);\n\n handle.on('closed', () => {\n this.windows.delete(definition.id);\n });\n\n return handle;\n }\n\n close(id: WindowId): void {\n const handle = this.windows.get(id);\n if (handle && !handle.isDestroyed()) {\n handle.close();\n }\n }\n\n closeAll(): void {\n for (const handle of this.windows.values()) {\n if (!handle.isDestroyed()) {\n handle.close();\n }\n }\n }\n\n count(): number {\n return this.windows.size;\n }\n}\n","import { getContext, runInContext, setContext } from '@zeltjs/core';\nimport type { IpcMainInvokeEvent } from 'electron';\nimport { match } from 'ts-pattern';\n\nimport type { IpcBody, IpcFetchRequest, IpcFetchResponse } from '../shared/ipc.types';\n\nconst BODY_FORBIDDEN_METHODS = new Set(['GET', 'HEAD']);\nconst NO_BODY_STATUSES = new Set([204, 205, 304]);\nconst TEXT_CONTENT_TYPE_PREFIXES = [\n 'text/',\n 'application/json',\n 'application/xml',\n 'application/javascript',\n 'application/x-www-form-urlencoded',\n];\n\nconst isTextContentType = (contentType: string): boolean =>\n TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));\n\nconst toBody = (body: IpcBody): BodyInit | null =>\n match(body)\n .with({ kind: 'none' }, () => null)\n .with({ kind: 'text' }, ({ value }) => value)\n .with({ kind: 'arrayBuffer' }, ({ value }) => value)\n .exhaustive();\n\nexport const toRequest = (payload: IpcFetchRequest, baseUrl: string): Request => {\n const headers: [string, string][] = payload.headers.map(([k, v]) => [k, v]);\n return new Request(baseUrl.replace(/\\/+$/, '') + payload.path, {\n method: payload.method,\n headers,\n body: BODY_FORBIDDEN_METHODS.has(payload.method) ? null : toBody(payload.body),\n });\n};\n\nexport const toIpcResponse = async (\n response: Response,\n method: string,\n): Promise<IpcFetchResponse> => {\n const headers: [string, string][] = [];\n response.headers.forEach((value, key) => {\n headers.push([key, value]);\n });\n\n let body: IpcBody;\n if (NO_BODY_STATUSES.has(response.status) || method === 'HEAD') {\n body = { kind: 'none' };\n } else {\n const contentType = response.headers.get('content-type');\n if (contentType && isTextContentType(contentType)) {\n body = { kind: 'text', value: await response.text() };\n } else {\n body = { kind: 'arrayBuffer', value: await response.arrayBuffer() };\n }\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers,\n body,\n };\n};\n\ndeclare module '@zeltjs/core' {\n interface RequestContextSchema {\n ipcEvent: IpcMainInvokeEvent;\n }\n}\n\ntype IpcMainLike = {\n handle(\n channel: string,\n listener: (event: IpcMainInvokeEvent, payload: IpcFetchRequest) => unknown,\n ): void;\n removeHandler(channel: string): void;\n};\n\n/** @throws {ZeltContextNotAvailableError} */\nexport const ipcEvent = (): IpcMainInvokeEvent | undefined => getContext('ipcEvent');\n\n/** @throws {ZeltContextNotAvailableError} */\nexport const setupIpcBridge = (\n ipcMain: IpcMainLike,\n fetch: (request: Request) => Promise<Response>,\n channel: string,\n): (() => void) => {\n ipcMain.handle(channel, async (event, payload) =>\n runInContext(async () => {\n setContext('ipcEvent', event);\n const request = toRequest(payload, channel);\n const response = await fetch(request);\n return toIpcResponse(response, payload.method);\n }),\n );\n\n return () => {\n ipcMain.removeHandler(channel);\n };\n};\n","type ZeltElectronIpcFeatureNotFoundContext = { readonly ipcFeature: string };\n\n/** No HttpFeature matches the `ipcFeature` key requested for IPC binding. */\nexport class ZeltElectronIpcFeatureNotFoundError extends Error {\n override readonly name = 'ZeltElectronIpcFeatureNotFoundError';\n readonly context: ZeltElectronIpcFeatureNotFoundContext;\n\n constructor(context: ZeltElectronIpcFeatureNotFoundContext) {\n super(`No HttpFeature registered with key \"${context.ipcFeature}\" to bind to the IPC bridge`);\n this.context = context;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import type { ListenOptions, ServerHandle } from '@zeltjs/adapter-node';\nimport { createListenForHttp } from '@zeltjs/adapter-node';\nimport type {\n ConfigClass,\n ConfiguredFeature,\n FeatureApp,\n FeatureReadyCapabilities,\n RuntimeApp,\n} from '@zeltjs/core';\nimport { HTTP_FEATURE_KEY, HttpFeature } from '@zeltjs/core';\n\nimport { ElectronAdaptor } from './electron.adaptor';\nimport { ElectronEnvAdaptor } from './electron-env.adaptor';\nimport { setupIpcBridge } from './ipc-bridge';\nimport { ZeltElectronIpcFeatureNotFoundError } from './on-electron.exceptions';\n\nexport type { ServerHandle } from '@zeltjs/adapter-node';\nexport { ZeltElectronIpcFeatureNotFoundError } from './on-electron.exceptions';\n\ntype IpcChannel = `http://${string}` | `https://${string}`;\n\nexport type ElectronAppOptions<TIpcFeature extends string = string> = {\n readonly configs?: readonly ConfigClass<object>[];\n readonly warmup?: boolean;\n readonly ipcChannel?: IpcChannel;\n readonly ipcFeature?: TIpcFeature;\n};\n\ntype HttpFeatureKeys<F extends readonly ConfiguredFeature[]> = Extract<\n F[number],\n HttpFeature<string>\n>['key'];\n\ntype EnvironmentElectronAppPart = {\n readonly shutdown: () => Promise<void>;\n};\n\ntype HttpElectronAppPart = {\n readonly listen: (portOrOptions?: number | ListenOptions) => Promise<ServerHandle>;\n};\n\ntype ElectronFeatureCapabilities<TFeature extends ConfiguredFeature> =\n FeatureReadyCapabilities<TFeature> &\n (TFeature extends HttpFeature<string> ? HttpElectronAppPart : unknown);\n\ntype ElectronNamespacedCapabilities<F extends readonly ConfiguredFeature[]> = {\n readonly [TFeature in F[number] as TFeature['key']]: ElectronFeatureCapabilities<TFeature>;\n};\n\nexport type OnElectronApp = RuntimeApp<readonly ConfiguredFeature[]> & EnvironmentElectronAppPart;\n\ntype ElectronAppForFeatures<F extends readonly ConfiguredFeature[]> = RuntimeApp<F> &\n EnvironmentElectronAppPart &\n ElectronNamespacedCapabilities<F>;\n\nconst DEFAULT_IPC_CHANNEL = 'http://zelt-ipc';\n\n// warmup already started feature-owned resources (e.g. DB connections); any setup failure\n// after createRuntime() must tear them down via cleanup so they aren't left leaked.\n/** @throws {AggregateError} */\nconst withCleanupOnError = async <T>(\n cleanup: () => Promise<void>,\n body: () => Promise<T>,\n): Promise<T> => {\n try {\n return await body();\n } catch (error) {\n try {\n await cleanup();\n } catch (cleanupError) {\n throw new AggregateError(\n [error, cleanupError],\n 'onElectron setup failed and runtime shutdown also failed',\n );\n }\n throw error;\n }\n};\n\nconst createElectronApp = (\n readyApp: RuntimeApp<readonly ConfiguredFeature[]>,\n shutdown: () => Promise<void>,\n): OnElectronApp => {\n const base: RuntimeApp<readonly ConfiguredFeature[]> & EnvironmentElectronAppPart = {\n ...readyApp,\n shutdown,\n };\n\n const electronApp: OnElectronApp = { ...base };\n\n for (const entry of readyApp.getFeatureEntries(HttpFeature)) {\n Object.defineProperty(electronApp, entry.key, {\n value: {\n ...entry.capabilities,\n listen: createListenForHttp(entry.capabilities.fetch, (callback) =>\n entry.feature.registerShutdown(callback),\n ),\n },\n configurable: true,\n enumerable: true,\n });\n }\n\n return electronApp;\n};\n\nexport function onElectron<const F extends readonly ConfiguredFeature[]>(\n app: FeatureApp<F>,\n options?: ElectronAppOptions<HttpFeatureKeys<F>>,\n): Promise<ElectronAppForFeatures<F>>;\n\n/** @throws {ZeltContextNotAvailableError | ZeltElectronIpcFeatureNotFoundError | AggregateError} */\nexport async function onElectron<const F extends readonly ConfiguredFeature[]>(\n app: FeatureApp<F>,\n options: ElectronAppOptions = {},\n): Promise<OnElectronApp> {\n const readyApp = await app.createRuntime({\n ...(options.configs === undefined ? {} : { configs: options.configs }),\n fallbackConfigs: [ElectronEnvAdaptor],\n warmup: options.warmup ?? true,\n });\n\n // declared outside the body so cleanup can remove the IPC handler even if a step\n // after setupIpcBridge (e.g. createElectronApp) throws before onElectron returns.\n let removeIpcHandler: (() => void) | undefined;\n\n return withCleanupOnError(\n async () => {\n removeIpcHandler?.();\n await readyApp.shutdown();\n },\n async () => {\n const ipcFeature = options.ipcFeature ?? HTTP_FEATURE_KEY;\n const ipcEntry = readyApp\n .getFeatureEntries(HttpFeature)\n .find((entry) => entry.key === ipcFeature);\n\n if (ipcEntry === undefined) {\n throw new ZeltElectronIpcFeatureNotFoundError({ ipcFeature });\n }\n\n const electronAdaptor = await readyApp.get(ElectronAdaptor);\n const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;\n\n removeIpcHandler = setupIpcBridge(\n electronAdaptor.ready.ipcMain,\n ipcEntry.capabilities.fetch,\n channel,\n );\n\n const shutdown = async (): Promise<void> => {\n removeIpcHandler?.();\n await readyApp.shutdown();\n };\n\n return createElectronApp(readyApp, shutdown);\n },\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeltjs/adapter-electron",
3
- "version": "0.9.1-canary.5",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -49,7 +49,8 @@
49
49
  ],
50
50
  "dependencies": {
51
51
  "ts-pattern": "5.7.1",
52
- "@zeltjs/core": "0.9.1-canary.5"
52
+ "@zeltjs/adapter-node": "0.10.0",
53
+ "@zeltjs/core": "0.10.0"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/node": "22.19.17"