@lvce-editor/file-system-process 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1388 -122
  2. package/package.json +1 -9
package/dist/index.js CHANGED
@@ -1,20 +1,113 @@
1
1
  import * as fs from 'node:fs/promises';
2
2
  import * as os from 'node:os';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { string, object } from '@lvce-editor/assert';
5
- import { VError } from '@lvce-editor/verror';
6
4
  import { join } from 'node:path';
7
5
  import { existsSync } from 'node:fs';
8
- import { NodeWebSocketRpcClient, ElectronMessagePortRpcClient, ElectronUtilityProcessRpcClient, NodeWorkerRpcClient, NodeForkedProcessRpcClient } from '@lvce-editor/rpc';
9
- import { invoke as invoke$1 } from '@lvce-editor/json-rpc';
10
6
  import _trash from 'trash';
7
+ import { Buffer } from 'node:buffer';
8
+
9
+ class AssertionError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'AssertionError';
13
+ }
14
+ }
15
+ const getType = value => {
16
+ switch (typeof value) {
17
+ case 'number':
18
+ return 'number';
19
+ case 'function':
20
+ return 'function';
21
+ case 'string':
22
+ return 'string';
23
+ case 'object':
24
+ if (value === null) {
25
+ return 'null';
26
+ }
27
+ if (Array.isArray(value)) {
28
+ return 'array';
29
+ }
30
+ return 'object';
31
+ case 'boolean':
32
+ return 'boolean';
33
+ default:
34
+ return 'unknown';
35
+ }
36
+ };
37
+ const object = value => {
38
+ const type = getType(value);
39
+ if (type !== 'object') {
40
+ throw new AssertionError('expected value to be of type object');
41
+ }
42
+ };
43
+ const string = value => {
44
+ const type = getType(value);
45
+ if (type !== 'string') {
46
+ throw new AssertionError('expected value to be of type string');
47
+ }
48
+ };
11
49
 
12
50
  const Utf8 = 'utf8';
13
51
 
14
52
  const ENOENT = 'ENOENT';
15
53
  const EXDEV = 'EXDEV';
16
54
 
