@zeltjs/adapter-electron 0.8.1 → 0.8.2-canary.1
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/dist/ipc.types-DgxeccV3.d.cts +26 -0
- package/dist/ipc.types-DgxeccV3.d.cts.map +1 -0
- package/dist/ipc.types-OYZhXKH2.d.ts +26 -0
- package/dist/ipc.types-OYZhXKH2.d.ts.map +1 -0
- package/dist/main/index.cjs +266 -0
- package/dist/main/index.d.cts +122 -0
- package/dist/main/index.d.cts.map +1 -0
- package/dist/main/index.d.ts +122 -0
- package/dist/main/index.d.ts.map +1 -0
- package/dist/main/index.js +240 -0
- package/dist/main/index.js.map +1 -0
- package/dist/preload/index.cjs +15 -0
- package/dist/preload/index.d.cts +10 -0
- package/dist/preload/index.d.cts.map +1 -0
- package/dist/preload/index.d.ts +10 -0
- package/dist/preload/index.d.ts.map +1 -0
- package/dist/preload/index.js +20 -0
- package/dist/preload/index.js.map +1 -0
- package/dist/renderer/index.cjs +62 -0
- package/dist/renderer/index.d.cts +15 -0
- package/dist/renderer/index.d.cts.map +1 -0
- package/dist/renderer/index.d.ts +15 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +61 -0
- package/dist/renderer/index.js.map +1 -0
- package/package.json +32 -9
- package/dist/index.d.ts +0 -19
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -29
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/shared/ipc.types.d.ts
|
|
2
|
+
type IpcBody = {
|
|
3
|
+
kind: 'none';
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'text';
|
|
6
|
+
readonly value: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'arrayBuffer';
|
|
9
|
+
readonly value: ArrayBuffer;
|
|
10
|
+
};
|
|
11
|
+
type IpcFetchRequest = {
|
|
12
|
+
readonly method: string;
|
|
13
|
+
readonly path: string;
|
|
14
|
+
readonly headers: ReadonlyArray<readonly [string, string]>;
|
|
15
|
+
readonly body: IpcBody;
|
|
16
|
+
};
|
|
17
|
+
type IpcFetchResponse = {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly statusText: string;
|
|
20
|
+
readonly headers: ReadonlyArray<readonly [string, string]>;
|
|
21
|
+
readonly body: IpcBody;
|
|
22
|
+
};
|
|
23
|
+
type IpcSender = (request: IpcFetchRequest) => Promise<IpcFetchResponse>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { IpcFetchResponse as n, IpcSender as r, IpcFetchRequest as t };
|
|
26
|
+
//# sourceMappingURL=ipc.types-DgxeccV3.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc.types-DgxeccV3.d.cts","names":[],"sources":["../src/shared/ipc.types.ts"],"mappings":";KAAY,OAAA;EACN,IAAA;AAAA;EACA,IAAA;EAAA,SAAuB,KAAA;AAAA;EACvB,IAAA;EAAA,SAA8B,KAAA,EAAO,WAAA;AAAA;AAAA,KAE/B,eAAA;EAAA,SACD,MAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA,EAAS,aAAA;EAAA,SACT,IAAA,EAAM,OAAA;AAAA;AAAA,KAGL,gBAAA;EAAA,SACD,MAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,aAAA;EAAA,SACT,IAAA,EAAM,OAAA;AAAA;AAAA,KAGL,SAAA,IAAa,OAAA,EAAS,eAAA,KAAoB,OAAA,CAAQ,gBAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/shared/ipc.types.d.ts
|
|
2
|
+
type IpcBody = {
|
|
3
|
+
kind: 'none';
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'text';
|
|
6
|
+
readonly value: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'arrayBuffer';
|
|
9
|
+
readonly value: ArrayBuffer;
|
|
10
|
+
};
|
|
11
|
+
type IpcFetchRequest = {
|
|
12
|
+
readonly method: string;
|
|
13
|
+
readonly path: string;
|
|
14
|
+
readonly headers: ReadonlyArray<readonly [string, string]>;
|
|
15
|
+
readonly body: IpcBody;
|
|
16
|
+
};
|
|
17
|
+
type IpcFetchResponse = {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly statusText: string;
|
|
20
|
+
readonly headers: ReadonlyArray<readonly [string, string]>;
|
|
21
|
+
readonly body: IpcBody;
|
|
22
|
+
};
|
|
23
|
+
type IpcSender = (request: IpcFetchRequest) => Promise<IpcFetchResponse>;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { IpcFetchResponse as n, IpcSender as r, IpcFetchRequest as t };
|
|
26
|
+
//# sourceMappingURL=ipc.types-OYZhXKH2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ipc.types-OYZhXKH2.d.ts","names":[],"sources":["../src/shared/ipc.types.ts"],"mappings":";KAAY,OAAA;EACN,IAAA;AAAA;EACA,IAAA;EAAA,SAAuB,KAAA;AAAA;EACvB,IAAA;EAAA,SAA8B,KAAA,EAAO,WAAA;AAAA;AAAA,KAE/B,eAAA;EAAA,SACD,MAAA;EAAA,SACA,IAAA;EAAA,SACA,OAAA,EAAS,aAAA;EAAA,SACT,IAAA,EAAM,OAAA;AAAA;AAAA,KAGL,gBAAA;EAAA,SACD,MAAA;EAAA,SACA,UAAA;EAAA,SACA,OAAA,EAAS,aAAA;EAAA,SACT,IAAA,EAAM,OAAA;AAAA;AAAA,KAGL,SAAA,IAAa,OAAA,EAAS,eAAA,KAAoB,OAAA,CAAQ,gBAAA"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _zeltjs_core = require("@zeltjs/core");
|
|
3
|
+
let ts_pattern = require("ts-pattern");
|
|
4
|
+
//#region src/main/electron.adaptor.ts
|
|
5
|
+
function _ts_decorate$3(decorators, target, key, desc) {
|
|
6
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
7
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
8
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
9
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10
|
+
}
|
|
11
|
+
function _ts_metadata$2(k, v) {
|
|
12
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
13
|
+
}
|
|
14
|
+
var ElectronAdaptor = class {
|
|
15
|
+
async startup() {
|
|
16
|
+
const { app, BrowserWindow: BW, dialog, ipcMain, Menu, protocol, screen, shell } = await import("electron");
|
|
17
|
+
await app.whenReady();
|
|
18
|
+
return {
|
|
19
|
+
app,
|
|
20
|
+
ipcMain,
|
|
21
|
+
protocol,
|
|
22
|
+
shell,
|
|
23
|
+
screen,
|
|
24
|
+
dialog,
|
|
25
|
+
Menu,
|
|
26
|
+
createBrowserWindow: (options) => new BW(options),
|
|
27
|
+
getAllWindows: () => BW.getAllWindows(),
|
|
28
|
+
fromWebContents: (wc) => BW.fromWebContents(wc),
|
|
29
|
+
fromId: (id) => BW.fromId(id),
|
|
30
|
+
getFocusedWindow: () => BW.getFocusedWindow()
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
shutdown() {
|
|
34
|
+
this.ready.app.quit();
|
|
35
|
+
}
|
|
36
|
+
constructor(lifecycleManager = (0, _zeltjs_core.inject)(_zeltjs_core.LifecycleManager)) {
|
|
37
|
+
this.ready = lifecycleManager.register(this);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
ElectronAdaptor = _ts_decorate$3([
|
|
41
|
+
(0, _zeltjs_core.Injectable)(),
|
|
42
|
+
_ts_metadata$2("design:type", Function),
|
|
43
|
+
_ts_metadata$2("design:paramtypes", [void 0])
|
|
44
|
+
], ElectronAdaptor);
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/main/electron-env.adaptor.ts
|
|
47
|
+
function _ts_decorate$2(decorators, target, key, desc) {
|
|
48
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
49
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
50
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
51
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
52
|
+
}
|
|
53
|
+
var ElectronEnvAdaptor = class extends _zeltjs_core.EnvAdaptor {
|
|
54
|
+
get(key) {
|
|
55
|
+
return process.env[key];
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
ElectronEnvAdaptor = _ts_decorate$2([_zeltjs_core.Config], ElectronEnvAdaptor);
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/main/electron-window-runtime.service.ts
|
|
61
|
+
function _ts_decorate$1(decorators, target, key, desc) {
|
|
62
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
63
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
64
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
65
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
66
|
+
}
|
|
67
|
+
function _ts_metadata$1(k, v) {
|
|
68
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
69
|
+
}
|
|
70
|
+
var ElectronWindowRuntimeService = class {
|
|
71
|
+
open(definition) {
|
|
72
|
+
const handle = this.createWindowHandle(this.electronApp.ready.createBrowserWindow(definition.options));
|
|
73
|
+
if (definition.loadTarget.type === "url") handle.loadURL(definition.loadTarget.url);
|
|
74
|
+
else handle.loadFile(definition.loadTarget.path);
|
|
75
|
+
return handle;
|
|
76
|
+
}
|
|
77
|
+
createWindowHandle(win) {
|
|
78
|
+
return {
|
|
79
|
+
id: win.id,
|
|
80
|
+
native: win,
|
|
81
|
+
close: () => win.close(),
|
|
82
|
+
focus: () => win.focus(),
|
|
83
|
+
show: () => win.show(),
|
|
84
|
+
isDestroyed: () => win.isDestroyed(),
|
|
85
|
+
getTitle: () => win.getTitle(),
|
|
86
|
+
getBounds: () => win.getBounds(),
|
|
87
|
+
setBounds: (bounds) => win.setBounds(bounds),
|
|
88
|
+
loadFile: (path) => {
|
|
89
|
+
win.loadFile(path);
|
|
90
|
+
},
|
|
91
|
+
loadURL: (url) => {
|
|
92
|
+
win.loadURL(url);
|
|
93
|
+
},
|
|
94
|
+
on: (event, handler) => {
|
|
95
|
+
(0, ts_pattern.match)(event).with("closed", (e) => win.on(e, handler)).with("ready-to-show", (e) => win.on(e, handler)).exhaustive();
|
|
96
|
+
},
|
|
97
|
+
removeListener: (event, handler) => {
|
|
98
|
+
(0, ts_pattern.match)(event).with("closed", (e) => win.removeListener(e, handler)).with("ready-to-show", (e) => win.removeListener(e, handler)).exhaustive();
|
|
99
|
+
},
|
|
100
|
+
webContents: {
|
|
101
|
+
send: (channel, ...args) => win.webContents.send(channel, ...args),
|
|
102
|
+
setWindowOpenHandler: (handler) => win.webContents.setWindowOpenHandler(handler)
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
constructor(electronApp = (0, _zeltjs_core.inject)(ElectronAdaptor)) {
|
|
107
|
+
this.electronApp = electronApp;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
ElectronWindowRuntimeService = _ts_decorate$1([
|
|
111
|
+
(0, _zeltjs_core.Injectable)(),
|
|
112
|
+
_ts_metadata$1("design:type", Function),
|
|
113
|
+
_ts_metadata$1("design:paramtypes", [typeof ElectronAdaptor === "undefined" ? Object : ElectronAdaptor])
|
|
114
|
+
], ElectronWindowRuntimeService);
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/main/electron-window-registry.service.ts
|
|
117
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
118
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
119
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
120
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
121
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
122
|
+
}
|
|
123
|
+
function _ts_metadata(k, v) {
|
|
124
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
125
|
+
}
|
|
126
|
+
var ElectronWindowRegistryService = class {
|
|
127
|
+
open(definition) {
|
|
128
|
+
const existing = this.windows.get(definition.id);
|
|
129
|
+
if (existing && !existing.isDestroyed()) {
|
|
130
|
+
existing.focus();
|
|
131
|
+
return existing;
|
|
132
|
+
}
|
|
133
|
+
const handle = this.runtime.open(definition);
|
|
134
|
+
this.windows.set(definition.id, handle);
|
|
135
|
+
handle.on("closed", () => {
|
|
136
|
+
this.windows.delete(definition.id);
|
|
137
|
+
});
|
|
138
|
+
return handle;
|
|
139
|
+
}
|
|
140
|
+
close(id) {
|
|
141
|
+
const handle = this.windows.get(id);
|
|
142
|
+
if (handle && !handle.isDestroyed()) handle.close();
|
|
143
|
+
}
|
|
144
|
+
closeAll() {
|
|
145
|
+
for (const handle of this.windows.values()) if (!handle.isDestroyed()) handle.close();
|
|
146
|
+
}
|
|
147
|
+
count() {
|
|
148
|
+
return this.windows.size;
|
|
149
|
+
}
|
|
150
|
+
constructor(runtime = (0, _zeltjs_core.inject)(ElectronWindowRuntimeService)) {
|
|
151
|
+
this.runtime = runtime;
|
|
152
|
+
this.windows = /* @__PURE__ */ new Map();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
ElectronWindowRegistryService = _ts_decorate([
|
|
156
|
+
(0, _zeltjs_core.Injectable)(),
|
|
157
|
+
_ts_metadata("design:type", Function),
|
|
158
|
+
_ts_metadata("design:paramtypes", [void 0])
|
|
159
|
+
], ElectronWindowRegistryService);
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/main/ipc-bridge.ts
|
|
162
|
+
const BODY_FORBIDDEN_METHODS = new Set(["GET", "HEAD"]);
|
|
163
|
+
const NO_BODY_STATUSES = new Set([
|
|
164
|
+
204,
|
|
165
|
+
205,
|
|
166
|
+
304
|
|
167
|
+
]);
|
|
168
|
+
const TEXT_CONTENT_TYPE_PREFIXES = [
|
|
169
|
+
"text/",
|
|
170
|
+
"application/json",
|
|
171
|
+
"application/xml",
|
|
172
|
+
"application/javascript",
|
|
173
|
+
"application/x-www-form-urlencoded"
|
|
174
|
+
];
|
|
175
|
+
const isTextContentType = (contentType) => TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));
|
|
176
|
+
const toBody = (body) => (0, ts_pattern.match)(body).with({ kind: "none" }, () => null).with({ kind: "text" }, ({ value }) => value).with({ kind: "arrayBuffer" }, ({ value }) => value).exhaustive();
|
|
177
|
+
const toRequest = (payload, baseUrl) => {
|
|
178
|
+
const headers = payload.headers.map(([k, v]) => [k, v]);
|
|
179
|
+
return new Request(baseUrl + payload.path, {
|
|
180
|
+
method: payload.method,
|
|
181
|
+
headers,
|
|
182
|
+
body: BODY_FORBIDDEN_METHODS.has(payload.method) ? null : toBody(payload.body)
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
const toIpcResponse = async (response, method) => {
|
|
186
|
+
const headers = [];
|
|
187
|
+
response.headers.forEach((value, key) => {
|
|
188
|
+
headers.push([key, value]);
|
|
189
|
+
});
|
|
190
|
+
let body;
|
|
191
|
+
if (NO_BODY_STATUSES.has(response.status) || method === "HEAD") body = { kind: "none" };
|
|
192
|
+
else {
|
|
193
|
+
const contentType = response.headers.get("content-type");
|
|
194
|
+
if (contentType && isTextContentType(contentType)) body = {
|
|
195
|
+
kind: "text",
|
|
196
|
+
value: await response.text()
|
|
197
|
+
};
|
|
198
|
+
else body = {
|
|
199
|
+
kind: "arrayBuffer",
|
|
200
|
+
value: await response.arrayBuffer()
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
status: response.status,
|
|
205
|
+
statusText: response.statusText,
|
|
206
|
+
headers,
|
|
207
|
+
body
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
const setupIpcBridge = (ipcMain, fetch, channel) => {
|
|
211
|
+
ipcMain.handle(channel, async (_event, payload) => {
|
|
212
|
+
return toIpcResponse(await fetch(toRequest(payload, channel)), payload.method);
|
|
213
|
+
});
|
|
214
|
+
return () => {
|
|
215
|
+
ipcMain.removeHandler(channel);
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/main/on-electron.ts
|
|
220
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
221
|
+
const onElectron = async (app, options = {}) => {
|
|
222
|
+
const readyApp = await app.createRuntime({
|
|
223
|
+
fallbackConfigs: [ElectronEnvAdaptor],
|
|
224
|
+
warmup: options.warmup ?? true
|
|
225
|
+
});
|
|
226
|
+
const electronApp = await readyApp.get(ElectronAdaptor);
|
|
227
|
+
const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
|
|
228
|
+
const removeIpcHandler = setupIpcBridge(electronApp.ready.ipcMain, readyApp.http.fetch, channel);
|
|
229
|
+
return {
|
|
230
|
+
get: readyApp.get,
|
|
231
|
+
fetch: readyApp.http.fetch,
|
|
232
|
+
shutdown: async () => {
|
|
233
|
+
removeIpcHandler();
|
|
234
|
+
await readyApp.shutdown();
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
//#endregion
|
|
239
|
+
Object.defineProperty(exports, "ElectronAdaptor", {
|
|
240
|
+
enumerable: true,
|
|
241
|
+
get: function() {
|
|
242
|
+
return ElectronAdaptor;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
Object.defineProperty(exports, "ElectronEnvAdaptor", {
|
|
246
|
+
enumerable: true,
|
|
247
|
+
get: function() {
|
|
248
|
+
return ElectronEnvAdaptor;
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
Object.defineProperty(exports, "ElectronWindowRegistryService", {
|
|
252
|
+
enumerable: true,
|
|
253
|
+
get: function() {
|
|
254
|
+
return ElectronWindowRegistryService;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
Object.defineProperty(exports, "ElectronWindowRuntimeService", {
|
|
258
|
+
enumerable: true,
|
|
259
|
+
get: function() {
|
|
260
|
+
return ElectronWindowRuntimeService;
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
exports.onElectron = onElectron;
|
|
264
|
+
exports.setupIpcBridge = setupIpcBridge;
|
|
265
|
+
exports.toIpcResponse = toIpcResponse;
|
|
266
|
+
exports.toRequest = toRequest;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, t as IpcFetchRequest } from "../ipc.types-DgxeccV3.cjs";
|
|
2
|
+
import { ConfiguredFeature, CreateRuntimeOptions, EnvAdaptor, HttpCapabilities, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
|
|
3
|
+
import { App, BrowserWindow, BrowserWindowConstructorOptions, Dialog, IpcMain, Menu, Protocol, Rectangle, Screen, Shell, WebContents } from "electron";
|
|
4
|
+
|
|
5
|
+
//#region src/main/electron.adaptor.d.ts
|
|
6
|
+
type ElectronReady = {
|
|
7
|
+
readonly app: App;
|
|
8
|
+
readonly ipcMain: IpcMain;
|
|
9
|
+
readonly protocol: Protocol;
|
|
10
|
+
readonly shell: Shell;
|
|
11
|
+
readonly screen: Screen;
|
|
12
|
+
readonly dialog: Dialog;
|
|
13
|
+
readonly Menu: typeof Menu;
|
|
14
|
+
readonly createBrowserWindow: (options: BrowserWindowConstructorOptions) => BrowserWindow;
|
|
15
|
+
readonly getAllWindows: () => BrowserWindow[];
|
|
16
|
+
readonly fromWebContents: (webContents: WebContents) => BrowserWindow | null;
|
|
17
|
+
readonly fromId: (id: number) => BrowserWindow | null;
|
|
18
|
+
readonly getFocusedWindow: () => BrowserWindow | null;
|
|
19
|
+
};
|
|
20
|
+
declare class ElectronAdaptor implements Lifecycle<ElectronReady> {
|
|
21
|
+
readonly ready: ReadyValue<ElectronReady>;
|
|
22
|
+
constructor(lifecycleManager?: LifecycleManager);
|
|
23
|
+
startup(): Promise<ElectronReady>;
|
|
24
|
+
shutdown(): void;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/main/electron-env.adaptor.d.ts
|
|
28
|
+
declare class ElectronEnvAdaptor extends EnvAdaptor {
|
|
29
|
+
get(key: string): string | undefined;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/main/window.types.d.ts
|
|
33
|
+
type WindowId = string;
|
|
34
|
+
type WindowOpenHandlerResult = {
|
|
35
|
+
readonly action: 'allow' | 'deny';
|
|
36
|
+
};
|
|
37
|
+
type WindowHandle = {
|
|
38
|
+
readonly id: number;
|
|
39
|
+
readonly native: BrowserWindow;
|
|
40
|
+
close(): void;
|
|
41
|
+
focus(): void;
|
|
42
|
+
show(): void;
|
|
43
|
+
isDestroyed(): boolean;
|
|
44
|
+
getTitle(): string;
|
|
45
|
+
getBounds(): Rectangle;
|
|
46
|
+
setBounds(bounds: Partial<Rectangle>): void;
|
|
47
|
+
loadFile(path: string): void;
|
|
48
|
+
loadURL(url: string): void;
|
|
49
|
+
on(event: 'closed' | 'ready-to-show', handler: () => void): void;
|
|
50
|
+
removeListener(event: 'closed' | 'ready-to-show', handler: (...args: unknown[]) => void): void;
|
|
51
|
+
webContents: {
|
|
52
|
+
send(channel: string, ...args: unknown[]): void;
|
|
53
|
+
setWindowOpenHandler(handler: (details: {
|
|
54
|
+
url: string;
|
|
55
|
+
}) => WindowOpenHandlerResult): void;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
type WindowLoadTarget = {
|
|
59
|
+
type: 'file';
|
|
60
|
+
readonly path: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'url';
|
|
63
|
+
readonly url: string;
|
|
64
|
+
};
|
|
65
|
+
type WindowDefinition = {
|
|
66
|
+
readonly id: WindowId;
|
|
67
|
+
readonly options: BrowserWindowConstructorOptions;
|
|
68
|
+
readonly loadTarget: WindowLoadTarget;
|
|
69
|
+
};
|
|
70
|
+
type WindowRuntime = {
|
|
71
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/main/electron-window-runtime.service.d.ts
|
|
75
|
+
declare class ElectronWindowRuntimeService implements WindowRuntime {
|
|
76
|
+
private readonly electronApp;
|
|
77
|
+
constructor(electronApp?: ElectronAdaptor);
|
|
78
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
79
|
+
createWindowHandle(win: BrowserWindow): WindowHandle;
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/main/electron-window-registry.service.d.ts
|
|
83
|
+
declare class ElectronWindowRegistryService {
|
|
84
|
+
private readonly runtime;
|
|
85
|
+
private readonly windows;
|
|
86
|
+
constructor(runtime?: ElectronWindowRuntimeService);
|
|
87
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
88
|
+
close(id: WindowId): void;
|
|
89
|
+
closeAll(): void;
|
|
90
|
+
count(): number;
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/main/ipc-bridge.d.ts
|
|
94
|
+
declare const toRequest: (payload: IpcFetchRequest, baseUrl: string) => Request;
|
|
95
|
+
declare const toIpcResponse: (response: Response, method: string) => Promise<IpcFetchResponse>;
|
|
96
|
+
type IpcMainLike = {
|
|
97
|
+
handle(channel: string, listener: (event: unknown, payload: IpcFetchRequest) => unknown): void;
|
|
98
|
+
removeHandler(channel: string): void;
|
|
99
|
+
};
|
|
100
|
+
declare const setupIpcBridge: (ipcMain: IpcMainLike, fetch: (request: Request) => Promise<Response>, channel: string) => (() => void);
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/main/on-electron.d.ts
|
|
103
|
+
type IpcChannel = `http://${string}` | `https://${string}`;
|
|
104
|
+
type ElectronAppOptions = {
|
|
105
|
+
readonly warmup?: boolean;
|
|
106
|
+
readonly ipcChannel?: IpcChannel;
|
|
107
|
+
};
|
|
108
|
+
type HttpRuntimeApp = RuntimeApp<readonly ConfiguredFeature[]> & {
|
|
109
|
+
readonly http: HttpCapabilities;
|
|
110
|
+
};
|
|
111
|
+
type HttpApp = {
|
|
112
|
+
readonly createRuntime: (options?: CreateRuntimeOptions) => Promise<HttpRuntimeApp>;
|
|
113
|
+
};
|
|
114
|
+
type OnElectronApp = {
|
|
115
|
+
readonly get: HttpRuntimeApp['get'];
|
|
116
|
+
readonly fetch: (request: Request) => Promise<Response>;
|
|
117
|
+
readonly shutdown: () => Promise<void>;
|
|
118
|
+
};
|
|
119
|
+
declare const onElectron: (app: HttpApp, options?: ElectronAppOptions) => Promise<OnElectronApp>;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, onElectron, setupIpcBridge, toIpcResponse, toRequest };
|
|
122
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +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":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, t as IpcFetchRequest } from "../ipc.types-OYZhXKH2.js";
|
|
2
|
+
import { ConfiguredFeature, CreateRuntimeOptions, EnvAdaptor, HttpCapabilities, Lifecycle, LifecycleManager, ReadyValue, RuntimeApp } from "@zeltjs/core";
|
|
3
|
+
import { App, BrowserWindow, BrowserWindowConstructorOptions, Dialog, IpcMain, Menu, Protocol, Rectangle, Screen, Shell, WebContents } from "electron";
|
|
4
|
+
|
|
5
|
+
//#region src/main/electron.adaptor.d.ts
|
|
6
|
+
type ElectronReady = {
|
|
7
|
+
readonly app: App;
|
|
8
|
+
readonly ipcMain: IpcMain;
|
|
9
|
+
readonly protocol: Protocol;
|
|
10
|
+
readonly shell: Shell;
|
|
11
|
+
readonly screen: Screen;
|
|
12
|
+
readonly dialog: Dialog;
|
|
13
|
+
readonly Menu: typeof Menu;
|
|
14
|
+
readonly createBrowserWindow: (options: BrowserWindowConstructorOptions) => BrowserWindow;
|
|
15
|
+
readonly getAllWindows: () => BrowserWindow[];
|
|
16
|
+
readonly fromWebContents: (webContents: WebContents) => BrowserWindow | null;
|
|
17
|
+
readonly fromId: (id: number) => BrowserWindow | null;
|
|
18
|
+
readonly getFocusedWindow: () => BrowserWindow | null;
|
|
19
|
+
};
|
|
20
|
+
declare class ElectronAdaptor implements Lifecycle<ElectronReady> {
|
|
21
|
+
readonly ready: ReadyValue<ElectronReady>;
|
|
22
|
+
constructor(lifecycleManager?: LifecycleManager);
|
|
23
|
+
startup(): Promise<ElectronReady>;
|
|
24
|
+
shutdown(): void;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/main/electron-env.adaptor.d.ts
|
|
28
|
+
declare class ElectronEnvAdaptor extends EnvAdaptor {
|
|
29
|
+
get(key: string): string | undefined;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/main/window.types.d.ts
|
|
33
|
+
type WindowId = string;
|
|
34
|
+
type WindowOpenHandlerResult = {
|
|
35
|
+
readonly action: 'allow' | 'deny';
|
|
36
|
+
};
|
|
37
|
+
type WindowHandle = {
|
|
38
|
+
readonly id: number;
|
|
39
|
+
readonly native: BrowserWindow;
|
|
40
|
+
close(): void;
|
|
41
|
+
focus(): void;
|
|
42
|
+
show(): void;
|
|
43
|
+
isDestroyed(): boolean;
|
|
44
|
+
getTitle(): string;
|
|
45
|
+
getBounds(): Rectangle;
|
|
46
|
+
setBounds(bounds: Partial<Rectangle>): void;
|
|
47
|
+
loadFile(path: string): void;
|
|
48
|
+
loadURL(url: string): void;
|
|
49
|
+
on(event: 'closed' | 'ready-to-show', handler: () => void): void;
|
|
50
|
+
removeListener(event: 'closed' | 'ready-to-show', handler: (...args: unknown[]) => void): void;
|
|
51
|
+
webContents: {
|
|
52
|
+
send(channel: string, ...args: unknown[]): void;
|
|
53
|
+
setWindowOpenHandler(handler: (details: {
|
|
54
|
+
url: string;
|
|
55
|
+
}) => WindowOpenHandlerResult): void;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
type WindowLoadTarget = {
|
|
59
|
+
type: 'file';
|
|
60
|
+
readonly path: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'url';
|
|
63
|
+
readonly url: string;
|
|
64
|
+
};
|
|
65
|
+
type WindowDefinition = {
|
|
66
|
+
readonly id: WindowId;
|
|
67
|
+
readonly options: BrowserWindowConstructorOptions;
|
|
68
|
+
readonly loadTarget: WindowLoadTarget;
|
|
69
|
+
};
|
|
70
|
+
type WindowRuntime = {
|
|
71
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/main/electron-window-runtime.service.d.ts
|
|
75
|
+
declare class ElectronWindowRuntimeService implements WindowRuntime {
|
|
76
|
+
private readonly electronApp;
|
|
77
|
+
constructor(electronApp?: ElectronAdaptor);
|
|
78
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
79
|
+
createWindowHandle(win: BrowserWindow): WindowHandle;
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/main/electron-window-registry.service.d.ts
|
|
83
|
+
declare class ElectronWindowRegistryService {
|
|
84
|
+
private readonly runtime;
|
|
85
|
+
private readonly windows;
|
|
86
|
+
constructor(runtime?: ElectronWindowRuntimeService);
|
|
87
|
+
open(definition: WindowDefinition): WindowHandle;
|
|
88
|
+
close(id: WindowId): void;
|
|
89
|
+
closeAll(): void;
|
|
90
|
+
count(): number;
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/main/ipc-bridge.d.ts
|
|
94
|
+
declare const toRequest: (payload: IpcFetchRequest, baseUrl: string) => Request;
|
|
95
|
+
declare const toIpcResponse: (response: Response, method: string) => Promise<IpcFetchResponse>;
|
|
96
|
+
type IpcMainLike = {
|
|
97
|
+
handle(channel: string, listener: (event: unknown, payload: IpcFetchRequest) => unknown): void;
|
|
98
|
+
removeHandler(channel: string): void;
|
|
99
|
+
};
|
|
100
|
+
declare const setupIpcBridge: (ipcMain: IpcMainLike, fetch: (request: Request) => Promise<Response>, channel: string) => (() => void);
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/main/on-electron.d.ts
|
|
103
|
+
type IpcChannel = `http://${string}` | `https://${string}`;
|
|
104
|
+
type ElectronAppOptions = {
|
|
105
|
+
readonly warmup?: boolean;
|
|
106
|
+
readonly ipcChannel?: IpcChannel;
|
|
107
|
+
};
|
|
108
|
+
type HttpRuntimeApp = RuntimeApp<readonly ConfiguredFeature[]> & {
|
|
109
|
+
readonly http: HttpCapabilities;
|
|
110
|
+
};
|
|
111
|
+
type HttpApp = {
|
|
112
|
+
readonly createRuntime: (options?: CreateRuntimeOptions) => Promise<HttpRuntimeApp>;
|
|
113
|
+
};
|
|
114
|
+
type OnElectronApp = {
|
|
115
|
+
readonly get: HttpRuntimeApp['get'];
|
|
116
|
+
readonly fetch: (request: Request) => Promise<Response>;
|
|
117
|
+
readonly shutdown: () => Promise<void>;
|
|
118
|
+
};
|
|
119
|
+
declare const onElectron: (app: HttpApp, options?: ElectronAppOptions) => Promise<OnElectronApp>;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { ElectronAdaptor, type ElectronAppOptions, ElectronEnvAdaptor, type ElectronReady, ElectronWindowRegistryService, ElectronWindowRuntimeService, type OnElectronApp, type WindowDefinition, type WindowHandle, type WindowId, type WindowLoadTarget, type WindowOpenHandlerResult, type WindowRuntime, onElectron, setupIpcBridge, toIpcResponse, toRequest };
|
|
122
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { Config, EnvAdaptor, Injectable, LifecycleManager, inject } from "@zeltjs/core";
|
|
2
|
+
import { match } from "ts-pattern";
|
|
3
|
+
//#region src/main/electron.adaptor.ts
|
|
4
|
+
function _ts_decorate$3(decorators, target, key, desc) {
|
|
5
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
7
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
8
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9
|
+
}
|
|
10
|
+
function _ts_metadata$2(k, v) {
|
|
11
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
12
|
+
}
|
|
13
|
+
var ElectronAdaptor = class {
|
|
14
|
+
async startup() {
|
|
15
|
+
const { app, BrowserWindow: BW, dialog, ipcMain, Menu, protocol, screen, shell } = await import("electron");
|
|
16
|
+
await app.whenReady();
|
|
17
|
+
return {
|
|
18
|
+
app,
|
|
19
|
+
ipcMain,
|
|
20
|
+
protocol,
|
|
21
|
+
shell,
|
|
22
|
+
screen,
|
|
23
|
+
dialog,
|
|
24
|
+
Menu,
|
|
25
|
+
createBrowserWindow: (options) => new BW(options),
|
|
26
|
+
getAllWindows: () => BW.getAllWindows(),
|
|
27
|
+
fromWebContents: (wc) => BW.fromWebContents(wc),
|
|
28
|
+
fromId: (id) => BW.fromId(id),
|
|
29
|
+
getFocusedWindow: () => BW.getFocusedWindow()
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
shutdown() {
|
|
33
|
+
this.ready.app.quit();
|
|
34
|
+
}
|
|
35
|
+
constructor(lifecycleManager = inject(LifecycleManager)) {
|
|
36
|
+
this.ready = lifecycleManager.register(this);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
ElectronAdaptor = _ts_decorate$3([
|
|
40
|
+
Injectable(),
|
|
41
|
+
_ts_metadata$2("design:type", Function),
|
|
42
|
+
_ts_metadata$2("design:paramtypes", [void 0])
|
|
43
|
+
], ElectronAdaptor);
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/main/electron-env.adaptor.ts
|
|
46
|
+
function _ts_decorate$2(decorators, target, key, desc) {
|
|
47
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
48
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
49
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
50
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
51
|
+
}
|
|
52
|
+
var ElectronEnvAdaptor = class extends EnvAdaptor {
|
|
53
|
+
get(key) {
|
|
54
|
+
return process.env[key];
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
ElectronEnvAdaptor = _ts_decorate$2([Config], ElectronEnvAdaptor);
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/main/electron-window-runtime.service.ts
|
|
60
|
+
function _ts_decorate$1(decorators, target, key, desc) {
|
|
61
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
62
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
63
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
64
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
65
|
+
}
|
|
66
|
+
function _ts_metadata$1(k, v) {
|
|
67
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
68
|
+
}
|
|
69
|
+
var ElectronWindowRuntimeService = class {
|
|
70
|
+
open(definition) {
|
|
71
|
+
const handle = this.createWindowHandle(this.electronApp.ready.createBrowserWindow(definition.options));
|
|
72
|
+
if (definition.loadTarget.type === "url") handle.loadURL(definition.loadTarget.url);
|
|
73
|
+
else handle.loadFile(definition.loadTarget.path);
|
|
74
|
+
return handle;
|
|
75
|
+
}
|
|
76
|
+
createWindowHandle(win) {
|
|
77
|
+
return {
|
|
78
|
+
id: win.id,
|
|
79
|
+
native: win,
|
|
80
|
+
close: () => win.close(),
|
|
81
|
+
focus: () => win.focus(),
|
|
82
|
+
show: () => win.show(),
|
|
83
|
+
isDestroyed: () => win.isDestroyed(),
|
|
84
|
+
getTitle: () => win.getTitle(),
|
|
85
|
+
getBounds: () => win.getBounds(),
|
|
86
|
+
setBounds: (bounds) => win.setBounds(bounds),
|
|
87
|
+
loadFile: (path) => {
|
|
88
|
+
win.loadFile(path);
|
|
89
|
+
},
|
|
90
|
+
loadURL: (url) => {
|
|
91
|
+
win.loadURL(url);
|
|
92
|
+
},
|
|
93
|
+
on: (event, handler) => {
|
|
94
|
+
match(event).with("closed", (e) => win.on(e, handler)).with("ready-to-show", (e) => win.on(e, handler)).exhaustive();
|
|
95
|
+
},
|
|
96
|
+
removeListener: (event, handler) => {
|
|
97
|
+
match(event).with("closed", (e) => win.removeListener(e, handler)).with("ready-to-show", (e) => win.removeListener(e, handler)).exhaustive();
|
|
98
|
+
},
|
|
99
|
+
webContents: {
|
|
100
|
+
send: (channel, ...args) => win.webContents.send(channel, ...args),
|
|
101
|
+
setWindowOpenHandler: (handler) => win.webContents.setWindowOpenHandler(handler)
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
constructor(electronApp = inject(ElectronAdaptor)) {
|
|
106
|
+
this.electronApp = electronApp;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
ElectronWindowRuntimeService = _ts_decorate$1([
|
|
110
|
+
Injectable(),
|
|
111
|
+
_ts_metadata$1("design:type", Function),
|
|
112
|
+
_ts_metadata$1("design:paramtypes", [typeof ElectronAdaptor === "undefined" ? Object : ElectronAdaptor])
|
|
113
|
+
], ElectronWindowRuntimeService);
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/main/electron-window-registry.service.ts
|
|
116
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
117
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
118
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
119
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
120
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
121
|
+
}
|
|
122
|
+
function _ts_metadata(k, v) {
|
|
123
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
124
|
+
}
|
|
125
|
+
var ElectronWindowRegistryService = class {
|
|
126
|
+
open(definition) {
|
|
127
|
+
const existing = this.windows.get(definition.id);
|
|
128
|
+
if (existing && !existing.isDestroyed()) {
|
|
129
|
+
existing.focus();
|
|
130
|
+
return existing;
|
|
131
|
+
}
|
|
132
|
+
const handle = this.runtime.open(definition);
|
|
133
|
+
this.windows.set(definition.id, handle);
|
|
134
|
+
handle.on("closed", () => {
|
|
135
|
+
this.windows.delete(definition.id);
|
|
136
|
+
});
|
|
137
|
+
return handle;
|
|
138
|
+
}
|
|
139
|
+
close(id) {
|
|
140
|
+
const handle = this.windows.get(id);
|
|
141
|
+
if (handle && !handle.isDestroyed()) handle.close();
|
|
142
|
+
}
|
|
143
|
+
closeAll() {
|
|
144
|
+
for (const handle of this.windows.values()) if (!handle.isDestroyed()) handle.close();
|
|
145
|
+
}
|
|
146
|
+
count() {
|
|
147
|
+
return this.windows.size;
|
|
148
|
+
}
|
|
149
|
+
constructor(runtime = inject(ElectronWindowRuntimeService)) {
|
|
150
|
+
this.runtime = runtime;
|
|
151
|
+
this.windows = /* @__PURE__ */ new Map();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
ElectronWindowRegistryService = _ts_decorate([
|
|
155
|
+
Injectable(),
|
|
156
|
+
_ts_metadata("design:type", Function),
|
|
157
|
+
_ts_metadata("design:paramtypes", [void 0])
|
|
158
|
+
], ElectronWindowRegistryService);
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/main/ipc-bridge.ts
|
|
161
|
+
const BODY_FORBIDDEN_METHODS = new Set(["GET", "HEAD"]);
|
|
162
|
+
const NO_BODY_STATUSES = new Set([
|
|
163
|
+
204,
|
|
164
|
+
205,
|
|
165
|
+
304
|
|
166
|
+
]);
|
|
167
|
+
const TEXT_CONTENT_TYPE_PREFIXES = [
|
|
168
|
+
"text/",
|
|
169
|
+
"application/json",
|
|
170
|
+
"application/xml",
|
|
171
|
+
"application/javascript",
|
|
172
|
+
"application/x-www-form-urlencoded"
|
|
173
|
+
];
|
|
174
|
+
const isTextContentType = (contentType) => TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));
|
|
175
|
+
const toBody = (body) => match(body).with({ kind: "none" }, () => null).with({ kind: "text" }, ({ value }) => value).with({ kind: "arrayBuffer" }, ({ value }) => value).exhaustive();
|
|
176
|
+
const toRequest = (payload, baseUrl) => {
|
|
177
|
+
const headers = payload.headers.map(([k, v]) => [k, v]);
|
|
178
|
+
return new Request(baseUrl + payload.path, {
|
|
179
|
+
method: payload.method,
|
|
180
|
+
headers,
|
|
181
|
+
body: BODY_FORBIDDEN_METHODS.has(payload.method) ? null : toBody(payload.body)
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
const toIpcResponse = async (response, method) => {
|
|
185
|
+
const headers = [];
|
|
186
|
+
response.headers.forEach((value, key) => {
|
|
187
|
+
headers.push([key, value]);
|
|
188
|
+
});
|
|
189
|
+
let body;
|
|
190
|
+
if (NO_BODY_STATUSES.has(response.status) || method === "HEAD") body = { kind: "none" };
|
|
191
|
+
else {
|
|
192
|
+
const contentType = response.headers.get("content-type");
|
|
193
|
+
if (contentType && isTextContentType(contentType)) body = {
|
|
194
|
+
kind: "text",
|
|
195
|
+
value: await response.text()
|
|
196
|
+
};
|
|
197
|
+
else body = {
|
|
198
|
+
kind: "arrayBuffer",
|
|
199
|
+
value: await response.arrayBuffer()
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
status: response.status,
|
|
204
|
+
statusText: response.statusText,
|
|
205
|
+
headers,
|
|
206
|
+
body
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
const setupIpcBridge = (ipcMain, fetch, channel) => {
|
|
210
|
+
ipcMain.handle(channel, async (_event, payload) => {
|
|
211
|
+
return toIpcResponse(await fetch(toRequest(payload, channel)), payload.method);
|
|
212
|
+
});
|
|
213
|
+
return () => {
|
|
214
|
+
ipcMain.removeHandler(channel);
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/main/on-electron.ts
|
|
219
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
220
|
+
const onElectron = async (app, options = {}) => {
|
|
221
|
+
const readyApp = await app.createRuntime({
|
|
222
|
+
fallbackConfigs: [ElectronEnvAdaptor],
|
|
223
|
+
warmup: options.warmup ?? true
|
|
224
|
+
});
|
|
225
|
+
const electronApp = await readyApp.get(ElectronAdaptor);
|
|
226
|
+
const channel = options.ipcChannel ?? DEFAULT_IPC_CHANNEL;
|
|
227
|
+
const removeIpcHandler = setupIpcBridge(electronApp.ready.ipcMain, readyApp.http.fetch, channel);
|
|
228
|
+
return {
|
|
229
|
+
get: readyApp.get,
|
|
230
|
+
fetch: readyApp.http.fetch,
|
|
231
|
+
shutdown: async () => {
|
|
232
|
+
removeIpcHandler();
|
|
233
|
+
await readyApp.shutdown();
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
//#endregion
|
|
238
|
+
export { ElectronAdaptor, ElectronEnvAdaptor, ElectronWindowRegistryService, ElectronWindowRuntimeService, onElectron, setupIpcBridge, toIpcResponse, toRequest };
|
|
239
|
+
|
|
240
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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","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","path","method","has","toIpcResponse","response","forEach","key","push","status","get","text","arrayBuffer","statusText","setupIpcBridge","ipcMain","fetch","channel","handle","_event","request","removeHandler","ElectronAdaptor","ElectronEnvAdaptor","setupIpcBridge","DEFAULT_IPC_CHANNEL","onElectron","app","options","readyApp","createRuntime","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 { 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 + 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\ntype IpcMainLike = {\n handle(channel: string, listener: (event: unknown, payload: IpcFetchRequest) => unknown): void;\n removeHandler(channel: string): void;\n};\n\nexport const setupIpcBridge = (\n ipcMain: IpcMainLike,\n fetch: (request: Request) => Promise<Response>,\n channel: string,\n): (() => void) => {\n ipcMain.handle(channel, async (_event: unknown, payload: IpcFetchRequest) => {\n const request = toRequest(payload, channel);\n const response = await fetch(request);\n return toIpcResponse(response, payload.method);\n });\n\n return () => {\n ipcMain.removeHandler(channel);\n };\n};\n","import type {\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 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\nexport const onElectron = async (\n app: HttpApp,\n options: ElectronAppOptions = {},\n): Promise<OnElectronApp> => {\n const readyApp = await app.createRuntime({\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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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/preload/expose-ipc.ts
|
|
3
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
4
|
+
const loadElectron = () => {
|
|
5
|
+
return require("electron");
|
|
6
|
+
};
|
|
7
|
+
const exposeIpc = (options = {}) => {
|
|
8
|
+
const channel = options.channel ?? DEFAULT_IPC_CHANNEL;
|
|
9
|
+
const { contextBridge, ipcRenderer } = loadElectron();
|
|
10
|
+
const sender = (request) => ipcRenderer.invoke(channel, request);
|
|
11
|
+
if (process.contextIsolated) contextBridge.exposeInMainWorld(channel, sender);
|
|
12
|
+
else Reflect.set(globalThis, channel, sender);
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.exposeIpc = exposeIpc;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, r as IpcSender, t as IpcFetchRequest } from "../ipc.types-DgxeccV3.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/preload/expose-ipc.d.ts
|
|
4
|
+
type ExposeIpcOptions = {
|
|
5
|
+
readonly channel?: string;
|
|
6
|
+
};
|
|
7
|
+
declare const exposeIpc: (options?: ExposeIpcOptions) => void;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { type ExposeIpcOptions, type IpcFetchRequest, type IpcFetchResponse, type IpcSender, exposeIpc };
|
|
10
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/preload/expose-ipc.ts"],"mappings":";;;KAMY,gBAAA;EAAA,SACD,OAAA;AAAA;AAAA,cAcE,SAAA,GAAa,OAAA,GAAS,gBAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, r as IpcSender, t as IpcFetchRequest } from "../ipc.types-OYZhXKH2.js";
|
|
2
|
+
|
|
3
|
+
//#region src/preload/expose-ipc.d.ts
|
|
4
|
+
type ExposeIpcOptions = {
|
|
5
|
+
readonly channel?: string;
|
|
6
|
+
};
|
|
7
|
+
declare const exposeIpc: (options?: ExposeIpcOptions) => void;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { type ExposeIpcOptions, type IpcFetchRequest, type IpcFetchResponse, type IpcSender, exposeIpc };
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/preload/expose-ipc.ts"],"mappings":";;;KAMY,gBAAA;EAAA,SACD,OAAA;AAAA;AAAA,cAcE,SAAA,GAAa,OAAA,GAAS,gBAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/preload/expose-ipc.ts
|
|
6
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
7
|
+
const loadElectron = () => {
|
|
8
|
+
return __require("electron");
|
|
9
|
+
};
|
|
10
|
+
const exposeIpc = (options = {}) => {
|
|
11
|
+
const channel = options.channel ?? DEFAULT_IPC_CHANNEL;
|
|
12
|
+
const { contextBridge, ipcRenderer } = loadElectron();
|
|
13
|
+
const sender = (request) => ipcRenderer.invoke(channel, request);
|
|
14
|
+
if (process.contextIsolated) contextBridge.exposeInMainWorld(channel, sender);
|
|
15
|
+
else Reflect.set(globalThis, channel, sender);
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { exposeIpc };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["DEFAULT_IPC_CHANNEL","loadElectron","mod","require","exposeIpc","options","channel","contextBridge","ipcRenderer","sender","request","invoke","process","contextIsolated","exposeInMainWorld","Reflect","set","globalThis"],"sources":["../../src/preload/expose-ipc.ts"],"sourcesContent":["import type { ContextBridge, IpcRenderer } from 'electron';\n\nimport type { IpcFetchRequest, IpcFetchResponse } from '../shared/ipc.types';\n\nconst DEFAULT_IPC_CHANNEL = 'http://zelt-ipc';\n\nexport type ExposeIpcOptions = {\n readonly channel?: string;\n};\n\ntype ElectronPreload = {\n readonly contextBridge: ContextBridge;\n readonly ipcRenderer: IpcRenderer;\n};\n\n// In the preload context electron is only available via require (no ESM in preload).\nconst loadElectron = (): ElectronPreload => {\n const mod: ElectronPreload = require('electron');\n return mod;\n};\n\nexport const exposeIpc = (options: ExposeIpcOptions = {}): void => {\n const channel = options.channel ?? DEFAULT_IPC_CHANNEL;\n const { contextBridge, ipcRenderer } = loadElectron();\n\n const sender = (request: IpcFetchRequest): Promise<IpcFetchResponse> =>\n ipcRenderer.invoke(channel, request);\n\n if (process.contextIsolated) {\n contextBridge.exposeInMainWorld(channel, sender);\n } else {\n Reflect.set(globalThis, channel, sender);\n }\n};\n"],"mappings":";;;;;AAIA,MAAMA,sBAAsB;AAY5B,MAAMC,qBAAe;AAEnB,QAAA,UADqC,WAC9BC;;AAGT,MAAaE,aAAaC,UAA4B,EAAE,KAAA;CACtD,MAAMC,UAAUD,QAAQC,WAAWN;CACnC,MAAM,EAAEO,eAAeC,gBAAgBP,cAAAA;CAEvC,MAAMQ,UAAUC,YACdF,YAAYG,OAAOL,SAASI,QAAAA;AAE9B,KAAIE,QAAQC,gBACVN,eAAcO,kBAAkBR,SAASG,OAAAA;KAEzCM,SAAQC,IAAIC,YAAYX,SAASG,OAAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/renderer/ipc-fetch.ts
|
|
3
|
+
const TEXT_CONTENT_TYPE_PREFIXES = [
|
|
4
|
+
"text/",
|
|
5
|
+
"application/json",
|
|
6
|
+
"application/xml",
|
|
7
|
+
"application/javascript",
|
|
8
|
+
"application/x-www-form-urlencoded"
|
|
9
|
+
];
|
|
10
|
+
const isTextContentType = (contentType) => TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));
|
|
11
|
+
const toIpcRequest = async (input, init) => {
|
|
12
|
+
const request = new Request(input, init);
|
|
13
|
+
const url = new URL(request.url);
|
|
14
|
+
const headers = [];
|
|
15
|
+
request.headers.forEach((value, key) => {
|
|
16
|
+
headers.push([key, value]);
|
|
17
|
+
});
|
|
18
|
+
let body;
|
|
19
|
+
if (request.body === null) body = { kind: "none" };
|
|
20
|
+
else {
|
|
21
|
+
const contentType = request.headers.get("content-type");
|
|
22
|
+
if (contentType && isTextContentType(contentType)) body = {
|
|
23
|
+
kind: "text",
|
|
24
|
+
value: await request.text()
|
|
25
|
+
};
|
|
26
|
+
else body = {
|
|
27
|
+
kind: "arrayBuffer",
|
|
28
|
+
value: await request.arrayBuffer()
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
method: request.method,
|
|
33
|
+
path: url.pathname + url.search,
|
|
34
|
+
headers,
|
|
35
|
+
body
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const toResponse = (payload) => {
|
|
39
|
+
let body = null;
|
|
40
|
+
if (payload.body.kind === "text") body = payload.body.value;
|
|
41
|
+
else if (payload.body.kind === "arrayBuffer") body = payload.body.value;
|
|
42
|
+
const headers = payload.headers.map(([k, v]) => [k, v]);
|
|
43
|
+
return new Response(body, {
|
|
44
|
+
status: payload.status,
|
|
45
|
+
statusText: payload.statusText,
|
|
46
|
+
headers
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
50
|
+
/**
|
|
51
|
+
* @throws {Error} when the IPC sender is not registered for the given channel
|
|
52
|
+
*/ const ipcFetch = async (input, init, options) => {
|
|
53
|
+
const channel = options?.channel ?? DEFAULT_IPC_CHANNEL;
|
|
54
|
+
const senderCandidate = Reflect.get(globalThis, channel);
|
|
55
|
+
if (typeof senderCandidate !== "function") throw new Error(`IPC sender not found for channel "${channel}". Did you call exposeIpc() in the preload script?`);
|
|
56
|
+
const ipcRequest = await toIpcRequest(input, init);
|
|
57
|
+
return toResponse(await senderCandidate.call(null, ipcRequest));
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
exports.ipcFetch = ipcFetch;
|
|
61
|
+
exports.toIpcRequest = toIpcRequest;
|
|
62
|
+
exports.toResponse = toResponse;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, r as IpcSender, t as IpcFetchRequest } from "../ipc.types-DgxeccV3.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/renderer/ipc-fetch.d.ts
|
|
4
|
+
declare const toIpcRequest: (input: RequestInfo | URL, init?: RequestInit) => Promise<IpcFetchRequest>;
|
|
5
|
+
declare const toResponse: (payload: IpcFetchResponse) => Response;
|
|
6
|
+
type IpcFetchOptions = {
|
|
7
|
+
readonly channel?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @throws {Error} when the IPC sender is not registered for the given channel
|
|
11
|
+
*/
|
|
12
|
+
declare const ipcFetch: (input: RequestInfo | URL, init?: RequestInit, options?: IpcFetchOptions) => Promise<Response>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { type IpcFetchOptions, type IpcFetchRequest, type IpcFetchResponse, type IpcSender, ipcFetch, toIpcRequest, toResponse };
|
|
15
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/renderer/ipc-fetch.ts"],"mappings":";;;cAaa,YAAA,GACX,KAAA,EAAO,WAAA,GAAc,GAAA,EACrB,IAAA,GAAO,WAAA,KACN,OAAA,CAAQ,eAAA;AAAA,cA6BE,UAAA,GAAc,OAAA,EAAS,gBAAA,KAAmB,QAAA;AAAA,KAkB3C,eAAA;EAAA,SACD,OAAA;AAAA;;;;cAME,QAAA,GACX,KAAA,EAAO,WAAA,GAAc,GAAA,EACrB,IAAA,GAAO,WAAA,EACP,OAAA,GAAU,eAAA,KACT,OAAA,CAAQ,QAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { n as IpcFetchResponse, r as IpcSender, t as IpcFetchRequest } from "../ipc.types-OYZhXKH2.js";
|
|
2
|
+
|
|
3
|
+
//#region src/renderer/ipc-fetch.d.ts
|
|
4
|
+
declare const toIpcRequest: (input: RequestInfo | URL, init?: RequestInit) => Promise<IpcFetchRequest>;
|
|
5
|
+
declare const toResponse: (payload: IpcFetchResponse) => Response;
|
|
6
|
+
type IpcFetchOptions = {
|
|
7
|
+
readonly channel?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @throws {Error} when the IPC sender is not registered for the given channel
|
|
11
|
+
*/
|
|
12
|
+
declare const ipcFetch: (input: RequestInfo | URL, init?: RequestInit, options?: IpcFetchOptions) => Promise<Response>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { type IpcFetchOptions, type IpcFetchRequest, type IpcFetchResponse, type IpcSender, ipcFetch, toIpcRequest, toResponse };
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/renderer/ipc-fetch.ts"],"mappings":";;;cAaa,YAAA,GACX,KAAA,EAAO,WAAA,GAAc,GAAA,EACrB,IAAA,GAAO,WAAA,KACN,OAAA,CAAQ,eAAA;AAAA,cA6BE,UAAA,GAAc,OAAA,EAAS,gBAAA,KAAmB,QAAA;AAAA,KAkB3C,eAAA;EAAA,SACD,OAAA;AAAA;;;;cAME,QAAA,GACX,KAAA,EAAO,WAAA,GAAc,GAAA,EACrB,IAAA,GAAO,WAAA,EACP,OAAA,GAAU,eAAA,KACT,OAAA,CAAQ,QAAA"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
//#region src/renderer/ipc-fetch.ts
|
|
2
|
+
const TEXT_CONTENT_TYPE_PREFIXES = [
|
|
3
|
+
"text/",
|
|
4
|
+
"application/json",
|
|
5
|
+
"application/xml",
|
|
6
|
+
"application/javascript",
|
|
7
|
+
"application/x-www-form-urlencoded"
|
|
8
|
+
];
|
|
9
|
+
const isTextContentType = (contentType) => TEXT_CONTENT_TYPE_PREFIXES.some((prefix) => contentType.startsWith(prefix));
|
|
10
|
+
const toIpcRequest = async (input, init) => {
|
|
11
|
+
const request = new Request(input, init);
|
|
12
|
+
const url = new URL(request.url);
|
|
13
|
+
const headers = [];
|
|
14
|
+
request.headers.forEach((value, key) => {
|
|
15
|
+
headers.push([key, value]);
|
|
16
|
+
});
|
|
17
|
+
let body;
|
|
18
|
+
if (request.body === null) body = { kind: "none" };
|
|
19
|
+
else {
|
|
20
|
+
const contentType = request.headers.get("content-type");
|
|
21
|
+
if (contentType && isTextContentType(contentType)) body = {
|
|
22
|
+
kind: "text",
|
|
23
|
+
value: await request.text()
|
|
24
|
+
};
|
|
25
|
+
else body = {
|
|
26
|
+
kind: "arrayBuffer",
|
|
27
|
+
value: await request.arrayBuffer()
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
method: request.method,
|
|
32
|
+
path: url.pathname + url.search,
|
|
33
|
+
headers,
|
|
34
|
+
body
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
const toResponse = (payload) => {
|
|
38
|
+
let body = null;
|
|
39
|
+
if (payload.body.kind === "text") body = payload.body.value;
|
|
40
|
+
else if (payload.body.kind === "arrayBuffer") body = payload.body.value;
|
|
41
|
+
const headers = payload.headers.map(([k, v]) => [k, v]);
|
|
42
|
+
return new Response(body, {
|
|
43
|
+
status: payload.status,
|
|
44
|
+
statusText: payload.statusText,
|
|
45
|
+
headers
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const DEFAULT_IPC_CHANNEL = "http://zelt-ipc";
|
|
49
|
+
/**
|
|
50
|
+
* @throws {Error} when the IPC sender is not registered for the given channel
|
|
51
|
+
*/ const ipcFetch = async (input, init, options) => {
|
|
52
|
+
const channel = options?.channel ?? DEFAULT_IPC_CHANNEL;
|
|
53
|
+
const senderCandidate = Reflect.get(globalThis, channel);
|
|
54
|
+
if (typeof senderCandidate !== "function") throw new Error(`IPC sender not found for channel "${channel}". Did you call exposeIpc() in the preload script?`);
|
|
55
|
+
const ipcRequest = await toIpcRequest(input, init);
|
|
56
|
+
return toResponse(await senderCandidate.call(null, ipcRequest));
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { ipcFetch, toIpcRequest, toResponse };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["TEXT_CONTENT_TYPE_PREFIXES","isTextContentType","contentType","some","prefix","startsWith","toIpcRequest","input","init","request","Request","url","URL","headers","forEach","value","key","push","body","kind","get","text","arrayBuffer","method","path","pathname","search","toResponse","payload","map","k","v","Response","status","statusText","DEFAULT_IPC_CHANNEL","ipcFetch","options","channel","senderCandidate","Reflect","globalThis","Error","ipcRequest","call"],"sources":["../../src/renderer/ipc-fetch.ts"],"sourcesContent":["import type { IpcBody, IpcFetchRequest, IpcFetchResponse } from '../shared/ipc.types';\n\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\nexport const toIpcRequest = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n): Promise<IpcFetchRequest> => {\n const request = new Request(input, init);\n const url = new URL(request.url);\n\n const headers: [string, string][] = [];\n request.headers.forEach((value, key) => {\n headers.push([key, value]);\n });\n\n let body: IpcBody;\n if (request.body === null) {\n body = { kind: 'none' };\n } else {\n const contentType = request.headers.get('content-type');\n if (contentType && isTextContentType(contentType)) {\n body = { kind: 'text', value: await request.text() };\n } else {\n body = { kind: 'arrayBuffer', value: await request.arrayBuffer() };\n }\n }\n\n return {\n method: request.method,\n path: url.pathname + url.search,\n headers,\n body,\n };\n};\n\nexport const toResponse = (payload: IpcFetchResponse): Response => {\n let body: BodyInit | null = null;\n if (payload.body.kind === 'text') {\n body = payload.body.value;\n } else if (payload.body.kind === 'arrayBuffer') {\n body = payload.body.value;\n }\n\n const headers: [string, string][] = payload.headers.map(([k, v]) => [k, v]);\n return new Response(body, {\n status: payload.status,\n statusText: payload.statusText,\n headers,\n });\n};\n\nconst DEFAULT_IPC_CHANNEL = 'http://zelt-ipc';\n\nexport type IpcFetchOptions = {\n readonly channel?: string;\n};\n\n/**\n * @throws {Error} when the IPC sender is not registered for the given channel\n */\nexport const ipcFetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n options?: IpcFetchOptions,\n): Promise<Response> => {\n const channel = options?.channel ?? DEFAULT_IPC_CHANNEL;\n const senderCandidate: unknown = Reflect.get(globalThis, channel);\n\n if (typeof senderCandidate !== 'function') {\n throw new Error(\n `IPC sender not found for channel \"${channel}\". Did you call exposeIpc() in the preload script?`,\n );\n }\n\n const ipcRequest = await toIpcRequest(input, init);\n return toResponse(await senderCandidate.call(null, ipcRequest));\n};\n"],"mappings":";AAEA,MAAMA,6BAA6B;CACjC;CACA;CACA;CACA;CACA;CACD;AAED,MAAMC,qBAAqBC,gBACzBF,2BAA2BG,MAAMC,WAAWF,YAAYG,WAAWD,OAAAA,CAAAA;AAErE,MAAaE,eAAe,OAC1BC,OACAC,SAAAA;CAEA,MAAMC,UAAU,IAAIC,QAAQH,OAAOC,KAAAA;CACnC,MAAMG,MAAM,IAAIC,IAAIH,QAAQE,IAAG;CAE/B,MAAME,UAA8B,EAAE;AACtCJ,SAAQI,QAAQC,SAASC,OAAOC,QAAAA;AAC9BH,UAAQI,KAAK,CAACD,KAAKD,MAAM,CAAA;GAC3B;CAEA,IAAIG;AACJ,KAAIT,QAAQS,SAAS,KACnBA,QAAO,EAAEC,MAAM,QAAO;MACjB;EACL,MAAMjB,cAAcO,QAAQI,QAAQO,IAAI,eAAA;AACxC,MAAIlB,eAAeD,kBAAkBC,YAAAA,CACnCgB,QAAO;GAAEC,MAAM;GAAQJ,OAAO,MAAMN,QAAQY,MAAI;GAAG;MAEnDH,QAAO;GAAEC,MAAM;GAAeJ,OAAO,MAAMN,QAAQa,aAAW;GAAG;;AAIrE,QAAO;EACLC,QAAQd,QAAQc;EAChBC,MAAMb,IAAIc,WAAWd,IAAIe;EACzBb;EACAK;EACF;;AAGF,MAAaS,cAAcC,YAAAA;CACzB,IAAIV,OAAwB;AAC5B,KAAIU,QAAQV,KAAKC,SAAS,OACxBD,QAAOU,QAAQV,KAAKH;UACXa,QAAQV,KAAKC,SAAS,cAC/BD,QAAOU,QAAQV,KAAKH;CAGtB,MAAMF,UAA8Be,QAAQf,QAAQgB,KAAK,CAACC,GAAGC,OAAO,CAACD,GAAGC,EAAE,CAAA;AAC1E,QAAO,IAAIC,SAASd,MAAM;EACxBe,QAAQL,QAAQK;EAChBC,YAAYN,QAAQM;EACpBrB;EACF,CAAA;;AAGF,MAAMsB,sBAAsB;;;GAS5B,MAAaC,WAAW,OACtB7B,OACAC,MACA6B,YAAAA;CAEA,MAAMC,UAAUD,SAASC,WAAWH;CACpC,MAAMI,kBAA2BC,QAAQpB,IAAIqB,YAAYH,QAAAA;AAEzD,KAAI,OAAOC,oBAAoB,WAC7B,OAAM,IAAIG,MACR,qCAAqCJ,QAAQ,oDAAmD;CAIpG,MAAMK,aAAa,MAAMrC,aAAaC,OAAOC,KAAAA;AAC7C,QAAOmB,WAAW,MAAMY,gBAAgBK,KAAK,MAAMD,WAAAA,CAAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeltjs/adapter-electron",
|
|
3
|
-
"version": "0.8.1",
|
|
3
|
+
"version": "0.8.2-canary.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -13,15 +13,43 @@
|
|
|
13
13
|
},
|
|
14
14
|
"exports": {
|
|
15
15
|
".": {
|
|
16
|
-
"
|
|
17
|
-
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/main/index.d.ts",
|
|
18
|
+
"default": "./dist/main/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/main/index.d.cts",
|
|
22
|
+
"default": "./dist/main/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"./preload": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/preload/index.d.ts",
|
|
28
|
+
"default": "./dist/preload/index.js"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./dist/preload/index.d.cts",
|
|
32
|
+
"default": "./dist/preload/index.cjs"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"./renderer": {
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/renderer/index.d.ts",
|
|
38
|
+
"default": "./dist/renderer/index.js"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./dist/renderer/index.d.cts",
|
|
42
|
+
"default": "./dist/renderer/index.cjs"
|
|
43
|
+
}
|
|
18
44
|
}
|
|
19
45
|
},
|
|
46
|
+
"main": "./dist/main/index.cjs",
|
|
20
47
|
"files": [
|
|
21
48
|
"dist"
|
|
22
49
|
],
|
|
23
50
|
"dependencies": {
|
|
24
|
-
"
|
|
51
|
+
"ts-pattern": "5.7.1",
|
|
52
|
+
"@zeltjs/core": "0.8.2-canary.1"
|
|
25
53
|
},
|
|
26
54
|
"devDependencies": {
|
|
27
55
|
"@types/node": "22.19.17"
|
|
@@ -29,11 +57,6 @@
|
|
|
29
57
|
"peerDependencies": {
|
|
30
58
|
"electron": ">=28.0.0"
|
|
31
59
|
},
|
|
32
|
-
"peerDependenciesMeta": {
|
|
33
|
-
"electron": {
|
|
34
|
-
"optional": true
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
60
|
"volta": {
|
|
38
61
|
"extends": "../../package.json"
|
|
39
62
|
},
|
package/dist/index.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { EnvAdaptor, HttpApp, ReadyResult } from "@zeltjs/core";
|
|
2
|
-
|
|
3
|
-
//#region src/electron-env.adaptor.d.ts
|
|
4
|
-
declare class ElectronEnvAdaptor extends EnvAdaptor {
|
|
5
|
-
get(key: string): string | undefined;
|
|
6
|
-
}
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region src/on-electron.d.ts
|
|
9
|
-
type ElectronAppOptions = {
|
|
10
|
-
readonly warmup?: boolean;
|
|
11
|
-
};
|
|
12
|
-
type ElectronApp = ReadyResult & {
|
|
13
|
-
readonly fetch: (request: Request) => Promise<Response>;
|
|
14
|
-
readonly shutdown: () => Promise<void>;
|
|
15
|
-
};
|
|
16
|
-
declare const onElectron: (app: HttpApp, options?: ElectronAppOptions) => Promise<ElectronApp>;
|
|
17
|
-
//#endregion
|
|
18
|
-
export { type ElectronApp, type ElectronAppOptions, ElectronEnvAdaptor, onElectron };
|
|
19
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/electron-env.adaptor.ts","../src/on-electron.ts"],"mappings":";;;cAGa,kBAAA,SAA2B,UAAA;EAC7B,GAAA,CAAI,GAAA;AAAA;;;KCAH,kBAAA;EAAA,SACD,MAAA;AAAA;AAAA,KAGC,WAAA,GAAc,WAAA;EAAA,SACf,KAAA,GAAQ,OAAA,EAAS,OAAA,KAAY,OAAA,CAAQ,QAAA;EAAA,SACrC,QAAA,QAAgB,OAAA;AAAA;AAAA,cAGd,UAAA,GACX,GAAA,EAAK,OAAA,EACL,OAAA,GAAS,kBAAA,KACR,OAAA,CAAQ,WAAA"}
|
package/dist/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Config, EnvAdaptor } from "@zeltjs/core";
|
|
2
|
-
//#region src/electron-env.adaptor.ts
|
|
3
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
4
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
5
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
6
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
7
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
8
|
-
}
|
|
9
|
-
var ElectronEnvAdaptor = class extends EnvAdaptor {
|
|
10
|
-
get(key) {
|
|
11
|
-
return process.env[key];
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
ElectronEnvAdaptor = _ts_decorate([Config], ElectronEnvAdaptor);
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/on-electron.ts
|
|
17
|
-
const onElectron = async (app, options = {}) => {
|
|
18
|
-
app.addFallbackConfig(ElectronEnvAdaptor);
|
|
19
|
-
const readyOptions = { warmup: options.warmup ?? true };
|
|
20
|
-
return {
|
|
21
|
-
...await app.ready(readyOptions),
|
|
22
|
-
fetch: app.fetch,
|
|
23
|
-
shutdown: app.shutdown
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
export { ElectronEnvAdaptor, onElectron };
|
|
28
|
-
|
|
29
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Config","EnvAdaptor","ElectronEnvAdaptor","get","key","process","env","ElectronEnvAdaptor","onElectron","app","options","addFallbackConfig","readyOptions","warmup","resolver","ready","fetch","shutdown"],"sources":["../src/electron-env.adaptor.ts","../src/on-electron.ts"],"sourcesContent":["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 type { HttpApp, ReadyOptions, ReadyResult } from '@zeltjs/core';\n\nimport { ElectronEnvAdaptor } from './electron-env.adaptor';\n\nexport type ElectronAppOptions = {\n readonly warmup?: boolean;\n};\n\nexport type ElectronApp = ReadyResult & {\n readonly fetch: (request: Request) => Promise<Response>;\n readonly shutdown: () => Promise<void>;\n};\n\nexport const onElectron = async (\n app: HttpApp,\n options: ElectronAppOptions = {},\n): Promise<ElectronApp> => {\n app.addFallbackConfig(ElectronEnvAdaptor);\n\n const readyOptions: ReadyOptions = { warmup: options.warmup ?? true };\n const resolver = await app.ready(readyOptions);\n\n return {\n ...resolver,\n fetch: app.fetch,\n shutdown: app.shutdown,\n };\n};\n"],"mappings":";;;;;;;;AAGA,IAAaE,qBAAb,cAAwCD,WAAAA;CAC7BE,IAAIC,KAAiC;AAC5C,SAAOC,QAAQC,IAAIF;;;;;;ACQvB,MAAaI,aAAa,OACxBC,KACAC,UAA8B,EAAE,KAAA;AAEhCD,KAAIE,kBAAkBJ,mBAAAA;CAEtB,MAAMK,eAA6B,EAAEC,QAAQH,QAAQG,UAAU,MAAK;AAGpE,QAAO;EACL,GAAGC,MAHkBL,IAAIM,MAAMH,aAAAA;EAI/BI,OAAOP,IAAIO;EACXC,UAAUR,IAAIQ;EAChB"}
|