• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

electron / fiddle / 26301040957

22 May 2026 04:59PM UTC coverage: 88.201% (-0.1%) from 88.301%
26301040957

Pull #1942

github

web-flow
Merge 813c174ee into c4a48887a
Pull Request #1942: refactor: move GitHub tokens to main

569 of 625 branches covered (91.04%)

Branch coverage included in aggregate %.

31 of 39 new or added lines in 9 files covered. (79.49%)

6 existing lines in 1 file now uncovered.

3565 of 4062 relevant lines covered (87.76%)

46.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.55
/src/preload/preload.ts
1
// Remember to update ambient.d.ts for extending window object
2
import { IpcRendererEvent, contextBridge, ipcRenderer } from 'electron';
3

4
import {
5
  BlockableAccelerator,
6
  DownloadVersionParams,
7
  FiddleEvent,
8
  FileTransformOperation,
9
  Files,
10
  GistCreateParams,
11
  GistLoadParams,
12
  GistUpdateParams,
13
  IPackageManager,
14
  MessageOptions,
15
  PMOperationOptions,
16
  PackageJsonOptions,
17
  RunnableVersion,
18
  StartFiddleOptions,
19
  Version,
20
} from '../interfaces';
21
import { IpcEvents, WEBCONTENTS_READY_FOR_IPC_SIGNAL } from '../ipc-events';
22
import { FiddleTheme } from '../themes-defaults';
23

24
const channelMapping: Record<FiddleEvent, IpcEvents> = {
1✔
25
  'before-quit': IpcEvents.BEFORE_QUIT,
26
  'clear-console': IpcEvents.CLEAR_CONSOLE,
27
  'electron-types-changed': IpcEvents.ELECTRON_TYPES_CHANGED,
28
  'execute-monaco-command': IpcEvents.MONACO_EXECUTE_COMMAND,
29
  'fiddle-runner-output': IpcEvents.FIDDLE_RUNNER_OUTPUT,
30
  'fiddle-modules-installed': IpcEvents.FIDDLE_MODULES_INSTALLED,
31
  'fiddle-stopped': IpcEvents.FIDDLE_STOPPED,
32
  'is-auto-bisecting': IpcEvents.IS_AUTO_BISECTING,
33
  'load-example': IpcEvents.LOAD_ELECTRON_EXAMPLE_REQUEST,
34
  'load-gist': IpcEvents.LOAD_GIST_REQUEST,
35
  'make-fiddle': IpcEvents.FIDDLE_MAKE,
36
  'new-fiddle': IpcEvents.FS_NEW_FIDDLE,
37
  'new-test': IpcEvents.FS_NEW_TEST,
38
  'open-fiddle': IpcEvents.FS_OPEN_FIDDLE,
39
  'open-settings': IpcEvents.OPEN_SETTINGS,
40
  'open-template': IpcEvents.FS_OPEN_TEMPLATE,
41
  'package-fiddle': IpcEvents.FIDDLE_PACKAGE,
42
  'redo-in-editor': IpcEvents.REDO_IN_EDITOR,
43
  'run-fiddle': IpcEvents.FIDDLE_RUN,
44
  'saved-local-fiddle': IpcEvents.SAVED_LOCAL_FIDDLE,
45
  'save-fiddle-gist': IpcEvents.FS_SAVE_FIDDLE_GIST,
46
  'select-all-in-editor': IpcEvents.SELECT_ALL_IN_EDITOR,
47
  'set-show-me-template': IpcEvents.SET_SHOW_ME_TEMPLATE,
48
  'show-welcome-tour': IpcEvents.SHOW_WELCOME_TOUR,
49
  'toggle-bisect': IpcEvents.BISECT_COMMANDS_TOGGLE,
50
  'toggle-monaco-option': IpcEvents.MONACO_TOGGLE_OPTION,
51
  'undo-in-editor': IpcEvents.UNDO_IN_EDITOR,
52
  'version-download-progress': IpcEvents.VERSION_DOWNLOAD_PROGRESS,
53
  'version-state-changed': IpcEvents.VERSION_STATE_CHANGED,
54
} as const;
55

56
async function preload() {
57
  await setupFiddleGlobal();
1✔
58
}
59

