electron-snapora 1.0.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/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.es.md +79 -0
- package/README.ja.md +79 -0
- package/README.ko.md +79 -0
- package/README.md +392 -0
- package/README.zh-CN.md +79 -0
- package/dist/core/index.cjs +184 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +97 -0
- package/dist/core/index.d.ts +97 -0
- package/dist/core/index.mjs +150 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/main/index.cjs +1637 -0
- package/dist/main/index.cjs.map +1 -0
- package/dist/main/index.d.cts +283 -0
- package/dist/main/index.d.ts +283 -0
- package/dist/main/index.mjs +1599 -0
- package/dist/main/index.mjs.map +1 -0
- package/dist/messages-DYY0MpGh.d.ts +76 -0
- package/dist/messages-ifub9bae.d.cts +76 -0
- package/dist/overlay/assets/index-7dVRGn83.css +1 -0
- package/dist/overlay/assets/index-CJf5iC1U.js +2 -0
- package/dist/overlay/assets/index-CJf5iC1U.js.map +1 -0
- package/dist/overlay/index.html +316 -0
- package/dist/overlay/preload.cjs +97 -0
- package/dist/overlay/preload.cjs.map +1 -0
- package/dist/overlay/preload.d.cts +16 -0
- package/dist/overlay/preload.d.ts +16 -0
- package/dist/overlay/preload.mjs +80 -0
- package/dist/overlay/preload.mjs.map +1 -0
- package/dist/preload/auto.cjs +24 -0
- package/dist/preload/auto.cjs.map +1 -0
- package/dist/preload/auto.d.cts +2 -0
- package/dist/preload/auto.d.ts +2 -0
- package/dist/preload/auto.mjs +22 -0
- package/dist/preload/auto.mjs.map +1 -0
- package/dist/preload/index.cjs +46 -0
- package/dist/preload/index.cjs.map +1 -0
- package/dist/preload/index.d.cts +18 -0
- package/dist/preload/index.d.ts +18 -0
- package/dist/preload/index.mjs +19 -0
- package/dist/preload/index.mjs.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +92 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/types/index.mjs +1 -0
- package/dist/types/index.mjs.map +1 -0
- package/package.json +158 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { BrowserWindowConstructorOptions, BrowserWindow, WebContents, IpcMain, IpcMainInvokeEvent } from 'electron';
|
|
2
|
+
import { ScreenshotErrorCode, ScreenshotOptions, ScreenshotResult } from '../types/index.js';
|
|
3
|
+
export { ScreenshotBounds, ScreenshotImageResult, ScreenshotLocale, ScreenshotMessageOverrides, ScreenshotMessages, ScreenshotOutputMetadata, ScreenshotTheme, ScreenshotTool } from '../types/index.js';
|
|
4
|
+
import { d as ScreenshotOutputPayload, e as ScreenshotOutputResponse, S as ScreenshotInitializePayload, C as CaptureDisplay, f as ScreenCaptureAdapter, g as CapturedFrame } from '../messages-DYY0MpGh.js';
|
|
5
|
+
export { h as SCREENSHOT_PROTOCOL_VERSION, i as ScreenshotCancelPayload, b as ScreenshotCompletePayload, c as ScreenshotErrorPayload, j as ScreenshotOutputAction, k as ScreenshotReadyPayload } from '../messages-DYY0MpGh.js';
|
|
6
|
+
|
|
7
|
+
type ScreenshotDiagnosticStage = 'queue' | 'session' | 'capture' | 'overlay-create' | 'overlay-load' | 'overlay-ready' | 'overlay-prepare' | 'output';
|
|
8
|
+
type ScreenshotDiagnosticPhase = 'start' | 'complete' | 'cancel' | 'error';
|
|
9
|
+
type ScreenshotDiagnosticContextValue = string | number | boolean | ReadonlyArray<string | number | boolean>;
|
|
10
|
+
interface ScreenshotDiagnosticEvent {
|
|
11
|
+
jobId: string;
|
|
12
|
+
stage: ScreenshotDiagnosticStage;
|
|
13
|
+
phase: ScreenshotDiagnosticPhase;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
durationMs?: number;
|
|
16
|
+
senderWebContentsId?: number;
|
|
17
|
+
code?: ScreenshotErrorCode;
|
|
18
|
+
message?: string;
|
|
19
|
+
context?: Readonly<Record<string, ScreenshotDiagnosticContextValue>>;
|
|
20
|
+
}
|
|
21
|
+
type ScreenshotDiagnosticListener = (event: Readonly<ScreenshotDiagnosticEvent>) => void;
|
|
22
|
+
|
|
23
|
+
interface ScreenshotOutputContext {
|
|
24
|
+
senderWebContentsId: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ElectronOutputAdapterOptions {
|
|
28
|
+
saveFile?: (data: Uint8Array, suggestedName: string, senderWebContentsId: number) => Promise<string | undefined>;
|
|
29
|
+
copyImage?: (data: Uint8Array) => void;
|
|
30
|
+
createSuggestedName?: () => string;
|
|
31
|
+
}
|
|
32
|
+
interface ScreenshotOutputExecutor {
|
|
33
|
+
execute(payload: ScreenshotOutputPayload, context: ScreenshotOutputContext): Promise<ScreenshotOutputResponse>;
|
|
34
|
+
}
|
|
35
|
+
declare class ElectronOutputAdapter implements ScreenshotOutputExecutor {
|
|
36
|
+
#private;
|
|
37
|
+
constructor(options?: ElectronOutputAdapterOptions);
|
|
38
|
+
execute(payload: ScreenshotOutputPayload, context: ScreenshotOutputContext): Promise<ScreenshotOutputResponse>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface OverlayResources {
|
|
42
|
+
htmlPath: string;
|
|
43
|
+
preloadPath: string;
|
|
44
|
+
}
|
|
45
|
+
type PackagedResourceExists = (path: string) => boolean;
|
|
46
|
+
interface MissingPackagedResource {
|
|
47
|
+
label: string;
|
|
48
|
+
path: string;
|
|
49
|
+
}
|
|
50
|
+
declare class PackagedResourceError extends Error {
|
|
51
|
+
readonly missingResources: ReadonlyArray<MissingPackagedResource>;
|
|
52
|
+
constructor(missingResources: ReadonlyArray<MissingPackagedResource>);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* main 入口发布在 dist/main,Overlay 页面与内部 Preload 发布在 dist/overlay。
|
|
56
|
+
* 资源定位集中在这里,避免宿主构建工具或 Electron 版本参与路径拼接。
|
|
57
|
+
*/
|
|
58
|
+
declare function resolveOverlayResources(mainModuleDirectory?: string, resourceExists?: PackagedResourceExists): OverlayResources;
|
|
59
|
+
/** 返回包内已打包的默认宿主 Preload,适用于不需要合并其他 Preload 的窗口。 */
|
|
60
|
+
declare function resolveHostPreloadPath(mainModuleDirectory?: string, resourceExists?: PackagedResourceExists): string;
|
|
61
|
+
declare function assertOverlayResources(resources: OverlayResources, resourceExists?: PackagedResourceExists): void;
|
|
62
|
+
|
|
63
|
+
type OverlayBrowserWindow = Pick<BrowserWindow, 'destroy' | 'focus' | 'isDestroyed' | 'loadFile' | 'moveTop' | 'on' | 'removeListener' | 'setAlwaysOnTop' | 'setBounds' | 'setIgnoreMouseEvents' | 'setOpacity' | 'setVisibleOnAllWorkspaces' | 'show' | 'showInactive'> & {
|
|
64
|
+
webContents: Pick<WebContents, 'id' | 'on' | 'removeListener' | 'send'>;
|
|
65
|
+
};
|
|
66
|
+
type OverlayBrowserWindowFactory = (options: BrowserWindowConstructorOptions) => OverlayBrowserWindow;
|
|
67
|
+
interface OverlayWindowOptions {
|
|
68
|
+
display: CaptureDisplay;
|
|
69
|
+
resources?: OverlayResources;
|
|
70
|
+
createWindow?: OverlayBrowserWindowFactory;
|
|
71
|
+
platform?: NodeJS.Platform;
|
|
72
|
+
resourceExists?: PackagedResourceExists;
|
|
73
|
+
}
|
|
74
|
+
interface ScreenshotOverlayWindow {
|
|
75
|
+
readonly webContentsId: number;
|
|
76
|
+
load(): Promise<void>;
|
|
77
|
+
sendInitialize(payload: ScreenshotInitializePayload): void;
|
|
78
|
+
prime(): void;
|
|
79
|
+
reveal(): void;
|
|
80
|
+
showCopyFeedback?(durationMs: number, options: ScreenshotOptions): void;
|
|
81
|
+
destroy(): void;
|
|
82
|
+
onClosed(listener: () => void): () => void;
|
|
83
|
+
onRendererGone(listener: () => void): () => void;
|
|
84
|
+
}
|
|
85
|
+
/** 管理包内截图窗口,窗口始终使用隔离上下文且不向页面开放 Node.js。 */
|
|
86
|
+
declare class OverlayWindow implements ScreenshotOverlayWindow {
|
|
87
|
+
#private;
|
|
88
|
+
constructor(options: OverlayWindowOptions);
|
|
89
|
+
get webContentsId(): number;
|
|
90
|
+
load(): Promise<void>;
|
|
91
|
+
sendInitialize(payload: ScreenshotInitializePayload): void;
|
|
92
|
+
/** 先以全透明状态进入桌面合成器,隐藏 Windows/macOS 的窗口出场和大图首帧栅格化。 */
|
|
93
|
+
prime(): void;
|
|
94
|
+
reveal(): void;
|
|
95
|
+
/** 复制完成后销毁全屏截图层,改用独立的小窗口显示鼠标穿透提示。 */
|
|
96
|
+
showCopyFeedback(durationMs: number, options: ScreenshotOptions): void;
|
|
97
|
+
destroy(): void;
|
|
98
|
+
onClosed(listener: () => void): () => void;
|
|
99
|
+
onRendererGone(listener: () => void): () => void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface ScreenshotResourceLimits {
|
|
103
|
+
maxCapturePixels: number;
|
|
104
|
+
maxCaptureDataUrlBytes: number;
|
|
105
|
+
maxOutputBytes: number;
|
|
106
|
+
}
|
|
107
|
+
type ScreenshotResourceLimitOptions = Partial<ScreenshotResourceLimits>;
|
|
108
|
+
declare const DEFAULT_SCREENSHOT_RESOURCE_LIMITS: Readonly<ScreenshotResourceLimits>;
|
|
109
|
+
declare const HARD_SCREENSHOT_RESOURCE_LIMITS: Readonly<ScreenshotResourceLimits>;
|
|
110
|
+
declare function resolveScreenshotResourceLimits(options?: ScreenshotResourceLimitOptions): ScreenshotResourceLimits;
|
|
111
|
+
|
|
112
|
+
type ScreenshotSessionState = 'idle' | 'capturing' | 'opening-overlay' | 'preparing-overlay' | 'editing' | 'exporting' | 'completed' | 'cancelled' | 'failed';
|
|
113
|
+
type ScreenshotOverlayFactory = (display: CaptureDisplay) => ScreenshotOverlayWindow;
|
|
114
|
+
interface ScreenshotSessionOptions {
|
|
115
|
+
jobId: string;
|
|
116
|
+
captureOptions: ScreenshotOptions;
|
|
117
|
+
captureAdapter: ScreenCaptureAdapter;
|
|
118
|
+
ipcMain: Pick<IpcMain, 'on' | 'removeListener'>;
|
|
119
|
+
createOverlay: ScreenshotOverlayFactory;
|
|
120
|
+
overlayReadyTimeoutMs?: number;
|
|
121
|
+
onSettled?: () => void;
|
|
122
|
+
registerOutputHandler?: (senderWebContentsId: number, jobId: string) => () => void;
|
|
123
|
+
resourceLimits?: ScreenshotResourceLimitOptions;
|
|
124
|
+
onDiagnostic?: ScreenshotDiagnosticListener;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* 管理一次截图任务从屏幕采集到 Overlay 结算的完整生命周期。
|
|
128
|
+
* 所有 IPC 都同时校验发送窗口、协议版本和 jobId,并且只允许结算一次。
|
|
129
|
+
*/
|
|
130
|
+
declare class ScreenshotSession {
|
|
131
|
+
#private;
|
|
132
|
+
constructor(options: ScreenshotSessionOptions);
|
|
133
|
+
get state(): ScreenshotSessionState;
|
|
134
|
+
/** 允许主进程在宿主窗口销毁或业务主动终止时结束任意活动阶段。 */
|
|
135
|
+
cancel(): boolean;
|
|
136
|
+
run(): Promise<ScreenshotResult>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface ScreenshotJobContext {
|
|
140
|
+
senderWebContentsId?: number;
|
|
141
|
+
}
|
|
142
|
+
interface ScreenshotExecution {
|
|
143
|
+
result: Promise<ScreenshotResult>;
|
|
144
|
+
cancel(): boolean;
|
|
145
|
+
}
|
|
146
|
+
type ScreenshotBusyPolicy = 'reject' | 'queue';
|
|
147
|
+
type ScreenshotRunner = (jobId: string, options: ScreenshotOptions, context: ScreenshotJobContext) => Promise<ScreenshotResult> | ScreenshotExecution;
|
|
148
|
+
type ScreenshotManagerIpcMain = Pick<IpcMain, 'handle' | 'on' | 'removeListener'>;
|
|
149
|
+
interface ScreenshotManagerOptions {
|
|
150
|
+
/** 完全接管会话执行;设置后其余高层注入项不会参与默认 runner。 */
|
|
151
|
+
runner?: ScreenshotRunner;
|
|
152
|
+
ipcMain?: ScreenshotManagerIpcMain;
|
|
153
|
+
captureAdapter?: ScreenCaptureAdapter;
|
|
154
|
+
outputAdapter?: ScreenshotOutputExecutor;
|
|
155
|
+
createOverlay?: ScreenshotOverlayFactory;
|
|
156
|
+
overlayOptions?: Omit<OverlayWindowOptions, 'display'>;
|
|
157
|
+
overlayReadyTimeoutMs?: number;
|
|
158
|
+
resourceLimits?: ScreenshotResourceLimitOptions;
|
|
159
|
+
/** reject 保持即时失败;queue 仅为其他宿主窗口按 FIFO 排队。 */
|
|
160
|
+
busyPolicy?: ScreenshotBusyPolicy;
|
|
161
|
+
maxQueuedCaptures?: number;
|
|
162
|
+
onDiagnostic?: ScreenshotDiagnosticListener;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 统一管理截图会话,确保同一时刻只存在一个覆盖层任务。
|
|
166
|
+
* 窗口创建、屏幕采集与导出由 runner 注入,避免核心调度逻辑绑定 Electron 版本细节。
|
|
167
|
+
*/
|
|
168
|
+
declare class ScreenshotManager {
|
|
169
|
+
#private;
|
|
170
|
+
constructor(options?: ScreenshotManagerOptions);
|
|
171
|
+
get activeJobId(): string | undefined;
|
|
172
|
+
get queuedCaptureCount(): number;
|
|
173
|
+
/** 不传 sender ID 时供主进程直接取消;传入时只允许取消该页面创建的任务。 */
|
|
174
|
+
cancel(senderWebContentsId?: number): boolean;
|
|
175
|
+
capture(options?: ScreenshotOptions, context?: ScreenshotJobContext): Promise<ScreenshotResult>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface ElectronDisplayLike {
|
|
179
|
+
id: number;
|
|
180
|
+
bounds: {
|
|
181
|
+
x: number;
|
|
182
|
+
y: number;
|
|
183
|
+
width: number;
|
|
184
|
+
height: number;
|
|
185
|
+
};
|
|
186
|
+
scaleFactor: number;
|
|
187
|
+
}
|
|
188
|
+
interface ScreenApi {
|
|
189
|
+
getAllDisplays(): ElectronDisplayLike[];
|
|
190
|
+
getCursorScreenPoint(): {
|
|
191
|
+
x: number;
|
|
192
|
+
y: number;
|
|
193
|
+
};
|
|
194
|
+
getDisplayNearestPoint(point: {
|
|
195
|
+
x: number;
|
|
196
|
+
y: number;
|
|
197
|
+
}): ElectronDisplayLike;
|
|
198
|
+
getPrimaryDisplay(): ElectronDisplayLike;
|
|
199
|
+
}
|
|
200
|
+
interface DesktopCaptureSource {
|
|
201
|
+
display_id: string;
|
|
202
|
+
thumbnail: {
|
|
203
|
+
getSize(): {
|
|
204
|
+
width: number;
|
|
205
|
+
height: number;
|
|
206
|
+
};
|
|
207
|
+
isEmpty(): boolean;
|
|
208
|
+
toDataURL(): string;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
interface DesktopCapturerApi {
|
|
212
|
+
getSources(options: {
|
|
213
|
+
types: Array<'screen'>;
|
|
214
|
+
thumbnailSize: {
|
|
215
|
+
width: number;
|
|
216
|
+
height: number;
|
|
217
|
+
};
|
|
218
|
+
fetchWindowIcons: boolean;
|
|
219
|
+
}): Promise<DesktopCaptureSource[]>;
|
|
220
|
+
}
|
|
221
|
+
type ScreenPermissionStatus = 'not-determined' | 'granted' | 'denied' | 'restricted' | 'unknown';
|
|
222
|
+
interface ElectronCaptureAdapterOptions {
|
|
223
|
+
desktopCapturer?: DesktopCapturerApi;
|
|
224
|
+
screen?: ScreenApi;
|
|
225
|
+
platform?: NodeJS.Platform;
|
|
226
|
+
getScreenPermissionStatus?: () => ScreenPermissionStatus;
|
|
227
|
+
resourceLimits?: ScreenshotResourceLimitOptions;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Electron 默认屏幕采集实现。适配器只依赖长期稳定的 Electron API,
|
|
231
|
+
* 采集结果转换为普通数据结构后再交给 Overlay,避免 UI 直接持有 NativeImage。
|
|
232
|
+
*/
|
|
233
|
+
declare class ElectronCaptureAdapter implements ScreenCaptureAdapter {
|
|
234
|
+
#private;
|
|
235
|
+
constructor(options?: ElectronCaptureAdapterOptions);
|
|
236
|
+
resolveTargetDisplay(options?: ScreenshotOptions): CaptureDisplay;
|
|
237
|
+
capture(options?: ScreenshotOptions, targetDisplay?: CaptureDisplay): Promise<CapturedFrame[]>;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
declare class ScreenshotError extends Error {
|
|
241
|
+
readonly code: ScreenshotErrorCode;
|
|
242
|
+
constructor(code: ScreenshotErrorCode, message: string, options?: ErrorOptions);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type ValidateScreenshotIpcSender = (event: IpcMainInvokeEvent) => boolean;
|
|
246
|
+
interface RegisterScreenshotIpcOptions {
|
|
247
|
+
ipcMain: IpcMain;
|
|
248
|
+
manager: ScreenshotManager;
|
|
249
|
+
channel?: string;
|
|
250
|
+
cancelChannel?: string;
|
|
251
|
+
validateSender?: ValidateScreenshotIpcSender;
|
|
252
|
+
}
|
|
253
|
+
interface SetupElectronSnaporaOptions extends Omit<RegisterScreenshotIpcOptions, 'manager'> {
|
|
254
|
+
managerOptions?: ScreenshotManagerOptions;
|
|
255
|
+
}
|
|
256
|
+
interface SetupElectronSnaporaResult {
|
|
257
|
+
manager: ScreenshotManager;
|
|
258
|
+
preloadPath: string;
|
|
259
|
+
unregister: () => void;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* 创建默认截图管理器、注册宿主 IPC,并返回可直接交给 BrowserWindow 的 Preload 路径。
|
|
263
|
+
* 高级宿主仍可分别使用 ScreenshotManager 和 registerScreenshotIpc。
|
|
264
|
+
*/
|
|
265
|
+
declare function setupElectronSnapora(options: SetupElectronSnaporaOptions): SetupElectronSnaporaResult;
|
|
266
|
+
/** 注册宿主渲染进程调用入口,并返回可用于应用退出或热重载的清理函数。 */
|
|
267
|
+
declare function registerScreenshotIpc(options: RegisterScreenshotIpcOptions): () => void;
|
|
268
|
+
|
|
269
|
+
declare const DEFAULT_HOST_CAPTURE_CHANNEL = "electron-snapora:host:capture";
|
|
270
|
+
declare const DEFAULT_HOST_CANCEL_CHANNEL = "electron-snapora:host:cancel";
|
|
271
|
+
declare const OVERLAY_CHANNELS: {
|
|
272
|
+
readonly ready: "electron-snapora:overlay:ready";
|
|
273
|
+
readonly prepared: "electron-snapora:overlay:prepared";
|
|
274
|
+
readonly initialize: "electron-snapora:overlay:initialize";
|
|
275
|
+
readonly feedback: "electron-snapora:overlay:feedback";
|
|
276
|
+
readonly feedbackReady: "electron-snapora:overlay:feedback-ready";
|
|
277
|
+
readonly confirm: "electron-snapora:overlay:confirm";
|
|
278
|
+
readonly cancel: "electron-snapora:overlay:cancel";
|
|
279
|
+
readonly error: "electron-snapora:overlay:error";
|
|
280
|
+
readonly output: "electron-snapora:overlay:output";
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
export { CaptureDisplay, CapturedFrame, DEFAULT_HOST_CANCEL_CHANNEL, DEFAULT_HOST_CAPTURE_CHANNEL, DEFAULT_SCREENSHOT_RESOURCE_LIMITS, ElectronCaptureAdapter, type ElectronCaptureAdapterOptions, ElectronOutputAdapter, type ElectronOutputAdapterOptions, HARD_SCREENSHOT_RESOURCE_LIMITS, type MissingPackagedResource, OVERLAY_CHANNELS, type OverlayResources, OverlayWindow, type OverlayWindowOptions, PackagedResourceError, type PackagedResourceExists, type RegisterScreenshotIpcOptions, ScreenCaptureAdapter, type ScreenshotBusyPolicy, type ScreenshotDiagnosticContextValue, type ScreenshotDiagnosticEvent, type ScreenshotDiagnosticListener, type ScreenshotDiagnosticPhase, type ScreenshotDiagnosticStage, ScreenshotError, ScreenshotErrorCode, type ScreenshotExecution, ScreenshotInitializePayload, type ScreenshotJobContext, ScreenshotManager, type ScreenshotManagerIpcMain, type ScreenshotManagerOptions, ScreenshotOptions, type ScreenshotOutputExecutor, ScreenshotOutputPayload, ScreenshotOutputResponse, type ScreenshotOverlayFactory, type ScreenshotOverlayWindow, type ScreenshotResourceLimitOptions, type ScreenshotResourceLimits, ScreenshotResult, type ScreenshotRunner, ScreenshotSession, type ScreenshotSessionOptions, type ScreenshotSessionState, type SetupElectronSnaporaOptions, type SetupElectronSnaporaResult, type ValidateScreenshotIpcSender, assertOverlayResources, registerScreenshotIpc, resolveHostPreloadPath, resolveOverlayResources, resolveScreenshotResourceLimits, setupElectronSnapora };
|