17
- // @ts-ignore
55
+ const normalizeLine = line => {
56
+ if (line.startsWith('Error: ')) {
57
+ return line.slice('Error: '.length);
58
+ }
59
+ if (line.startsWith('VError: ')) {
60
+ return line.slice('VError: '.length);
61
+ }
62
+ return line;
63
+ };
64
+ const getCombinedMessage = (error, message) => {
65
+ const stringifiedError = normalizeLine(`${error}`);
66
+ if (message) {
67
+ return `${message}: ${stringifiedError}`;
68
+ }
69
+ return stringifiedError;
70
+ };
71
+ const NewLine$2 = '\n';
72
+ const getNewLineIndex$1 = (string, startIndex = undefined) => {
73
+ return string.indexOf(NewLine$2, startIndex);
74
+ };
75
+ const mergeStacks = (parent, child) => {
76
+ if (!child) {
77
+ return parent;
78
+ }
79
+ const parentNewLineIndex = getNewLineIndex$1(parent);
80
+ const childNewLineIndex = getNewLineIndex$1(child);
81
+ if (childNewLineIndex === -1) {
82
+ return parent;
83
+ }
84
+ const parentFirstLine = parent.slice(0, parentNewLineIndex);
85
+ const childRest = child.slice(childNewLineIndex);
86
+ const childFirstLine = normalizeLine(child.slice(0, childNewLineIndex));
87
+ if (parentFirstLine.includes(childFirstLine)) {
88
+ return parentFirstLine + childRest;
89
+ }
90
+ return child;
91
+ };
92
+ class VError extends Error {
93
+ constructor(error, message) {
94
+ const combinedMessage = getCombinedMessage(error, message);
95
+ super(combinedMessage);
96
+ this.name = 'VError';
97
+ if (error instanceof Error) {
98
+ this.stack = mergeStacks(this.stack, error.stack);
99
+ }
100
+ if (error.codeFrame) {
101
+ // @ts-ignore
102
+ this.codeFrame = error.codeFrame;
103
+ }
104
+ if (error.code) {
105
+ // @ts-ignore
106
+ this.code = error.code;
107
+ }
108
+ }
109
+ }
110
+
18
111
  const getDisplayPath = path => {
19
112
  if (path === '') {
20
113
  return '<empty string>';
@@ -22,10 +115,8 @@ const getDisplayPath = path => {
22
115
  return path;
23
116
  };
24
117
  class FileNotFoundError extends VError {
25
- // @ts-ignore
26
118
  constructor(path) {
27
119
  super(`File not found: '${getDisplayPath(path)}'`);
28
- // @ts-ignore
29
120
  this.code = ENOENT;
30
121
  }
31
122
  }
@@ -39,10 +130,6 @@ const Socket = 8;
39
130
  const Symlink = 9;
40
131
  const Unknown = 12;
41
132
 
42
- /**
43
- * @param {import('fs').Dirent|import('fs').StatsBase} dirent
44
- */
45
- // @ts-ignore
46
133
  const getDirentType = dirent => {
47
134
  if (dirent.isFile()) {
48
135
  return File;
@@ -106,76 +193,57 @@ const isEnoentError = error => {
106
193
  return isEnoentErrorLinux(error) || isEnoentErrorWindows(error);
107
194
  };
108
195
 
109
- const getElectronRunAsNode = () => {
110
- return process.env.ELECTRON_RUN_AS_NODE;
196
+ const rpcs = Object.create(null);
197
+ const set$7 = (id, rpc) => {
198
+ rpcs[id] = rpc;
111
199
  };
112
- process;
113
-
114
- const isElectron = Boolean(getElectronRunAsNode()) || 'electron' in process.versions;
115
-
116
- const NodeWorker = 1;
117
- const NodeForkedProcess = 2;
118
- const ElectronUtilityProcess = 3;
119
- const ElectronMessagePort = 4;
120
- const WebSocket = 6;
121
- const Auto = argv => {
122
- if (argv.includes('--ipc-type=node-worker')) {
123
- return NodeWorker;
124
- }
125
- if (argv.includes('--ipc-type=node-forked-process')) {
126
- return NodeForkedProcess;
127
- }
128
- if (argv.includes('--ipc-type=electron-utility-process')) {
129
- return ElectronUtilityProcess;
130
- }
131
- throw new Error(`[file-system-process] unknown ipc type`);
200
+ const get$1 = id => {
201
+ return rpcs[id];
132
202
  };
133
203
 
134
- const getModule = method => {
135
- switch (method) {
136
- case NodeForkedProcess:
137
- return NodeForkedProcessRpcClient;
138
- case NodeWorker:
139
- return NodeWorkerRpcClient;
140
- case ElectronUtilityProcess:
141
- return ElectronUtilityProcessRpcClient;
142
- case ElectronMessagePort:
143
- return ElectronMessagePortRpcClient;
144
- case WebSocket:
145
- return NodeWebSocketRpcClient;
146
- default:
147
- throw new Error('unexpected ipc type');
148
- }
149
- };
204
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
150
205
 
151
- const listen$1 = async ({
152
- method,
153
- ...params
154
- }) => {
155
- const module = getModule(method);
156
- const rpc = await module.create(params);
157
- return rpc;
158
- };
159
-
160
- // TODO add tests for this
161
-
162
- // TODO handle structure: one shared process multiple extension hosts
163
-
164
- // TODO pass socket / port handle also in electron
165
-
166
- const state = {
167
- ipc: undefined
206
+ const create$6 = rpcId => {
207
+ return {
208
+ // @ts-ignore
209
+ invoke(method, ...params) {
210
+ const rpc = get$1(rpcId);
211
+ // @ts-ignore
212
+ return rpc.invoke(method, ...params);
213
+ },
214
+ // @ts-ignore
215
+ invokeAndTransfer(method, ...params) {
216
+ const rpc = get$1(rpcId);
217
+ // @ts-ignore
218
+ return rpc.invokeAndTransfer(method, ...params);
219
+ },
220
+ set(rpc) {
221
+ set$7(rpcId, rpc);
222
+ }
223
+ };
168
224
  };
169
- const invoke = (method, ...params) => {
170
- return invoke$1(state.ipc, method, ...params);
225
+ const MainProcess$1 = -5;
226
+ const {
227
+ invoke: invoke$3,
228
+ set: set$3
229
+ } = create$6(MainProcess$1);
230
+ const MainProcess = {
231
+ __proto__: null,
232
+ invoke: invoke$3,
233
+ set: set$3
171
234
  };
172
235
 
173
- // @ts-ignore
236
+ const {
237
+ invoke: invoke$1,
238
+ set: set$1
239
+ } = MainProcess;
240
+
174
241
  const trash$2 = async path => {
175
242
  if (!existsSync(path)) {
176
243
  return;
177
244
  }
178
- await invoke('Trash.trash', path);
245
+ // @ts-ignore
246
+ await invoke$1('Trash.trash', path);
179
247
  };
180
248
 
181
249
  // @ts-ignore
@@ -183,17 +251,22 @@ const trash$1 = async path => {
183
251
  await _trash(path);
184
252
  };
185
253
 
186
- const getFn = () => {
254
+ const getTrashFn = isElectron => {
187
255
  if (isElectron) {
188
256
  return trash$2;
189
257
  }
190
258
  return trash$1;
191
259
  };
192
260
 
193
- // @ts-ignore
261
+ const getElectronRunAsNode = () => {
262
+ return process.env.ELECTRON_RUN_AS_NODE;
263
+ };
264
+
265
+ const isElectron = Boolean(getElectronRunAsNode()) || 'electron' in process.versions;
266
+
194
267
  const trash = async path => {
195
268
  try {
196
- const fn = getFn();
269
+ const fn = getTrashFn(isElectron);
197
270
  await fn(path);
198
271
  } catch (error) {
199
272
  throw new VError(error, 'Failed to move item to trash');
@@ -201,8 +274,6 @@ const trash = async path => {
201
274
  };
202
275
 
203
276
  // TODO lazyload chokidar and trash (but doesn't work currently because of bug with jest)
204
-
205
- // @ts-ignore
206
277
  const assertUri = uri => {
207
278
  if (!uri.startsWith('file://')) {
208
279
  throw new Error(`path must be a valid file uri`);
@@ -224,20 +295,11 @@ const copy = async (sourceUri, targetUri) => {
224
295
  throw new VError(error, `Failed to copy "${sourceUri}" to "${targetUri}"`);
225
296
  }
226
297
  };
227
-
228
- /**
229
- *
230
- * @param {string} uri
231
- * @param {BufferEncoding} encoding
232
- * @returns
233
- */
234
- // @ts-ignore
235
298
  const readFile = async (uri, encoding = Utf8) => {
236
299
  try {
237
300
  string(uri);
238
301
  assertUri(uri);
239
302
  const path = fileURLToPath(uri);
240
- // @ts-ignore
241
303
  const content = await fs.readFile(path, encoding);
242
304
  return content;
243
305
  } catch (error) {
@@ -247,14 +309,6 @@ const readFile = async (uri, encoding = Utf8) => {
247
309
  throw new VError(error, `Failed to read file "${uri}"`);
248
310
  }
249
311
  };
250
-
251
- /**
252
- *
253
- * @param {string} uri
254
- * @param {string} content
255
- * @param {BufferEncoding} encoding
256
- */
257
- // @ts-ignore
258
312
  const writeFile = async (uri, content, encoding = Utf8) => {
259
313
  try {
260
314
  assertUri(uri);
@@ -263,7 +317,6 @@ const writeFile = async (uri, content, encoding = Utf8) => {
263
317
  const path = fileURLToPath(uri);
264
318
  // queue would be more correct for concurrent writes but also slower
265
319
  // Queue.add(`writeFile/${path}`, () =>
266
- // @ts-ignore
267
320
  await fs.writeFile(path, content, encoding);
268
321
  } catch (error) {
269
322
  if (isEnoentError(error)) {
@@ -272,8 +325,6 @@ const writeFile = async (uri, content, encoding = Utf8) => {
272
325
  throw new VError(error, `Failed to write to file "${uri}"`);
273
326
  }
274
327
  };
275
-
276
- // @ts-ignore
277
328
  const isOkayToRemove = path => {
278
329
  if (path === '/') {
279
330
  return false;
@@ -286,9 +337,7 @@ const isOkayToRemove = path => {
286
337
  }
287
338
  return true;
288
339
  };
289
-
290
- // @ts-ignore
291
- const remove = async uri => {
340
+ const remove$1 = async uri => {
292
341
  assertUri(uri);
293
342
  const path = fileURLToPath(uri);
294
343
  if (!isOkayToRemove(path)) {
@@ -304,19 +353,12 @@ const remove = async uri => {
304
353
  throw new VError(error, `Failed to remove "${uri}"`);
305
354
  }
306
355
  };
307
-
308
- /**
309
- * @param {import('fs').Dirent} dirent
310
- */
311
- // @ts-ignore
312
356
  const toPrettyDirent = dirent => {
313
357
  return {
314
358
  name: dirent.name,
315
359
  type: getDirentType(dirent)
316
360
  };
317
361
  };
318
-
319
- // @ts-ignore
320
362
  const readDirWithFileTypes = async uri => {
321
363
  try {
322
364
  assertUri(uri);
@@ -330,8 +372,6 @@ const readDirWithFileTypes = async uri => {
330
372
  throw new VError(error, `Failed to read directory "${uri}"`);
331
373
  }
332
374
  };
333
-
334
- // @ts-ignore
335
375
  const mkdir = async uri => {
336
376
  try {
337
377
  assertUri(uri);
@@ -343,8 +383,6 @@ const mkdir = async uri => {
343
383
  throw new VError(error, `Failed to create directory "${uri}"`);
344
384
  }
345
385
  };
346
-
347
- // @ts-ignore
348
386
  const fallbackRename = async (oldUri, newUri) => {
349
387
  try {
350
388
  const oldPath = fileURLToPath(oldUri);
@@ -359,8 +397,6 @@ const fallbackRename = async (oldUri, newUri) => {
359
397
  throw new VError(error, `Failed to rename "${oldUri}" to "${newUri}"`);
360
398
  }
361
399
  };
362
-
363
- // @ts-ignore
364
400
  const rename = async (oldUri, newUri) => {
365
401
  try {
366
402
  const oldPath = fileURLToPath(oldUri);
@@ -376,23 +412,16 @@ const rename = async (oldUri, newUri) => {
376
412
  const getPathSeparator = () => {
377
413
  return '/';
378
414
  };
379
-
380
- // TODO handle error
381
- // @ts-ignore
382
415
  const stat = async uri => {
383
416
  const path = fileURLToPath(uri);
384
417
  const stats = await fs.stat(path);
385
418
  const type = getDirentType(stats);
386
419
  return type;
387
420
  };
388
-
389
- // @ts-ignore
390
421
  const chmod = async (uri, permissions) => {
391
422
  const path = fileURLToPath(uri);
392
423
  await fs.chmod(path, permissions);
393
424
  };
394
-
395
- // @ts-ignore
396
425
  const readJson = async uri => {
397
426
  try {
398
427
  string(uri);
@@ -408,14 +437,1198 @@ const readJson = async uri => {
408
437
  throw new VError(error, `Failed to read file as json "${uri}"`);
409
438
  }
410
439
  };
411
-
412
- // @ts-ignore
413
440
  const getFolderSize = async uri => {
414
441
  const path = fileURLToPath(uri);
415
442
  const total = await getFolderSizeInternal(path);
416
443
  return total;
417
444
  };
418
445
 
446
+ const isMessagePort = value => {
447
+ return value && value instanceof MessagePort;
448
+ };
449
+ const isMessagePortMain = value => {
450
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
451
+ };
452
+ const isOffscreenCanvas = value => {
453
+ return typeof OffscreenCanvas !== 'undefined' && value instanceof OffscreenCanvas;
454
+ };
455
+ const isInstanceOf = (value, constructorName) => {
456
+ return value?.constructor?.name === constructorName;
457
+ };
458
+ const isSocket = value => {
459
+ return isInstanceOf(value, 'Socket');
460
+ };
461
+ const transferrables = [isMessagePort, isMessagePortMain, isOffscreenCanvas, isSocket];
462
+ const isTransferrable = value => {
463
+ for (const fn of transferrables) {
464
+ if (fn(value)) {
465
+ return true;
466
+ }
467
+ }
468
+ return false;
469
+ };
470
+ const walkValue = (value, transferrables, isTransferrable) => {
471
+ if (!value) {
472
+ return;
473
+ }
474
+ if (isTransferrable(value)) {
475
+ transferrables.push(value);
476
+ return;
477
+ }
478
+ if (Array.isArray(value)) {
479
+ for (const item of value) {
480
+ walkValue(item, transferrables, isTransferrable);
481
+ }
482
+ return;
483
+ }
484
+ if (typeof value === 'object') {
485
+ for (const property of Object.values(value)) {
486
+ walkValue(property, transferrables, isTransferrable);
487
+ }
488
+ return;
489
+ }
490
+ };
491
+ const getTransferrables = value => {
492
+ const transferrables = [];
493
+ walkValue(value, transferrables, isTransferrable);
494
+ return transferrables;
495
+ };
496
+ const removeValues = (value, toRemove) => {
497
+ if (!value) {
498
+ return value;
499
+ }
500
+ if (Array.isArray(value)) {
501
+ const newItems = [];
502
+ for (const item of value) {
503
+ if (!toRemove.includes(item)) {
504
+ newItems.push(removeValues(item, toRemove));
505
+ }
506
+ }
507
+ return newItems;
508
+ }
509
+ if (typeof value === 'object') {
510
+ const newObject = Object.create(null);
511
+ for (const [key, property] of Object.entries(value)) {
512
+ if (!toRemove.includes(property)) {
513
+ newObject[key] = removeValues(property, toRemove);
514
+ }
515
+ }
516
+ return newObject;
517
+ }
518
+ return value;
519
+ };
520
+
521
+ // workaround for electron not supporting transferrable objects
522
+ // as parameters. If the transferrable object is a parameter, in electron
523
+ // only an empty objected is received in the main process
524
+ const fixElectronParameters = value => {
525
+ const transfer = getTransferrables(value);
526
+ const newValue = removeValues(value, transfer);
527
+ return {
528
+ newValue,
529
+ transfer
530
+ };
531
+ };
532
+ const getActualDataElectron = event => {
533
+ const {
534
+ data,
535
+ ports
536
+ } = event;
537
+ if (ports.length === 0) {
538
+ return data;
539
+ }
540
+ return {
541
+ ...data,
542
+ params: [...ports, ...data.params]
543
+ };
544
+ };
545
+ const attachEvents = that => {
546
+ const handleMessage = (...args) => {
547
+ const data = that.getData(...args);
548
+ that.dispatchEvent(new MessageEvent('message', {
549
+ data
550
+ }));
551
+ };
552
+ that.onMessage(handleMessage);
553
+ const handleClose = event => {
554
+ that.dispatchEvent(new Event('close'));
555
+ };
556
+ that.onClose(handleClose);
557
+ };
558
+ class Ipc extends EventTarget {
559
+ constructor(rawIpc) {
560
+ super();
561
+ this._rawIpc = rawIpc;
562
+ attachEvents(this);
563
+ }
564
+ }
565
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
566
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
567
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
568
+ const NewLine$1 = '\n';
569
+ const joinLines$1 = lines => {
570
+ return lines.join(NewLine$1);
571
+ };
572
+ const RE_AT = /^\s+at/;
573
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
574
+ const isNormalStackLine = line => {
575
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
576
+ };
577
+ const getDetails = lines => {
578
+ const index = lines.findIndex(isNormalStackLine);
579
+ if (index === -1) {
580
+ return {
581
+ actualMessage: joinLines$1(lines),
582
+ rest: []
583
+ };
584
+ }
585
+ let lastIndex = index - 1;
586
+ while (++lastIndex < lines.length) {
587
+ if (!isNormalStackLine(lines[lastIndex])) {
588
+ break;
589
+ }
590
+ }
591
+ return {
592
+ actualMessage: lines[index - 1],
593
+ rest: lines.slice(index, lastIndex)
594
+ };
595
+ };
596
+ const splitLines$1 = lines => {
597
+ return lines.split(NewLine$1);
598
+ };
599
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
600
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
601
+ const isMessageCodeBlockStartIndex = line => {
602
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
603
+ };
604
+ const isMessageCodeBlockEndIndex = line => {
605
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
606
+ };
607
+ const getMessageCodeBlock = stderr => {
608
+ const lines = splitLines$1(stderr);
609
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
610
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
611
+ const relevantLines = lines.slice(startIndex, endIndex);
612
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
613
+ return relevantMessage;
614
+ };
615
+ const isModuleNotFoundMessage = line => {
616
+ return line.includes('[ERR_MODULE_NOT_FOUND]');
617
+ };
618
+ const getModuleNotFoundError = stderr => {
619
+ const lines = splitLines$1(stderr);
620
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
621
+ const message = lines[messageIndex];
622
+ return {
623
+ message,
624
+ code: ERR_MODULE_NOT_FOUND
625
+ };
626
+ };
627
+ const isModuleNotFoundError = stderr => {
628
+ if (!stderr) {
629
+ return false;
630
+ }
631
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
632
+ };
633
+ const isModulesSyntaxError = stderr => {
634
+ if (!stderr) {
635
+ return false;
636
+ }
637
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
638
+ };
639
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
640
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
641
+ const isUnhelpfulNativeModuleError = stderr => {
642
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
643
+ };
644
+ const getNativeModuleErrorMessage = stderr => {
645
+ const message = getMessageCodeBlock(stderr);
646
+ return {
647
+ message: `Incompatible native node module: ${message}`,
648
+ code: E_INCOMPATIBLE_NATIVE_MODULE
649
+ };
650
+ };
651
+ const getModuleSyntaxError = () => {
652
+ return {
653
+ message: `ES Modules are not supported in electron`,
654
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
655
+ };
656
+ };
657
+ const getHelpfulChildProcessError = (stdout, stderr) => {
658
+ if (isUnhelpfulNativeModuleError(stderr)) {
659
+ return getNativeModuleErrorMessage(stderr);
660
+ }
661
+ if (isModulesSyntaxError(stderr)) {
662
+ return getModuleSyntaxError();
663
+ }
664
+ if (isModuleNotFoundError(stderr)) {
665
+ return getModuleNotFoundError(stderr);
666
+ }
667
+ const lines = splitLines$1(stderr);
668
+ const {
669
+ actualMessage,
670
+ rest
671
+ } = getDetails(lines);
672
+ return {
673
+ message: actualMessage,
674
+ code: '',
675
+ stack: rest
676
+ };
677
+ };
678
+ class IpcError extends VError {
679
+ // @ts-ignore
680
+ constructor(betterMessage, stdout = '', stderr = '') {
681
+ if (stdout || stderr) {
682
+ // @ts-ignore
683
+ const {
684
+ message,
685
+ code,
686
+ stack
687
+ } = getHelpfulChildProcessError(stdout, stderr);
688
+ const cause = new Error(message);
689
+ // @ts-ignore
690
+ cause.code = code;
691
+ cause.stack = stack;
692
+ super(cause, betterMessage);
693
+ } else {
694
+ super(betterMessage);
695
+ }
696
+ // @ts-ignore
697
+ this.name = 'IpcError';
698
+ // @ts-ignore
699
+ this.stdout = stdout;
700
+ // @ts-ignore
701
+ this.stderr = stderr;
702
+ }
703
+ }
704
+ const listen$b = ({
705
+ messagePort
706
+ }) => {
707
+ if (!isMessagePortMain(messagePort)) {
708
+ throw new IpcError('port must be of type MessagePortMain');
709
+ }
710
+ return messagePort;
711
+ };
712
+ const signal$c = messagePort => {
713
+ messagePort.start();
714
+ };
715
+ class IpcChildWithElectronMessagePort extends Ipc {
716
+ getData = getActualDataElectron;
717
+ send(message) {
718
+ this._rawIpc.postMessage(message);
719
+ }
720
+ sendAndTransfer(message) {
721
+ const {
722
+ newValue,
723
+ transfer
724
+ } = fixElectronParameters(message);
725
+ this._rawIpc.postMessage(newValue, transfer);
726
+ }
727
+ dispose() {
728
+ this._rawIpc.close();
729
+ }
730
+ onMessage(callback) {
731
+ this._rawIpc.on('message', callback);
732
+ }
733
+ onClose(callback) {
734
+ this._rawIpc.on('close', callback);
735
+ }
736
+ }
737
+ const wrap$j = messagePort => {
738
+ return new IpcChildWithElectronMessagePort(messagePort);
739
+ };
740
+ const IpcChildWithElectronMessagePort$1 = {
741
+ __proto__: null,
742
+ listen: listen$b,
743
+ signal: signal$c,
744
+ wrap: wrap$j
745
+ };
746
+
747
+ // @ts-ignore
748
+ const getUtilityProcessPortData = event => {
749
+ const {
750
+ data,
751
+ ports
752
+ } = event;
753
+ if (ports.length === 0) {
754
+ return data;
755
+ }
756
+ return {
757
+ ...data,
758
+ params: [...ports, ...data.params]
759
+ };
760
+ };
761
+ const readyMessage = 'ready';
762
+ const listen$a = () => {
763
+ // @ts-ignore
764
+ const {
765
+ parentPort
766
+ } = process;
767
+ if (!parentPort) {
768
+ throw new Error('parent port must be defined');
769
+ }
770
+ return parentPort;
771
+ };
772
+ const signal$b = parentPort => {
773
+ parentPort.postMessage(readyMessage);
774
+ };
775
+ class IpcChildWithElectronUtilityProcess extends Ipc {
776
+ getData(event) {
777
+ return getUtilityProcessPortData(event);
778
+ }
779
+ send(message) {
780
+ this._rawIpc.postMessage(message);
781
+ }
782
+ sendAndTransfer(message) {
783
+ const {
784
+ newValue,
785
+ transfer
786
+ } = fixElectronParameters(message);
787
+ this._rawIpc.postMessage(newValue, transfer);
788
+ }
789
+ dispose() {
790
+ this._rawIpc.close();
791
+ }
792
+ onClose(callback) {
793
+ this._rawIpc.on('close', callback);
794
+ }
795
+ onMessage(callback) {
796
+ this._rawIpc.on('message', callback);
797
+ }
798
+ }
799
+ const wrap$i = parentPort => {
800
+ return new IpcChildWithElectronUtilityProcess(parentPort);
801
+ };
802
+ const IpcChildWithElectronUtilityProcess$1 = {
803
+ __proto__: null,
804
+ listen: listen$a,
805
+ signal: signal$b,
806
+ wrap: wrap$i
807
+ };
808
+ const getActualData = (message, handle) => {
809
+ if (handle) {
810
+ return {
811
+ ...message,
812
+ params: [handle, ...message.params]
813
+ };
814
+ }
815
+ return message;
816
+ };
817
+ const getTransferrablesNode = value => {
818
+ const transferrables = getTransferrables(value);
819
+ if (transferrables.length === 0) {
820
+ throw new Error(`no transferrables found`);
821
+ }
822
+ return transferrables[0];
823
+ };
824
+ const listen$5 = async () => {
825
+ if (!process.send) {
826
+ throw new Error('process.send must be defined');
827
+ }
828
+ return process;
829
+ };
830
+ const signal$7 = process => {
831
+ process.send(readyMessage);
832
+ };
833
+ class IpcChildWithNodeForkedProcess extends Ipc {
834
+ getData(message, handle) {
835
+ return getActualData(message, handle);
836
+ }
837
+ onClose(callback) {
838
+ this._rawIpc.on('close', callback);
839
+ }
840
+ send(message) {
841
+ this._rawIpc.send(message);
842
+ }
843
+ onMessage(callback) {
844
+ this._rawIpc.on('message', callback);
845
+ }
846
+ sendAndTransfer(message) {
847
+ const transfer = getTransferrablesNode(message);
848
+ this._rawIpc.send(message, transfer);
849
+ }
850
+ dispose() {
851
+ // ignore
852
+ }
853
+ }
854
+ const wrap$d = process => {
855
+ return new IpcChildWithNodeForkedProcess(process);
856
+ };
857
+ const IpcChildWithNodeForkedProcess$1 = {
858
+ __proto__: null,
859
+ listen: listen$5,
860
+ signal: signal$7,
861
+ wrap: wrap$d
862
+ };
863
+ const listen$3 = async () => {
864
+ const {
865
+ parentPort
866
+ } = await import('node:worker_threads');
867
+ if (!parentPort) {
868
+ throw new IpcError('parentPort is required');
869
+ }
870
+ return parentPort;
871
+ };
872
+ const signal$5 = parentPort => {
873
+ parentPort.postMessage(readyMessage);
874
+ };
875
+ class IpcChildWithNodeWorker extends Ipc {
876
+ getData(data) {
877
+ return data;
878
+ }
879
+ onClose(callback) {
880
+ this._rawIpc.on('close', callback);
881
+ }
882
+ send(message) {
883
+ this._rawIpc.postMessage(message);
884
+ }
885
+ onMessage(callback) {
886
+ this._rawIpc.on('message', callback);
887
+ }
888
+ sendAndTransfer(message) {
889
+ const transfer = getTransferrablesNode(message);
890
+ this._rawIpc.postMessage(message, transfer);
891
+ }
892
+ dispose() {
893
+ this._rawIpc.close();
894
+ }
895
+ }
896
+ const wrap$b = parentPort => {
897
+ return new IpcChildWithNodeWorker(parentPort);
898
+ };
899
+ const IpcChildWithNodeWorker$1 = {
900
+ __proto__: null,
901
+ listen: listen$3,
902
+ signal: signal$5,
903
+ wrap: wrap$b
904
+ };
905
+ const Open = 2;
906
+ const Close = 3;
907
+ const addListener = (emitter, type, callback) => {
908
+ if ('addEventListener' in emitter) {
909
+ emitter.addEventListener(type, callback);
910
+ } else {
911
+ emitter.on(type, callback);
912
+ }
913
+ };
914
+ const removeListener = (emitter, type, callback) => {
915
+ if ('removeEventListener' in emitter) {
916
+ emitter.removeEventListener(type, callback);
917
+ } else {
918
+ emitter.off(type, callback);
919
+ }
920
+ };
921
+ const getFirstEvent = (eventEmitter, eventMap) => {
922
+ const {
923
+ resolve,
924
+ promise
925
+ } = Promise.withResolvers();
926
+ const listenerMap = Object.create(null);
927
+ const cleanup = value => {
928
+ for (const event of Object.keys(eventMap)) {
929
+ removeListener(eventEmitter, event, listenerMap[event]);
930
+ }
931
+ resolve(value);
932
+ };
933
+ for (const [event, type] of Object.entries(eventMap)) {
934
+ const listener = event => {
935
+ cleanup({
936
+ type,
937
+ event
938
+ });
939
+ };
940
+ addListener(eventEmitter, event, listener);
941
+ listenerMap[event] = listener;
942
+ }
943
+ return promise;
944
+ };
945
+
946
+ // @ts-ignore
947
+ const getFirstWebSocketEvent = async webSocket => {
948
+ // @ts-ignore
949
+ const {
950
+ WebSocket
951
+ } = await import('ws');
952
+ switch (webSocket.readyState) {
953
+ case WebSocket.OPEN:
954
+ return {
955
+ type: Open,
956
+ event: undefined
957
+ };
958
+ case WebSocket.CLOSED:
959
+ return {
960
+ type: Close,
961
+ event: undefined
962
+ };
963
+ }
964
+ // @ts-ignore
965
+ const {
966
+ type,
967
+ event
968
+ } = await getFirstEvent(webSocket, {
969
+ open: Open,
970
+ close: Close
971
+ });
972
+ return {
973
+ type,
974
+ event
975
+ };
976
+ };
977
+
978
+ // @ts-ignore
979
+ const isWebSocketOpen = async webSocket => {
980
+ // @ts-ignore
981
+ const {
982
+ WebSocket
983
+ } = await import('ws');
984
+ return webSocket.readyState === WebSocket.OPEN;
985
+ };
986
+
987
+ // @ts-ignore
988
+ const serialize = message => {
989
+ return JSON.stringify(message);
990
+ };
991
+
992
+ // @ts-ignore
993
+ const deserialize = message => {
994
+ return JSON.parse(message.toString());
995
+ };
996
+
997
+ // @ts-ignore
998
+ const handleUpgrade$1 = async (...args) => {
999
+ const module = await Promise.resolve().then(function () { return index; });
1000
+ // @ts-ignore
1001
+ return module.handleUpgrade(...args);
1002
+ };
1003
+
1004
+ // @ts-ignore
1005
+ const listen$1$1 = async ({
1006
+ request,
1007
+ handle
1008
+ }) => {
1009
+ if (!request) {
1010
+ throw new IpcError('request must be defined');
1011
+ }
1012
+ if (!handle) {
1013
+ throw new IpcError('handle must be defined');
1014
+ }
1015
+ const webSocket = await handleUpgrade$1(request, handle);
1016
+ webSocket.pause();
1017
+ if (!(await isWebSocketOpen(webSocket))) {
1018
+ await getFirstWebSocketEvent(webSocket);
1019
+ }
1020
+ return webSocket;
1021
+ };
1022
+ const signal$4 = webSocket => {
1023
+ webSocket.resume();
1024
+ };
1025
+
1026
+ // @ts-ignore
1027
+ const wrap$9 = webSocket => {
1028
+ return {
1029
+ webSocket,
1030
+ /**
1031
+ * @type {any}
1032
+ */
1033
+ wrappedListener: undefined,
1034
+ // @ts-ignore
1035
+ on(event, listener) {
1036
+ switch (event) {
1037
+ case 'message':
1038
+ // @ts-ignore
1039
+ const wrappedListener = message => {
1040
+ const data = deserialize(message);
1041
+ const event = {
1042
+ data,
1043
+ target: this
1044
+ };
1045
+ listener(event);
1046
+ };
1047
+ webSocket.on('message', wrappedListener);
1048
+ break;
1049
+ case 'close':
1050
+ webSocket.on('close', listener);
1051
+ break;
1052
+ default:
1053
+ throw new Error('unknown event listener type');
1054
+ }
1055
+ },
1056
+ // @ts-ignore
1057
+ off(event, listener) {
1058
+ this.webSocket.off(event, listener);
1059
+ },
1060
+ // @ts-ignore
1061
+ send(message) {
1062
+ const stringifiedMessage = serialize(message);
1063
+ this.webSocket.send(stringifiedMessage);
1064
+ },
1065
+ dispose() {
1066
+ this.webSocket.close();
1067
+ },
1068
+ start() {
1069
+ throw new Error('start method is deprecated');
1070
+ }
1071
+ };
1072
+ };
1073
+ const IpcChildWithWebSocket = {
1074
+ __proto__: null,
1075
+ listen: listen$1$1,
1076
+ signal: signal$4,
1077
+ wrap: wrap$9
1078
+ };
1079
+
1080
+ const Two = '2.0';
1081
+ const create$4$1 = (method, params) => {
1082
+ return {
1083
+ jsonrpc: Two,
1084
+ method,
1085
+ params
1086
+ };
1087
+ };
1088
+ const callbacks = Object.create(null);
1089
+ const set = (id, fn) => {
1090
+ callbacks[id] = fn;
1091
+ };
1092
+ const get = id => {
1093
+ return callbacks[id];
1094
+ };
1095
+ const remove = id => {
1096
+ delete callbacks[id];
1097
+ };
1098
+ let id = 0;
1099
+ const create$3 = () => {
1100
+ return ++id;
1101
+ };
1102
+ const registerPromise = () => {
1103
+ const id = create$3();
1104
+ const {
1105
+ resolve,
1106
+ promise
1107
+ } = Promise.withResolvers();
1108
+ set(id, resolve);
1109
+ return {
1110
+ id,
1111
+ promise
1112
+ };
1113
+ };
1114
+ const create$2 = (method, params) => {
1115
+ const {
1116
+ id,
1117
+ promise
1118
+ } = registerPromise();
1119
+ const message = {
1120
+ jsonrpc: Two,
1121
+ method,
1122
+ params,
1123
+ id
1124
+ };
1125
+ return {
1126
+ message,
1127
+ promise
1128
+ };
1129
+ };
1130
+ class JsonRpcError extends Error {
1131
+ constructor(message) {
1132
+ super(message);
1133
+ this.name = 'JsonRpcError';
1134
+ }
1135
+ }
1136
+ const NewLine = '\n';
1137
+ const DomException = 'DOMException';
1138
+ const ReferenceError$1 = 'ReferenceError';
1139
+ const SyntaxError$1 = 'SyntaxError';
1140
+ const TypeError$1 = 'TypeError';
1141
+ const getErrorConstructor = (message, type) => {
1142
+ if (type) {
1143
+ switch (type) {
1144
+ case DomException:
1145
+ return DOMException;
1146
+ case TypeError$1:
1147
+ return TypeError;
1148
+ case SyntaxError$1:
1149
+ return SyntaxError;
1150
+ case ReferenceError$1:
1151
+ return ReferenceError;
1152
+ default:
1153
+ return Error;
1154
+ }
1155
+ }
1156
+ if (message.startsWith('TypeError: ')) {
1157
+ return TypeError;
1158
+ }
1159
+ if (message.startsWith('SyntaxError: ')) {
1160
+ return SyntaxError;
1161
+ }
1162
+ if (message.startsWith('ReferenceError: ')) {
1163
+ return ReferenceError;
1164
+ }
1165
+ return Error;
1166
+ };
1167
+ const constructError = (message, type, name) => {
1168
+ const ErrorConstructor = getErrorConstructor(message, type);
1169
+ if (ErrorConstructor === DOMException && name) {
1170
+ return new ErrorConstructor(message, name);
1171
+ }
1172
+ if (ErrorConstructor === Error) {
1173
+ const error = new Error(message);
1174
+ if (name && name !== 'VError') {
1175
+ error.name = name;
1176
+ }
1177
+ return error;
1178
+ }
1179
+ return new ErrorConstructor(message);
1180
+ };
1181
+ const getNewLineIndex = (string, startIndex = undefined) => {
1182
+ return string.indexOf(NewLine, startIndex);
1183
+ };
1184
+ const getParentStack = error => {
1185
+ let parentStack = error.stack || error.data || error.message || '';
1186
+ if (parentStack.startsWith(' at')) {
1187
+ parentStack = error.message + NewLine + parentStack;
1188
+ }
1189
+ return parentStack;
1190
+ };
1191
+ const joinLines = lines => {
1192
+ return lines.join(NewLine);
1193
+ };
1194
+ const MethodNotFound = -32601;
1195
+ const Custom = -32001;
1196
+ const splitLines = lines => {
1197
+ return lines.split(NewLine);
1198
+ };
1199
+ const restoreJsonRpcError = error => {
1200
+ if (error && error instanceof Error) {
1201
+ return error;
1202
+ }
1203
+ const currentStack = joinLines(splitLines(new Error().stack || '').slice(1));
1204
+ if (error && error.code && error.code === MethodNotFound) {
1205
+ const restoredError = new JsonRpcError(error.message);
1206
+ const parentStack = getParentStack(error);
1207
+ restoredError.stack = parentStack + NewLine + currentStack;
1208
+ return restoredError;
1209
+ }
1210
+ if (error && error.message) {
1211
+ const restoredError = constructError(error.message, error.type, error.name);
1212
+ if (error.data) {
1213
+ if (error.data.stack && error.data.type && error.message) {
1214
+ restoredError.stack = error.data.type + ': ' + error.message + NewLine + error.data.stack + NewLine + currentStack;
1215
+ } else if (error.data.stack) {
1216
+ restoredError.stack = error.data.stack;
1217
+ }
1218
+ if (error.data.codeFrame) {
1219
+ // @ts-ignore
1220
+ restoredError.codeFrame = error.data.codeFrame;
1221
+ }
1222
+ if (error.data.code) {
1223
+ // @ts-ignore
1224
+ restoredError.code = error.data.code;
1225
+ }
1226
+ if (error.data.type) {
1227
+ // @ts-ignore
1228
+ restoredError.name = error.data.type;
1229
+ }
1230
+ } else {
1231
+ if (error.stack) {
1232
+ const lowerStack = restoredError.stack || '';
1233
+ // @ts-ignore
1234
+ const indexNewLine = getNewLineIndex(lowerStack);
1235
+ const parentStack = getParentStack(error);
1236
+ // @ts-ignore
1237
+ restoredError.stack = parentStack + lowerStack.slice(indexNewLine);
1238
+ }
1239
+ if (error.codeFrame) {
1240
+ // @ts-ignore
1241
+ restoredError.codeFrame = error.codeFrame;
1242
+ }
1243
+ }
1244
+ return restoredError;
1245
+ }
1246
+ if (typeof error === 'string') {
1247
+ return new Error(`JsonRpc Error: ${error}`);
1248
+ }
1249
+ return new Error(`JsonRpc Error: ${error}`);
1250
+ };
1251
+ const unwrapJsonRpcResult = responseMessage => {
1252
+ if ('error' in responseMessage) {
1253
+ const restoredError = restoreJsonRpcError(responseMessage.error);
1254
+ throw restoredError;
1255
+ }
1256
+ if ('result' in responseMessage) {
1257
+ return responseMessage.result;
1258
+ }
1259
+ throw new JsonRpcError('unexpected response message');
1260
+ };
1261
+ const warn = (...args) => {
1262
+ console.warn(...args);
1263
+ };
1264
+ const resolve = (id, response) => {
1265
+ const fn = get(id);
1266
+ if (!fn) {
1267
+ console.log(response);
1268
+ warn(`callback ${id} may already be disposed`);
1269
+ return;
1270
+ }
1271
+ fn(response);
1272
+ remove(id);
1273
+ };
1274
+ const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND';
1275
+ const getErrorType = prettyError => {
1276
+ if (prettyError && prettyError.type) {
1277
+ return prettyError.type;
1278
+ }
1279
+ if (prettyError && prettyError.constructor && prettyError.constructor.name) {
1280
+ return prettyError.constructor.name;
1281
+ }
1282
+ return undefined;
1283
+ };
1284
+ const getErrorProperty = (error, prettyError) => {
1285
+ if (error && error.code === E_COMMAND_NOT_FOUND) {
1286
+ return {
1287
+ code: MethodNotFound,
1288
+ message: error.message,
1289
+ data: error.stack
1290
+ };
1291
+ }
1292
+ return {
1293
+ code: Custom,
1294
+ message: prettyError.message,
1295
+ data: {
1296
+ stack: prettyError.stack,
1297
+ codeFrame: prettyError.codeFrame,
1298
+ type: getErrorType(prettyError),
1299
+ code: prettyError.code,
1300
+ name: prettyError.name
1301
+ }
1302
+ };
1303
+ };
1304
+ const create$1 = (message, error) => {
1305
+ return {
1306
+ jsonrpc: Two,
1307
+ id: message.id,
1308
+ error
1309
+ };
1310
+ };
1311
+ const getErrorResponse = (message, error, preparePrettyError, logError) => {
1312
+ const prettyError = preparePrettyError(error);
1313
+ logError(error, prettyError);
1314
+ const errorProperty = getErrorProperty(error, prettyError);
1315
+ return create$1(message, errorProperty);
1316
+ };
1317
+ const create = (message, result) => {
1318
+ return {
1319
+ jsonrpc: Two,
1320
+ id: message.id,
1321
+ result: result ?? null
1322
+ };
1323
+ };
1324
+ const getSuccessResponse = (message, result) => {
1325
+ const resultProperty = result ?? null;
1326
+ return create(message, resultProperty);
1327
+ };
1328
+ const getResponse = async (message, ipc, execute, preparePrettyError, logError, requiresSocket) => {
1329
+ try {
1330
+ const result = requiresSocket(message.method) ? await execute(message.method, ipc, ...message.params) : await execute(message.method, ...message.params);
1331
+ return getSuccessResponse(message, result);
1332
+ } catch (error) {
1333
+ return getErrorResponse(message, error, preparePrettyError, logError);
1334
+ }
1335
+ };
1336
+ const defaultPreparePrettyError = error => {
1337
+ return error;
1338
+ };
1339
+ const defaultLogError = () => {
1340
+ // ignore
1341
+ };
1342
+ const defaultRequiresSocket = () => {
1343
+ return false;
1344
+ };
1345
+ const defaultResolve = resolve;
1346
+
1347
+ // TODO maybe remove this in v6 or v7, only accept options object to simplify the code
1348
+ const normalizeParams = args => {
1349
+ if (args.length === 1) {
1350
+ const options = args[0];
1351
+ return {
1352
+ ipc: options.ipc,
1353
+ message: options.message,
1354
+ execute: options.execute,
1355
+ resolve: options.resolve || defaultResolve,
1356
+ preparePrettyError: options.preparePrettyError || defaultPreparePrettyError,
1357
+ logError: options.logError || defaultLogError,
1358
+ requiresSocket: options.requiresSocket || defaultRequiresSocket
1359
+ };
1360
+ }
1361
+ return {
1362
+ ipc: args[0],
1363
+ message: args[1],
1364
+ execute: args[2],
1365
+ resolve: args[3],
1366
+ preparePrettyError: args[4],
1367
+ logError: args[5],
1368
+ requiresSocket: args[6]
1369
+ };
1370
+ };
1371
+ const handleJsonRpcMessage = async (...args) => {
1372
+ const options = normalizeParams(args);
1373
+ const {
1374
+ message,
1375
+ ipc,
1376
+ execute,
1377
+ resolve,
1378
+ preparePrettyError,
1379
+ logError,
1380
+ requiresSocket
1381
+ } = options;
1382
+ if ('id' in message) {
1383
+ if ('method' in message) {
1384
+ const response = await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1385
+ try {
1386
+ ipc.send(response);
1387
+ } catch (error) {
1388
+ const errorResponse = getErrorResponse(message, error, preparePrettyError, logError);
1389
+ ipc.send(errorResponse);
1390
+ }
1391
+ return;
1392
+ }
1393
+ resolve(message.id, message);
1394
+ return;
1395
+ }
1396
+ if ('method' in message) {
1397
+ await getResponse(message, ipc, execute, preparePrettyError, logError, requiresSocket);
1398
+ return;
1399
+ }
1400
+ throw new JsonRpcError('unexpected message');
1401
+ };
1402
+ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
1403
+ const {
1404
+ message,
1405
+ promise
1406
+ } = create$2(method, params);
1407
+ if (useSendAndTransfer && ipc.sendAndTransfer) {
1408
+ ipc.sendAndTransfer(message);
1409
+ } else {
1410
+ ipc.send(message);
1411
+ }
1412
+ const responseMessage = await promise;
1413
+ return unwrapJsonRpcResult(responseMessage);
1414
+ };
1415
+ const send = (transport, method, ...params) => {
1416
+ const message = create$4$1(method, params);
1417
+ transport.send(message);
1418
+ };
1419
+ const invoke = (ipc, method, ...params) => {
1420
+ return invokeHelper(ipc, method, params, false);
1421
+ };
1422
+ const invokeAndTransfer = (ipc, method, ...params) => {
1423
+ return invokeHelper(ipc, method, params, true);
1424
+ };
1425
+
1426
+ const commands = Object.create(null);
1427
+ const register = commandMap => {
1428
+ Object.assign(commands, commandMap);
1429
+ };
1430
+ const getCommand = key => {
1431
+ return commands[key];
1432
+ };
1433
+ const execute = (command, ...args) => {
1434
+ const fn = getCommand(command);
1435
+ if (!fn) {
1436
+ throw new Error(`command not found ${command}`);
1437
+ }
1438
+ return fn(...args);
1439
+ };
1440
+
1441
+ const createRpc = ipc => {
1442
+ const rpc = {
1443
+ // @ts-ignore
1444
+ ipc,
1445
+ /**
1446
+ * @deprecated
1447
+ */
1448
+ send(method, ...params) {
1449
+ send(ipc, method, ...params);
1450
+ },
1451
+ invoke(method, ...params) {
1452
+ return invoke(ipc, method, ...params);
1453
+ },
1454
+ invokeAndTransfer(method, ...params) {
1455
+ return invokeAndTransfer(ipc, method, ...params);
1456
+ },
1457
+ async dispose() {
1458
+ await ipc?.dispose();
1459
+ }
1460
+ };
1461
+ return rpc;
1462
+ };
1463
+ const requiresSocket = () => {
1464
+ return false;
1465
+ };
1466
+ const preparePrettyError = error => {
1467
+ return error;
1468
+ };
1469
+ const logError = () => {
1470
+ // handled by renderer worker
1471
+ };
1472
+ const handleMessage = event => {
1473
+ const actualRequiresSocket = event?.target?.requiresSocket || requiresSocket;
1474
+ const actualExecute = event?.target?.execute || execute;
1475
+ return handleJsonRpcMessage(event.target, event.data, actualExecute, resolve, preparePrettyError, logError, actualRequiresSocket);
1476
+ };
1477
+ const handleIpc = ipc => {
1478
+ if ('addEventListener' in ipc) {
1479
+ ipc.addEventListener('message', handleMessage);
1480
+ } else if ('on' in ipc) {
1481
+ // deprecated
1482
+ ipc.on('message', handleMessage);
1483
+ }
1484
+ };
1485
+ const listen$2 = async (module, options) => {
1486
+ const rawIpc = await module.listen(options);
1487
+ if (module.signal) {
1488
+ module.signal(rawIpc);
1489
+ }
1490
+ const ipc = module.wrap(rawIpc);
1491
+ return ipc;
1492
+ };
1493
+ const create$e = async ({
1494
+ commandMap,
1495
+ messagePort,
1496
+ requiresSocket
1497
+ }) => {
1498
+ // TODO create a commandMap per rpc instance
1499
+ register(commandMap);
1500
+ const ipc = await listen$2(IpcChildWithElectronMessagePort$1, {
1501
+ messagePort
1502
+ });
1503
+ if (requiresSocket) {
1504
+ ipc.requiresSocket = requiresSocket;
1505
+ }
1506
+ handleIpc(ipc);
1507
+ const rpc = createRpc(ipc);
1508
+ return rpc;
1509
+ };
1510
+ const ElectronMessagePortRpcClient = {
1511
+ __proto__: null,
1512
+ create: create$e
1513
+ };
1514
+ const create$d = async ({
1515
+ commandMap
1516
+ }) => {
1517
+ // TODO create a commandMap per rpc instance
1518
+ register(commandMap);
1519
+ const ipc = await listen$2(IpcChildWithElectronUtilityProcess$1);
1520
+ handleIpc(ipc);
1521
+ const rpc = createRpc(ipc);
1522
+ return rpc;
1523
+ };
1524
+ const ElectronUtilityProcessRpcClient = {
1525
+ __proto__: null,
1526
+ create: create$d
1527
+ };
1528
+ const create$7 = async ({
1529
+ commandMap
1530
+ }) => {
1531
+ // TODO create a commandMap per rpc instance
1532
+ register(commandMap);
1533
+ const ipc = await listen$2(IpcChildWithNodeForkedProcess$1);
1534
+ handleIpc(ipc);
1535
+ const rpc = createRpc(ipc);
1536
+ return rpc;
1537
+ };
1538
+ const NodeForkedProcessRpcClient = {
1539
+ __proto__: null,
1540
+ create: create$7
1541
+ };
1542
+ const create$5 = async ({
1543
+ commandMap,
1544
+ request,
1545
+ handle,
1546
+ requiresSocket
1547
+ }) => {
1548
+ // TODO create a commandMap per rpc instance
1549
+ register(commandMap);
1550
+ const ipc = await listen$2(IpcChildWithWebSocket, {
1551
+ request,
1552
+ handle
1553
+ });
1554
+ if (requiresSocket) {
1555
+ ipc.requiresSocket = requiresSocket;
1556
+ }
1557
+ handleIpc(ipc);
1558
+ const rpc = createRpc(ipc);
1559
+ return rpc;
1560
+ };
1561
+ const NodeWebSocketRpcClient = {
1562
+ __proto__: null,
1563
+ create: create$5
1564
+ };
1565
+ const create$4 = async ({
1566
+ commandMap
1567
+ }) => {
1568
+ // TODO create a commandMap per rpc instance
1569
+ register(commandMap);
1570
+ const ipc = await listen$2(IpcChildWithNodeWorker$1);
1571
+ handleIpc(ipc);
1572
+ const rpc = createRpc(ipc);
1573
+ return rpc;
1574
+ };
1575
+ const NodeWorkerRpcClient = {
1576
+ __proto__: null,
1577
+ create: create$4
1578
+ };
1579
+
1580
+ const NodeWorker = 1;
1581
+ const NodeForkedProcess = 2;
1582
+ const ElectronUtilityProcess = 3;
1583
+ const ElectronMessagePort = 4;
1584
+ const WebSocket = 6;
1585
+ const Auto = argv => {
1586
+ if (argv.includes('--ipc-type=node-worker')) {
1587
+ return NodeWorker;
1588
+ }
1589
+ if (argv.includes('--ipc-type=node-forked-process')) {
1590
+ return NodeForkedProcess;
1591
+ }
1592
+ if (argv.includes('--ipc-type=electron-utility-process')) {
1593
+ return ElectronUtilityProcess;
1594
+ }
1595
+ throw new Error(`[file-system-process] unknown ipc type`);
1596
+ };
1597
+
1598
+ const getModule = method => {
1599
+ switch (method) {
1600
+ case NodeForkedProcess:
1601
+ return NodeForkedProcessRpcClient.create;
1602
+ case NodeWorker:
1603
+ return NodeWorkerRpcClient.create;
1604
+ case ElectronUtilityProcess:
1605
+ return ElectronUtilityProcessRpcClient.create;
1606
+ case ElectronMessagePort:
1607
+ return ElectronMessagePortRpcClient.create;
1608
+ case WebSocket:
1609
+ return NodeWebSocketRpcClient.create;
1610
+ default:
1611
+ throw new Error('unexpected ipc type');
1612
+ }
1613
+ };
1614
+
1615
+ const listen$1 = async ({
1616
+ method,
1617
+ ...params
1618
+ }) => {
1619
+ const create = getModule(method);
1620
+ const rpc = await create(params);
1621
+ return rpc;
1622
+ };
1623
+
1624
+ const handleElectronMessagePort = async (messagePort, ...params) => {
1625
+ object(messagePort);
1626
+ await listen$1({
1627
+ method: ElectronMessagePort,
1628
+ messagePort
1629
+ });
1630
+ };
1631
+
419
1632
  const handleWebSocket = async (handle, request) => {
420
1633
  object(handle);
421
1634
  object(request);
@@ -426,6 +1639,24 @@ const handleWebSocket = async (handle, request) => {
426
1639
  });
427
1640
  };
428
1641
 
1642
+ const createMainProcessRpc = async port => {
1643
+ try {
1644
+ const rpc = await ElectronMessagePortRpcClient.create({
1645
+ commandMap: {},
1646
+ messagePort: port
1647
+ });
1648
+ return rpc;
1649
+ } catch (error) {
1650
+ throw new VError(error, `Failed to create main process rpc`);
1651
+ }
1652
+ };
1653
+
1654
+ const initialize = async port => {
1655
+ // TODO only connect to main process if platform is electron else not
1656
+ const rpc = await createMainProcessRpc(port);
1657
+ set$1(rpc);
1658
+ };
1659
+
429
1660
  const commandMap = {
430
1661
  'FileSystem.chmod': chmod,
431
1662
  'FileSystem.copy': copy,
@@ -435,11 +1666,13 @@ const commandMap = {
435
1666
  'FileSystem.readDirWithFileTypes': readDirWithFileTypes,
436
1667
  'FileSystem.readFile': readFile,
437
1668
  'FileSystem.readJson': readJson,
438
- 'FileSystem.remove': remove,
1669
+ 'FileSystem.remove': remove$1,
439
1670
  'FileSystem.rename': rename,
440
1671
  'FileSystem.stat': stat,
441
1672
  'FileSystem.writeFile': writeFile,
442
- 'HandleWebSocket.handleWebSocket': handleWebSocket
1673
+ 'HandleElectronMessagePort.handleElectronMessagePort': handleElectronMessagePort,
1674
+ 'HandleWebSocket.handleWebSocket': handleWebSocket,
1675
+ 'Initialize.initialize': initialize
443
1676
  };
444
1677
 
445
1678
  const listen = async argv => {
@@ -454,3 +1687,36 @@ const main = async () => {
454
1687
  };
455
1688
 
456
1689
  main();
1690
+
1691
+ const createWebSocketServer = async () => {
1692
+ const _ws = await import('ws');
1693
+ // workaround for jest or node bug
1694
+ const WebSocketServer = _ws.WebSocketServer ? _ws.WebSocketServer :
1695
+ // @ts-ignore
1696
+ _ws.default.WebSocketServer;
1697
+ const webSocketServer = new WebSocketServer({
1698
+ noServer: true
1699
+
1700
+ // TODO not sure if ws compress is working at all
1701
+ // perMessageDeflate: true
1702
+ });
1703
+ return webSocketServer;
1704
+ };
1705
+ const doSocketUpgrade = (webSocketServer, request, socket) => {
1706
+ const {
1707
+ promise,
1708
+ resolve
1709
+ } = Promise.withResolvers();
1710
+ webSocketServer.handleUpgrade(request, socket, Buffer.alloc(0), resolve);
1711
+ return promise;
1712
+ };
1713
+ const handleUpgrade = async (request, socket) => {
1714
+ const webSocketServer = await createWebSocketServer();
1715
+ const webSocket = await doSocketUpgrade(webSocketServer, request, socket);
1716
+ return webSocket;
1717
+ };
1718
+
1719
+ const index = {
1720
+ __proto__: null,
1721
+ handleUpgrade
1722
+ };