60
export async function setupFiddleGlobal() {
61
  contextBridge.exposeInMainWorld('ElectronFiddle', {
2✔
62
    addEventListener(
63
      type: FiddleEvent,
64
      listener: (...args: any[]) => void,
65
      options?: { signal: AbortSignal },
66
    ) {
67
      const channel = channelMapping[type];
×
68
      if (channel) {
×
69
        const ipcListener = (_event: IpcRendererEvent, ...args: any[]) => {
×
70
          listener(...args);
×
71
        };
72
        ipcRenderer.on(channel, ipcListener);
×
73
        if (options?.signal) {
×
74
          options.signal.addEventListener('abort', () => {
×
75
            ipcRenderer.off(channel, ipcListener);
×
76
          });
77
        }
78
      }
79
    },
80
    addModules(
81
      { dir, packageManager, useSocketFirewall }: PMOperationOptions,
82
      ...names: Array<string>
83
    ) {
84
      return ipcRenderer.invoke(
×
85
        IpcEvents.NPM_ADD_MODULES,
86
        { dir, packageManager, useSocketFirewall },
87
        ...names,
88
      );
89
    },
90
    arch: process.arch,
91
    autobisectFiddle(versions: Array<RunnableVersion>): void {
92
      ipcRenderer.send(IpcEvents.AUTOBISECT_FIDDLE, versions);
×
93
    },
94
    blockAccelerators(acceleratorsToBlock: BlockableAccelerator[]) {
95
      ipcRenderer.send(IpcEvents.BLOCK_ACCELERATORS, acceleratorsToBlock);
×
96
    },
97
    confirmQuit() {
98
      ipcRenderer.send(IpcEvents.CONFIRM_QUIT);
×
99
    },
100
    createThemeFile(newTheme: FiddleTheme, name?: string) {
101
      return ipcRenderer.invoke(IpcEvents.CREATE_THEME_FILE, newTheme, name);
×
102
    },
103
    async downloadVersion(
104
      version: string,
105
      opts?: Partial<DownloadVersionParams>,
106
    ) {
107
      await ipcRenderer.invoke(IpcEvents.DOWNLOAD_VERSION, version, opts);
×
108
    },
109
    fetchVersions() {
110
      return ipcRenderer.invoke(IpcEvents.FETCH_VERSIONS);
×
111
    },
112
    fetchExample: (ref: string, path: string) =>
113
      ipcRenderer.invoke(IpcEvents.GITHUB_FETCH_EXAMPLE, { ref, path }),
×
114
    gistCreate: (params: GistCreateParams) =>
NEW
115
      ipcRenderer.invoke(IpcEvents.GITHUB_GIST_CREATE, params),
×
116
    gistDelete: (id: string) =>
NEW
117
      ipcRenderer.invoke(IpcEvents.GITHUB_GIST_DELETE, id),
×
118
    gistListCommits: (gistId: string) =>
119
      ipcRenderer.invoke(IpcEvents.GITHUB_GIST_LIST_COMMITS, gistId),
×
120
    gistLoad: (params: GistLoadParams) =>
121
      ipcRenderer.invoke(IpcEvents.GITHUB_GIST_LOAD, params),
×
122
    gistUpdate: (params: GistUpdateParams) =>
NEW
123
      ipcRenderer.invoke(IpcEvents.GITHUB_GIST_UPDATE, params),
×
124
    gitHubCheckAuth: () =>
NEW
125
      ipcRenderer.invoke(IpcEvents.GITHUB_TOKEN_CHECK_AUTH),
×
126
    gitHubSignIn: (token: string) =>
NEW
127
      ipcRenderer.invoke(IpcEvents.GITHUB_TOKEN_SIGN_IN, token),
×
NEW
128
    gitHubSignOut: () => ipcRenderer.invoke(IpcEvents.GITHUB_TOKEN_SIGN_OUT),
×
129
    getElectronTypes(ver: RunnableVersion) {
130
      return ipcRenderer.invoke(IpcEvents.GET_ELECTRON_TYPES, ver);
×
131
    },
132
    getLatestStable() {
133
      return ipcRenderer.sendSync(IpcEvents.GET_LATEST_STABLE);
×
134
    },
135
    getLocalVersionState(ver: RunnableVersion) {
136
      return ipcRenderer.sendSync(IpcEvents.GET_LOCAL_VERSION_STATE, ver);
×
137
    },
138
    getLocalVersions(): Array<Version> {
139
      return ipcRenderer.sendSync(IpcEvents.GET_LOCAL_VERSIONS);
×
140
    },
141
    addLocalVersion(token: string, name: string): Array<Version> {
142
      return ipcRenderer.sendSync(IpcEvents.ADD_LOCAL_VERSION, token, name);
×
143
    },
144
    cancelPendingLocalVersion(token: string): void {
145
      ipcRenderer.sendSync(IpcEvents.CANCEL_PENDING_LOCAL_VERSION, token);
×
146
    },
147
    removeLocalVersion(version: string): Array<Version> {
148
      return ipcRenderer.sendSync(IpcEvents.REMOVE_LOCAL_VERSION, version);
×
149
    },
150
    migrateLocalVersions(versions: Version[]): boolean {
151
      return ipcRenderer.sendSync(IpcEvents.MIGRATE_LOCAL_VERSIONS, versions);
×
152
    },
153
    getOldestSupportedMajor() {
154
      return ipcRenderer.sendSync(IpcEvents.GET_OLDEST_SUPPORTED_MAJOR);
×
155
    },
156
    getReleasedVersions() {
157
      return ipcRenderer.sendSync(IpcEvents.GET_RELEASED_VERSIONS);
×
158
    },
159
    getReleaseInfo(version: string) {
160
      return ipcRenderer.invoke(IpcEvents.GET_RELEASE_INFO, version);
×
161
    },
162
    getAvailableThemes() {
163
      return ipcRenderer.invoke(IpcEvents.GET_AVAILABLE_THEMES);
×
164
    },
165
    getIsPackageManagerInstalled(
166
      packageManager: IPackageManager,
167
      ignoreCache?: boolean,
168
    ) {
169
      return ipcRenderer.invoke(
×
170
        IpcEvents.NPM_IS_PM_INSTALLED,
171
        packageManager,
172
        ignoreCache,
173
      );
174
    },
175
    getNodeTypes(version: string) {
176
      return ipcRenderer.invoke(IpcEvents.GET_NODE_TYPES, version);
×
177
    },
178
    getProjectName(localPath?: string) {
179
      return ipcRenderer.invoke(IpcEvents.GET_PROJECT_NAME, localPath);
×
180
    },
181
    getTemplate: (version: string) =>
182
      ipcRenderer.invoke(IpcEvents.GET_TEMPLATE, version),
×
183
    getTemplateValues: (name: string) => {
184
      return ipcRenderer.invoke(IpcEvents.GET_TEMPLATE_VALUES, name);
×
185
    },
186
    isReleasedMajor(major: number) {
187
      return ipcRenderer.invoke(IpcEvents.IS_RELEASED_MAJOR, major);
×
188
    },
189
    getTestTemplate: () => ipcRenderer.invoke(IpcEvents.GET_TEST_TEMPLATE),
×
190
    getUsername: () => ipcRenderer.sendSync(IpcEvents.GET_USERNAME),
×
191
    getVersionState: (version: string) =>
192
      ipcRenderer.sendSync(IpcEvents.GET_VERSION_STATE, version),
×
193
    isDevMode: ipcRenderer.sendSync(IpcEvents.IS_DEV_MODE),
194
    macTitlebarClicked() {
195
      ipcRenderer.send(IpcEvents.CLICK_TITLEBAR_MAC);
×
196
    },
197
    onGetFiles(
198
      callback: (
199
        options: PackageJsonOptions | undefined,
200
        transforms: Array<FileTransformOperation>,
201
      ) => Promise<{ localPath?: string; files: Files }>,
202
    ) {
203
      ipcRenderer.removeAllListeners(IpcEvents.GET_FILES);
×
204
      ipcRenderer.on(
×
205
        IpcEvents.GET_FILES,
206
        async (e, { options, transforms }) => {
207
          const { localPath, files } = await callback(options, transforms);
×
208
          e.ports[0].postMessage({ localPath, files: [...files.entries()] });
×
209
        },
210
      );
211
    },
212
    onGetStartFiddleOptions(callback: () => Promise<StartFiddleOptions>) {
213
      ipcRenderer.removeAllListeners(IpcEvents.GET_START_FIDDLE_OPTIONS);
×
214
      ipcRenderer.on(IpcEvents.GET_START_FIDDLE_OPTIONS, async (e) => {
×
215
        try {
×
216
          const options = await callback();
×
217
          e.ports[0].postMessage({ result: options });
×
218
        } catch (error) {
219
          const message =
220
            error instanceof Error ? error.message : String(error);
×
221
          e.ports[0].postMessage({ error: message });
×
222
        }
223
      });
224
    },
225
    onSetVersion(callback: (version: string) => Promise<void>) {
226
      ipcRenderer.removeAllListeners(IpcEvents.SET_VERSION);
×
227
      ipcRenderer.on(IpcEvents.SET_VERSION, async (e, version: string) => {
×
228
        await callback(version);
×
229
        e.ports[0].postMessage(undefined);
×
230
      });
231
    },
232
    async openThemeFolder() {
233
      await ipcRenderer.invoke(IpcEvents.OPEN_THEME_FOLDER);
×
234
    },
235
    packageRun({ dir, packageManager }: PMOperationOptions, command: string) {
236
      return ipcRenderer.invoke(
×
237
        IpcEvents.NPM_PACKAGE_RUN,
238
        { dir, packageManager },
239
        command,
240
      );
241
    },
242
    platform: process.platform,
243
    reloadWindows() {
244
      ipcRenderer.send(IpcEvents.RELOAD_WINDOW);
×
245
    },
246
    readThemeFile(name?: string) {
247
      return ipcRenderer.invoke(IpcEvents.READ_THEME_FILE, name);
×
248
    },
249
    removeAllListeners(type: FiddleEvent) {
250
      const channel = channelMapping[type];
×
251
      if (channel) {
×
252
        ipcRenderer.removeAllListeners(channel);
×
253
      }
254
    },
255
    async removeVersion(version: string) {
256
      return ipcRenderer.invoke(IpcEvents.REMOVE_VERSION, version);
×
257
    },
258
    saveFilesToTemp(files: Files) {
259
      return ipcRenderer.invoke(IpcEvents.SAVE_FILES_TO_TEMP, [
×
260
        ...files.entries(),
261
      ]);
262
    },
263
    selectLocalVersion: () => {
264
      return ipcRenderer.invoke(IpcEvents.LOAD_LOCAL_VERSION_FOLDER);
×
265
    },
266
    sendReady() {
267
      ipcRenderer.send(WEBCONTENTS_READY_FOR_IPC_SIGNAL);
×
268
    },
269
    setNativeTheme(theme: 'dark' | 'light' | 'system') {
270
      ipcRenderer.send(IpcEvents.SET_NATIVE_THEME, theme);
×
271
    },
272
    setShowMeTemplate(template?: string) {
273
      ipcRenderer.send(IpcEvents.SET_SHOW_ME_TEMPLATE, template);
×
274
    },
275
    showWarningDialog(messageOptions: MessageOptions) {
276
      ipcRenderer.send(IpcEvents.SHOW_WARNING_DIALOG, messageOptions);
×
277
    },
278
    showWindow() {
279
      ipcRenderer.send(IpcEvents.SHOW_WINDOW);
×
280
    },
281
    async startFiddle() {
282
      await ipcRenderer.invoke(IpcEvents.START_FIDDLE);
×
283
    },
284
    stopFiddle() {
285
      ipcRenderer.send(IpcEvents.STOP_FIDDLE);
×
286
    },
287
    themePath: await ipcRenderer.sendSync(IpcEvents.GET_THEME_PATH),
288
    async uncacheTypes(ver: RunnableVersion) {
289
      await ipcRenderer.invoke(IpcEvents.UNCACHE_TYPES, ver);
×
290
    },
291
    async unwatchElectronTypes() {
292
      await ipcRenderer.invoke(IpcEvents.UNWATCH_ELECTRON_TYPES);
×
293
    },
294
  });
295
}
296

297
preload();
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc