@lvce-editor/ipc 2.0.0 → 3.0.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 (34) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +831 -7
  3. package/package.json +2 -2
  4. package/dist/parts/Assert/Assert.js +0 -1
  5. package/dist/parts/CamelCase/CamelCase.js +0 -11
  6. package/dist/parts/Character/Character.js +0 -12
  7. package/dist/parts/ErrorCodes/ErrorCodes.js +0 -22
  8. package/dist/parts/FirstNodeWorkerEventType/FirstNodeWorkerEventType.js +0 -3
  9. package/dist/parts/FirstWebSocketEventType/FirstWebSocketEventType.js +0 -2
  10. package/dist/parts/FormatUtilityProcessName/FormatUtilityProcessName.js +0 -5
  11. package/dist/parts/GetFirstEvent/GetFirstEvent.js +0 -23
  12. package/dist/parts/GetFirstNodeChildProcessEvent/GetFirstNodeChildProcessEvent.js +0 -41
  13. package/dist/parts/GetFirstNodeWorkerEvent/GetFirstNodeWorkerEvent.js +0 -9
  14. package/dist/parts/GetFirstUtilityProcessEvent/GetFirstUtilityProcessEvent.js +0 -42
  15. package/dist/parts/GetFirstWebSocketEvent/GetFirstWebSocketEvent.js +0 -25
  16. package/dist/parts/GetHelpfulChildProcessError/GetHelpfulChildProcessError.js +0 -119
  17. package/dist/parts/GetUtilityProcessPortData/GetUtilityProcessPortData.js +0 -10
  18. package/dist/parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js +0 -51
  19. package/dist/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +0 -45
  20. package/dist/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +0 -46
  21. package/dist/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +0 -59
  22. package/dist/parts/IpcError/IpcError.js +0 -20
  23. package/dist/parts/IpcParentWithElectronUtilityProcess/IpcParentWithElectronUtilityProcess.js +0 -43
  24. package/dist/parts/IpcParentWithNodeForkedProcess/IpcParentWithNodeForkedProcess.js +0 -37
  25. package/dist/parts/IpcParentWithNodeWorker/IpcParentWithNodeWorker.js +0 -49
  26. package/dist/parts/IsMessagePortMain/IsMessagePortMain.js +0 -3
  27. package/dist/parts/IsWebSocketOpen/IsWebSocketOpen.js +0 -5
  28. package/dist/parts/JoinLines/JoinLines.js +0 -5
  29. package/dist/parts/Promises/Promises.js +0 -19
  30. package/dist/parts/SplitLines/SplitLines.js +0 -5
  31. package/dist/parts/VError/VError.js +0 -1
  32. package/dist/parts/WebSocketReadyState/WebSocketReadyState.js +0 -5
  33. package/dist/parts/WebSocketSerialization/WebSocketSerialization.js +0 -7
  34. package/dist/parts/WebSocketServer/WebSocketServer.js +0 -1
package/dist/index.js CHANGED
@@ -1,7 +1,831 @@
1
- export * as IpcChildWithElectronMessagePort from './parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js'
2
- export * as IpcChildWithElectronUtilityProcess from './parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js'
3
- export * as IpcChildWithNodeForkedProcess from './parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js'
4
- export * as IpcChildWithWebSocket from './parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js'
5
- export * as IpcParentWithElectronUtilityProcess from './parts/IpcParentWithElectronUtilityProcess/IpcParentWithElectronUtilityProcess.js'
6
- export * as IpcParentWithNodeForkedProcess from './parts/IpcParentWithNodeForkedProcess/IpcParentWithNodeForkedProcess.js'
7
- export * as IpcParentWithNodeWorker from './parts/IpcParentWithNodeWorker/IpcParentWithNodeWorker.js'
1
+ import { VError } from '@lvce-editor/verror';
2
+ import { string, array } from '@lvce-editor/assert';
3
+ import { fork } from 'node:child_process';
4
+ import { Worker } from 'node:worker_threads';
5
+
6
+ const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE';
7
+ const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON';
8
+ const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND';
9
+
10
+ const NewLine = '\n';
11
+
12
+ const splitLines = lines => {
13
+ return lines.split(NewLine);
14
+ };
15
+
16
+ const joinLines = lines => {
17
+ return lines.join(NewLine);
18
+ };
19
+
20
+ const RE_NATIVE_MODULE_ERROR = /^innerError Error: Cannot find module '.*.node'/;
21
+ const RE_NATIVE_MODULE_ERROR_2 = /was compiled against a different Node.js version/;
22
+ const RE_MESSAGE_CODE_BLOCK_START = /^Error: The module '.*'$/;
23
+ const RE_MESSAGE_CODE_BLOCK_END = /^\s* at/;
24
+ const RE_AT = /^\s+at/;
25
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/;
26
+ const isUnhelpfulNativeModuleError = stderr => {
27
+ return RE_NATIVE_MODULE_ERROR.test(stderr) && RE_NATIVE_MODULE_ERROR_2.test(stderr);
28
+ };
29
+ const isMessageCodeBlockStartIndex = line => {
30
+ return RE_MESSAGE_CODE_BLOCK_START.test(line);
31
+ };
32
+ const isMessageCodeBlockEndIndex = line => {
33
+ return RE_MESSAGE_CODE_BLOCK_END.test(line);
34
+ };
35
+ const getMessageCodeBlock = stderr => {
36
+ const lines = splitLines(stderr);
37
+ const startIndex = lines.findIndex(isMessageCodeBlockStartIndex);
38
+ const endIndex = startIndex + lines.slice(startIndex).findIndex(isMessageCodeBlockEndIndex, startIndex);
39
+ const relevantLines = lines.slice(startIndex, endIndex);
40
+ const relevantMessage = relevantLines.join(' ').slice('Error: '.length);
41
+ return relevantMessage;
42
+ };
43
+ const getNativeModuleErrorMessage = stderr => {
44
+ const message = getMessageCodeBlock(stderr);
45
+ return {
46
+ message: `Incompatible native node module: ${message}`,
47
+ code: E_INCOMPATIBLE_NATIVE_MODULE
48
+ };
49
+ };
50
+ const isModulesSyntaxError = stderr => {
51
+ if (!stderr) {
52
+ return false;
53
+ }
54
+ return stderr.includes('SyntaxError: Cannot use import statement outside a module');
55
+ };
56
+ const getModuleSyntaxError = stderr => {
57
+ return {
58
+ message: `ES Modules are not supported in electron`,
59
+ code: E_MODULES_NOT_SUPPORTED_IN_ELECTRON
60
+ };
61
+ };
62
+ const isModuleNotFoundError = stderr => {
63
+ if (!stderr) {
64
+ return false;
65
+ }
66
+ return stderr.includes('ERR_MODULE_NOT_FOUND');
67
+ };
68
+ const isModuleNotFoundMessage = line => {
69
+ return line.includes('ERR_MODULE_NOT_FOUND');
70
+ };
71
+ const getModuleNotFoundError = stderr => {
72
+ const lines = splitLines(stderr);
73
+ const messageIndex = lines.findIndex(isModuleNotFoundMessage);
74
+ const message = lines[messageIndex];
75
+ return {
76
+ message,
77
+ code: ERR_MODULE_NOT_FOUND
78
+ };
79
+ };
80
+ const isNormalStackLine = line => {
81
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line);
82
+ };
83
+ const getDetails = lines => {
84
+ const index = lines.findIndex(isNormalStackLine);
85
+ if (index === -1) {
86
+ return {
87
+ actualMessage: joinLines(lines),
88
+ rest: []
89
+ };
90
+ }
91
+ let lastIndex = index - 1;
92
+ while (++lastIndex < lines.length) {
93
+ if (!isNormalStackLine(lines[lastIndex])) {
94
+ break;
95
+ }
96
+ }
97
+ return {
98
+ actualMessage: lines[index - 1],
99
+ rest: lines.slice(index, lastIndex)
100
+ };
101
+ };
102
+ const getHelpfulChildProcessError = (stdout, stderr) => {
103
+ if (isUnhelpfulNativeModuleError(stderr)) {
104
+ return getNativeModuleErrorMessage(stderr);
105
+ }
106
+ if (isModulesSyntaxError(stderr)) {
107
+ return getModuleSyntaxError();
108
+ }
109
+ if (isModuleNotFoundError(stderr)) {
110
+ return getModuleNotFoundError(stderr);
111
+ }
112
+ const lines = splitLines(stderr);
113
+ const {
114
+ actualMessage,
115
+ rest
116
+ } = getDetails(lines);
117
+ return {
118
+ message: `${actualMessage}`,
119
+ code: '',
120
+ stack: rest
121
+ };
122
+ };
123
+
124
+ class IpcError extends VError {
125
+ constructor(message, stdout = '', stderr = '') {
126
+ if (stdout || stderr) {
127
+ // @ts-ignore
128
+ const {
129
+ message,
130
+ code,
131
+ stack
132
+ } = getHelpfulChildProcessError(stdout, stderr);
133
+ const cause = new Error(message);
134
+ // @ts-ignore
135
+ cause.code = code;
136
+ cause.stack = stack;
137
+ super(cause, message);
138
+ } else {
139
+ super(message);
140
+ }
141
+ // @ts-ignore
142
+ this.name = 'IpcError';
143
+ // @ts-ignore
144
+ this.stdout = stdout;
145
+ // @ts-ignore
146
+ this.stderr = stderr;
147
+ }
148
+ }
149
+
150
+ const isMessagePortMain = value => {
151
+ return value && value.constructor && value.constructor.name === 'MessagePortMain';
152
+ };
153
+
154
+ const listen$3 = ({
155
+ messagePort
156
+ }) => {
157
+ if (!isMessagePortMain(messagePort)) {
158
+ throw new IpcError('port must be of type MessagePortMain');
159
+ }
160
+ return messagePort;
161
+ };
162
+ const getActualData$1 = event => {
163
+ const {
164
+ data,
165
+ ports
166
+ } = event;
167
+ if (ports.length === 0) {
168
+ return data;
169
+ }
170
+ return {
171
+ ...data,
172
+ params: [...ports, ...data.params]
173
+ };
174
+ };
175
+ const wrap$6 = messagePort => {
176
+ return {
177
+ messagePort,
178
+ on(event, listener) {
179
+ if (event === 'message') {
180
+ const wrappedListener = event => {
181
+ const actualData = getActualData$1(event);
182
+ listener(actualData);
183
+ };
184
+ this.messagePort.on(event, wrappedListener);
185
+ } else if (event === 'close') {
186
+ this.messagePort.on('close', listener);
187
+ } else {
188
+ throw new Error('unsupported event type');
189
+ }
190
+ },
191
+ off(event, listener) {
192
+ this.messagePort.off(event, listener);
193
+ },
194
+ send(message) {
195
+ this.messagePort.postMessage(message);
196
+ },
197
+ dispose() {
198
+ this.messagePort.close();
199
+ },
200
+ start() {
201
+ this.messagePort.start();
202
+ }
203
+ };
204
+ };
205
+
206
+ const IpcChildWithElectronMessagePort = {
207
+ __proto__: null,
208
+ listen: listen$3,
209
+ wrap: wrap$6
210
+ };
211
+
212
+ const getUtilityProcessPortData = event => {
213
+ const {
214
+ data,
215
+ ports
216
+ } = event;
217
+ if (ports.length === 0) {
218
+ return data;
219
+ }
220
+ return {
221
+ ...data,
222
+ params: [...ports, ...data.params]
223
+ };
224
+ };
225
+
226
+ const listen$2 = () => {
227
+ // @ts-ignore
228
+ const {
229
+ parentPort
230
+ } = process;
231
+ if (!parentPort) {
232
+ throw new Error('parent port must be defined');
233
+ }
234
+ return parentPort;
235
+ };
236
+ const signal$1 = parentPort => {
237
+ parentPort.postMessage('ready');
238
+ };
239
+ const wrap$5 = parentPort => {
240
+ return {
241
+ parentPort,
242
+ on(event, listener) {
243
+ if (event === 'message') {
244
+ const wrappedListener = event => {
245
+ const actualData = getUtilityProcessPortData(event);
246
+ listener(actualData);
247
+ };
248
+ this.parentPort.on(event, wrappedListener);
249
+ } else if (event === 'close') {
250
+ this.parentPort.on('close', listener);
251
+ } else {
252
+ throw new Error('unsupported event type');
253
+ }
254
+ },
255
+ off(event, listener) {
256
+ this.parentPort.off(event, listener);
257
+ },
258
+ send(message) {
259
+ this.parentPort.postMessage(message);
260
+ },
261
+ sendAndTransfer(message, transfer) {
262
+ this.parentPort.postMessage(message, transfer);
263
+ },
264
+ dispose() {
265
+ this.parentPort.close();
266
+ }
267
+ };
268
+ };
269
+
270
+ const IpcChildWithElectronUtilityProcess = {
271
+ __proto__: null,
272
+ listen: listen$2,
273
+ signal: signal$1,
274
+ wrap: wrap$5
275
+ };
276
+
277
+ const listen$1 = async () => {
278
+ if (!process.send) {
279
+ throw new Error('process.send must be defined');
280
+ }
281
+ return process;
282
+ };
283
+ const signal = process => {
284
+ process.send('ready');
285
+ };
286
+ const getActualData = (message, handle) => {
287
+ if (handle) {
288
+ return {
289
+ ...message,
290
+ params: [...message.params, handle]
291
+ };
292
+ }
293
+ return message;
294
+ };
295
+ const wrap$4 = process => {
296
+ return {
297
+ process,
298
+ on(event, listener) {
299
+ if (event === 'message') {
300
+ const wrappedListener = (event, handle) => {
301
+ const actualData = getActualData(event, handle);
302
+ listener(actualData);
303
+ };
304
+ this.process.on(event, wrappedListener);
305
+ } else if (event === 'close') {
306
+ this.process.on('close', listener);
307
+ } else {
308
+ throw new Error('unsupported event type');
309
+ }
310
+ },
311
+ off(event, listener) {
312
+ this.process.off(event, listener);
313
+ },
314
+ send(message) {
315
+ this.process.send(message);
316
+ },
317
+ dispose() {}
318
+ };
319
+ };
320
+
321
+ const IpcChildWithNodeForkedProcess = {
322
+ __proto__: null,
323
+ listen: listen$1,
324
+ signal,
325
+ wrap: wrap$4
326
+ };
327
+
328
+ const Open = 1;
329
+ const Close = 2;
330
+
331
+ const withResolvers = () => {
332
+ /**
333
+ * @type {any}
334
+ */
335
+ let _resolve;
336
+ /**
337
+ * @type {any}
338
+ */
339
+ let _reject;
340
+ const promise = new Promise((resolve, reject) => {
341
+ _resolve = resolve;
342
+ _reject = reject;
343
+ });
344
+ return {
345
+ resolve: _resolve,
346
+ reject: _reject,
347
+ promise
348
+ };
349
+ };
350
+
351
+ const getFirstEvent = (eventEmitter, eventMap) => {
352
+ const {
353
+ resolve,
354
+ promise
355
+ } = withResolvers();
356
+ const listenerMap = Object.create(null);
357
+ const cleanup = value => {
358
+ for (const event of Object.keys(eventMap)) {
359
+ eventEmitter.off(event, listenerMap[event]);
360
+ }
361
+ resolve(value);
362
+ };
363
+ for (const [event, type] of Object.entries(eventMap)) {
364
+ const listener = event => {
365
+ cleanup({
366
+ type,
367
+ event
368
+ });
369
+ };
370
+ eventEmitter.on(event, listener);
371
+ listenerMap[event] = listener;
372
+ }
373
+ return promise;
374
+ };
375
+
376
+ const getFirstWebSocketEvent = async webSocket => {
377
+ const {
378
+ WebSocket
379
+ } = await import('ws');
380
+ switch (webSocket.readyState) {
381
+ case WebSocket.OPEN:
382
+ return {
383
+ type: Open,
384
+ event: undefined
385
+ };
386
+ case WebSocket.CLOSED:
387
+ return {
388
+ type: Close,
389
+ event: undefined
390
+ };
391
+ }
392
+ // @ts-ignore
393
+ const {
394
+ type,
395
+ event
396
+ } = await getFirstEvent(webSocket, {
397
+ open: Open,
398
+ close: Close
399
+ });
400
+ return {
401
+ type,
402
+ event
403
+ };
404
+ };
405
+
406
+ const isWebSocketOpen = async webSocket => {
407
+ const {
408
+ WebSocket
409
+ } = await import('ws');
410
+ return webSocket.readyState === WebSocket.OPEN;
411
+ };
412
+
413
+ const serialize = message => {
414
+ return JSON.stringify(message);
415
+ };
416
+ const deserialize = message => {
417
+ return JSON.parse(message.toString());
418
+ };
419
+
420
+ const handleUpgrade = async (...args) => {
421
+ const module = await import('@lvce-editor/web-socket-server');
422
+ // @ts-ignore
423
+ return module.handleUpgrade(...args);
424
+ };
425
+
426
+ const listen = async ({
427
+ request,
428
+ handle
429
+ }) => {
430
+ if (!request) {
431
+ throw new IpcError('request must be defined');
432
+ }
433
+ if (!handle) {
434
+ throw new IpcError('handle must be defined');
435
+ }
436
+ const webSocket = await handleUpgrade(request, handle);
437
+ webSocket.pause();
438
+ if (!(await isWebSocketOpen(webSocket))) {
439
+ await getFirstWebSocketEvent(webSocket);
440
+ }
441
+ return webSocket;
442
+ };
443
+ const wrap$3 = webSocket => {
444
+ return {
445
+ webSocket,
446
+ /**
447
+ * @type {any}
448
+ */
449
+ wrappedListener: undefined,
450
+ on(event, listener) {
451
+ switch (event) {
452
+ case 'message':
453
+ const wrappedListener = message => {
454
+ const data = deserialize(message);
455
+ listener(data);
456
+ };
457
+ webSocket.on('message', wrappedListener);
458
+ break;
459
+ case 'close':
460
+ webSocket.on('close', listener);
461
+ break;
462
+ default:
463
+ throw new Error('unknown event listener type');
464
+ }
465
+ },
466
+ off(event, listener) {
467
+ this.webSocket.off(event, listener);
468
+ },
469
+ send(message) {
470
+ const stringifiedMessage = serialize(message);
471
+ this.webSocket.send(stringifiedMessage);
472
+ },
473
+ dispose() {
474
+ this.webSocket.close();
475
+ },
476
+ start() {
477
+ this.webSocket.resume();
478
+ }
479
+ };
480
+ };
481
+
482
+ const IpcChildWithWebSocket = {
483
+ __proto__: null,
484
+ listen,
485
+ wrap: wrap$3
486
+ };
487
+
488
+ const Exit = 1;
489
+ const Error$1 = 2;
490
+ const Message = 3;
491
+
492
+ /**
493
+ *
494
+ * @param {any} utilityProcess
495
+ * @returns
496
+ */
497
+ const getFirstUtilityProcessEvent = async utilityProcess => {
498
+ const {
499
+ resolve,
500
+ promise
501
+ } = withResolvers();
502
+ let stdout = '';
503
+ let stderr = '';
504
+ const cleanup = value => {
505
+ // @ts-ignore
506
+ utilityProcess.stderr.off('data', handleStdErrData);
507
+ // @ts-ignore
508
+ utilityProcess.stdout.off('data', handleStdoutData);
509
+ utilityProcess.off('message', handleMessage);
510
+ utilityProcess.off('exit', handleExit);
511
+ resolve(value);
512
+ };
513
+ const handleStdErrData = data => {
514
+ stderr += data;
515
+ };
516
+ const handleStdoutData = data => {
517
+ stdout += data;
518
+ };
519
+ const handleMessage = event => {
520
+ cleanup({
521
+ type: Message,
522
+ event,
523
+ stdout,
524
+ stderr
525
+ });
526
+ };
527
+ const handleExit = event => {
528
+ cleanup({
529
+ type: Exit,
530
+ event,
531
+ stdout,
532
+ stderr
533
+ });
534
+ };
535
+ // @ts-ignore
536
+ utilityProcess.stderr.on('data', handleStdErrData);
537
+ // @ts-ignore
538
+ utilityProcess.stdout.on('data', handleStdoutData);
539
+ utilityProcess.on('message', handleMessage);
540
+ utilityProcess.on('exit', handleExit);
541
+ // @ts-ignore
542
+ const {
543
+ type,
544
+ event
545
+ } = await promise;
546
+ return {
547
+ type,
548
+ event,
549
+ stdout,
550
+ stderr
551
+ };
552
+ };
553
+
554
+ const create$2 = async ({
555
+ path,
556
+ argv = [],
557
+ execArgv = [],
558
+ name
559
+ }) => {
560
+ string(path);
561
+ const actualArgv = ['--ipc-type=electron-utility-process', ...argv];
562
+ // @ts-ignore
563
+ const {
564
+ utilityProcess
565
+ } = await import('electron');
566
+ const childProcess = utilityProcess.fork(path, actualArgv, {
567
+ execArgv,
568
+ stdio: 'pipe',
569
+ serviceName: name
570
+ });
571
+ // @ts-ignore
572
+ childProcess.stdout.pipe(process.stdout);
573
+ const {
574
+ type,
575
+ event,
576
+ stdout,
577
+ stderr
578
+ } = await getFirstUtilityProcessEvent(childProcess);
579
+ if (type === Exit) {
580
+ throw new IpcError(`Utility process exited before ipc connection was established`, stdout, stderr);
581
+ }
582
+ // @ts-ignore
583
+ childProcess.stderr.pipe(process.stderr);
584
+ return childProcess;
585
+ };
586
+ const wrap$2 = process => {
587
+ return {
588
+ process,
589
+ on(event, listener) {
590
+ this.process.on(event, listener);
591
+ },
592
+ send(message) {
593
+ this.process.postMessage(message);
594
+ },
595
+ sendAndTransfer(message, transfer) {
596
+ array(transfer);
597
+ this.process.postMessage(message, transfer);
598
+ },
599
+ dispose() {
600
+ this.process.kill();
601
+ }
602
+ };
603
+ };
604
+
605
+ const IpcParentWithElectronUtilityProcess = {
606
+ __proto__: null,
607
+ create: create$2,
608
+ wrap: wrap$2
609
+ };
610
+
611
+ class ChildProcessError extends Error {
612
+ constructor(stderr) {
613
+ // @ts-ignore
614
+ const {
615
+ message,
616
+ code,
617
+ stack
618
+ } = getHelpfulChildProcessError('', stderr);
619
+ super(message || 'child process error');
620
+ this.name = 'ChildProcessError';
621
+ if (code) {
622
+ // @ts-ignore
623
+ this.code = code;
624
+ }
625
+ if (stack) {
626
+ const lines = splitLines(this.stack);
627
+ const [firstLine, ...stackLines] = lines;
628
+ const newStackLines = [firstLine, ...stack, ...stackLines];
629
+ const newStack = joinLines(newStackLines);
630
+ this.stack = newStack;
631
+ }
632
+ }
633
+ }
634
+
635
+ const getFirstNodeChildProcessEvent = async childProcess => {
636
+ // @ts-ignore
637
+ const {
638
+ type,
639
+ event,
640
+ stdout,
641
+ stderr
642
+ } = await new Promise((resolve, reject) => {
643
+ let stderr = '';
644
+ let stdout = '';
645
+ const cleanup = value => {
646
+ if (childProcess.stdout && childProcess.stderr) {
647
+ childProcess.stderr.off('data', handleStdErrData);
648
+ childProcess.stdout.off('data', handleStdoutData);
649
+ }
650
+ childProcess.off('message', handleMessage);
651
+ childProcess.off('exit', handleExit);
652
+ childProcess.off('error', handleError);
653
+ resolve(value);
654
+ };
655
+ const handleStdErrData = data => {
656
+ stderr += data;
657
+ };
658
+ const handleStdoutData = data => {
659
+ stdout += data;
660
+ };
661
+ const handleMessage = event => {
662
+ cleanup({
663
+ type: Message,
664
+ event,
665
+ stdout,
666
+ stderr
667
+ });
668
+ };
669
+ const handleExit = event => {
670
+ cleanup({
671
+ type: Exit,
672
+ event,
673
+ stdout,
674
+ stderr
675
+ });
676
+ };
677
+ const handleError = event => {
678
+ cleanup({
679
+ type: Error$1,
680
+ event,
681
+ stdout,
682
+ stderr
683
+ });
684
+ };
685
+ if (childProcess.stdout && childProcess.stderr) {
686
+ childProcess.stderr.on('data', handleStdErrData);
687
+ childProcess.stdout.on('data', handleStdoutData);
688
+ }
689
+ childProcess.on('message', handleMessage);
690
+ childProcess.on('exit', handleExit);
691
+ childProcess.on('error', handleError);
692
+ });
693
+ return {
694
+ type,
695
+ event,
696
+ stdout,
697
+ stderr
698
+ };
699
+ };
700
+
701
+ const create$1 = async ({
702
+ path,
703
+ argv = [],
704
+ env,
705
+ execArgv = [],
706
+ stdio = 'inherit',
707
+ name = 'child process'
708
+ }) => {
709
+ try {
710
+ string(path);
711
+ const actualArgv = ['--ipc-type=node-forked-process', ...argv];
712
+ const childProcess = fork(path, actualArgv, {
713
+ env,
714
+ execArgv,
715
+ stdio: 'pipe'
716
+ });
717
+ const {
718
+ type,
719
+ event,
720
+ stdout,
721
+ stderr
722
+ } = await getFirstNodeChildProcessEvent(childProcess);
723
+ if (type === Exit) {
724
+ throw new ChildProcessError(stderr);
725
+ }
726
+ if (type === Error$1) {
727
+ throw new Error(`child process had an error ${event}`);
728
+ }
729
+ if (stdio === 'inherit' && childProcess.stdout && childProcess.stderr) {
730
+ childProcess.stdout.pipe(process.stdout);
731
+ childProcess.stderr.pipe(process.stderr);
732
+ }
733
+ return childProcess;
734
+ } catch (error) {
735
+ throw new VError(error, `Failed to launch ${name}`);
736
+ }
737
+ };
738
+ const wrap$1 = childProcess => {
739
+ return {
740
+ childProcess,
741
+ on(event, listener) {
742
+ this.childProcess.on(event, listener);
743
+ },
744
+ off(event, listener) {
745
+ this.childProcess.off(event, listener);
746
+ },
747
+ send(message) {
748
+ this.childProcess.send(message);
749
+ },
750
+ sendAndTransfer(message, handle) {
751
+ this.childProcess.send(message, handle);
752
+ },
753
+ dispose() {
754
+ this.childProcess.kill();
755
+ },
756
+ pid: childProcess.pid
757
+ };
758
+ };
759
+
760
+ const IpcParentWithNodeForkedProcess = {
761
+ __proto__: null,
762
+ create: create$1,
763
+ wrap: wrap$1
764
+ };
765
+
766
+ const getFirstNodeWorkerEvent = worker => {
767
+ return getFirstEvent(worker, {
768
+ exit: Exit,
769
+ error: Error$1
770
+ });
771
+ };
772
+
773
+ const create = async ({
774
+ path,
775
+ argv = [],
776
+ env = process.env,
777
+ execArgv = []
778
+ }) => {
779
+ string(path);
780
+ const actualArgv = ['--ipc-type=node-worker', ...argv];
781
+ const actualEnv = {
782
+ ...env,
783
+ ELECTRON_RUN_AS_NODE: '1'
784
+ };
785
+ const worker = new Worker(path, {
786
+ argv: actualArgv,
787
+ env: actualEnv,
788
+ execArgv
789
+ });
790
+ // @ts-ignore
791
+ const {
792
+ type,
793
+ event
794
+ } = await getFirstNodeWorkerEvent(worker);
795
+ if (type === Exit) {
796
+ throw new IpcError(`Worker exited before ipc connection was established`);
797
+ }
798
+ if (type === Error$1) {
799
+ throw new IpcError(`Worker threw an error before ipc connection was established: ${event}`);
800
+ }
801
+ if (event !== 'ready') {
802
+ throw new IpcError('unexpected first message from worker');
803
+ }
804
+ return worker;
805
+ };
806
+ const wrap = worker => {
807
+ return {
808
+ worker,
809
+ on(event, listener) {
810
+ this.worker.on(event, listener);
811
+ },
812
+ send(message) {
813
+ this.worker.postMessage(message);
814
+ },
815
+ sendAndTransfer(message, transfer) {
816
+ array(transfer);
817
+ this.worker.postMessage(message, transfer);
818
+ },
819
+ dispose() {
820
+ this.worker.terminate();
821
+ }
822
+ };
823
+ };
824
+
825
+ const IpcParentWithNodeWorker = {
826
+ __proto__: null,
827
+ create,
828
+ wrap
829
+ };
830
+
831
+ export { IpcChildWithElectronMessagePort, IpcChildWithElectronUtilityProcess, IpcChildWithNodeForkedProcess, IpcChildWithWebSocket, IpcParentWithElectronUtilityProcess, IpcParentWithNodeForkedProcess, IpcParentWithNodeWorker };