@lvce-editor/pty-host 0.15.16 → 0.15.18

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 (50) hide show
  1. package/package.json +5 -2
  2. package/src/parts/Assert/Assert.js +7 -5
  3. package/src/parts/AssertionError/AssertionError.js +6 -0
  4. package/src/parts/CleanStack/CleanStack.js +93 -0
  5. package/src/parts/Command/Command.js +9 -0
  6. package/src/parts/CommandMap/CommandMap.js +13 -0
  7. package/src/parts/CommandNotFoundError/CommandNotFoundError.js +9 -0
  8. package/src/parts/CommandState/CommandState.js +17 -0
  9. package/src/parts/EncodingType/EncodingType.js +1 -0
  10. package/src/parts/ErrorCodes/ErrorCodes.js +18 -0
  11. package/src/parts/FirstWebSocketEventType/FirstWebSocketEventType.js +2 -0
  12. package/src/parts/GetErrorResponse/GetErrorResponse.js +56 -0
  13. package/src/parts/GetFirstWebSocketEvent/GetFirstWebSocketEvent.js +41 -0
  14. package/src/parts/GetResponse/GetResponse.js +15 -0
  15. package/src/parts/GetSuccessResponse/GetSuccessResponse.js +12 -0
  16. package/src/parts/HandleElectronMessagePort/HandleElectronMessagePort.js +14 -0
  17. package/src/parts/HandleIpc/HandleIpc.js +13 -0
  18. package/src/parts/HandleNodeMessagePort/HandleNodeMessagePort.js +12 -0
  19. package/src/parts/HandleWebSocket/HandleWebSocket.js +18 -0
  20. package/src/parts/IpcChild/IpcChild.js +3 -2
  21. package/src/parts/IpcChildModule/IpcChildModule.js +8 -0
  22. package/src/parts/IpcChildType/IpcChildType.js +7 -0
  23. package/src/parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js +39 -0
  24. package/src/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +48 -0
  25. package/src/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +20 -2
  26. package/src/parts/IpcChildWithNodeMessagePort/IpcChildWithNodeMessagePort.js +27 -0
  27. package/src/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +51 -0
  28. package/src/parts/IpcError/IpcError.js +6 -0
  29. package/src/parts/IsMessagePort/IsMessagePort.js +3 -0
  30. package/src/parts/IsMessagePortMain/IsMessagePortMain.js +3 -0
  31. package/src/parts/IsWebSocketOpen/IsWebSocketOpen.js +5 -0
  32. package/src/parts/JoinLines/JoinLines.js +3 -0
  33. package/src/parts/Json/Json.js +17 -0
  34. package/src/parts/JsonError/JsonError.js +64 -0
  35. package/src/parts/JsonParsingError/JsonParsingError.js +17 -0
  36. package/src/parts/JsonRpcErrorCode/JsonRpcErrorCode.js +2 -0
  37. package/src/parts/JsonRpcVersion/JsonRpcVersion.js +1 -0
  38. package/src/parts/Logger/Logger.js +50 -0
  39. package/src/parts/Main/Main.js +11 -0
  40. package/src/parts/NodePty/NodePty.js +60 -0
  41. package/src/parts/PrettyError/PrettyError.js +139 -0
  42. package/src/parts/PrintPrettyError/PrintPrettyError.js +5 -0
  43. package/src/parts/Pty/Pty.js +1 -48
  44. package/src/parts/PtyController/PtyController.js +18 -9
  45. package/src/parts/RequiresSocket/RequiresSocket.js +5 -0
  46. package/src/parts/SplitLines/SplitLines.js +3 -0
  47. package/src/parts/WebSocketServer/WebSocketServer.ipc.js +7 -0
  48. package/src/parts/WebSocketServer/WebSocketServer.js +24 -0
  49. package/src/ptyHostMain.cjs +1 -0
  50. package/src/ptyHostMain.js +2 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/pty-host",
3
- "version": "0.15.16",
3
+ "version": "0.15.18",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -16,8 +16,11 @@
16
16
  "node": ">=16"
17
17
  },
18
18
  "dependencies": {
19
+ "@babel/code-frame": "^7.21.4",
19
20
  "debug": "^4.3.4",
20
- "verror": "^1.10.1"
21
+ "lines-and-columns": "^2.0.3",
22
+ "verror": "^1.10.1",
23
+ "ws": "^8.13.0"
21
24
  },
22
25
  "optionalDependencies": {
23
26
  "node-pty": "^0.11.0-beta27"
@@ -1,3 +1,5 @@
1
+ import { AssertionError } from '../AssertionError/AssertionError.js'
2
+
1
3
  const getType = (value) => {
2
4
  switch (typeof value) {
3
5
  case 'number':
@@ -24,34 +26,34 @@ const getType = (value) => {
24
26
  export const object = (value) => {
25
27
  const type = getType(value)
26
28
  if (type !== 'object') {
27
- throw new Error('expected value to be of type object')
29
+ throw new AssertionError('expected value to be of type object')
28
30
  }
29
31
  }
30
32
 
31
33
  export const number = (value) => {
32
34
  const type = getType(value)
33
35
  if (type !== 'number') {
34
- throw new Error('expected value to be of type number')
36
+ throw new AssertionError('expected value to be of type number')
35
37
  }
36
38
  }
37
39
 
38
40
  export const array = (value) => {
39
41
  const type = getType(value)
40
42
  if (type !== 'array') {
41
- throw new Error('expected value to be of type array')
43
+ throw new AssertionError('expected value to be of type array')
42
44
  }
43
45
  }
44
46
 
45
47
  export const string = (value) => {
46
48
  const type = getType(value)
47
49
  if (type !== 'string') {
48
- throw new Error('expected value to be of type string')
50
+ throw new AssertionError('expected value to be of type string')
49
51
  }
50
52
  }
51
53
 
52
54
  export const boolean = (value) => {
53
55
  const type = getType(value)
54
56
  if (type !== 'boolean') {
55
- throw new Error('expected value to be of type boolean')
57
+ throw new AssertionError('expected value to be of type boolean')
56
58
  }
57
59
  }
@@ -0,0 +1,6 @@
1
+ export class AssertionError extends Error {
2
+ constructor(message) {
3
+ super(message)
4
+ this.name = 'AssertionError'
5
+ }
6
+ }
@@ -0,0 +1,93 @@
1
+ import * as SplitLines from '../SplitLines/SplitLines.js'
2
+
3
+ const RE_AT = /^\s+at/
4
+ const RE_AT_PROMISE_INDEX = /^\s*at async Promise.all \(index \d+\)$/
5
+ const RE_OBJECT_AS = /^\s*at (async )?Object\.\w+ \[as ([\w\.]+)\]/
6
+ const RE_GET_RESPONSE = /^\s*at async getResponse/
7
+ const RE_WEBSOCKET_HANDLE_MESSAGE = /^\s*at async WebSocket.handleMessage/
8
+ const RE_EXECUTE_COMMAND_ASYNC = /^\s*at executeCommandAsync/
9
+ const RE_HANDLE_OTHER_MESSAGES_FROM_MESSAGE_PORT = /^\s*at async MessagePort\.handleOtherMessagesFromMessagePort/
10
+
11
+ const isInternalLine = (line) => {
12
+ return line.includes('node:') || RE_AT_PROMISE_INDEX.test(line) || line.includes('node_modules/ws')
13
+ }
14
+
15
+ const isRelevantLine = (line) => {
16
+ return !isInternalLine(line)
17
+ }
18
+
19
+ const isApplicationUsefulLine = (line, index) => {
20
+ if (index === 0) {
21
+ return true
22
+ }
23
+ if (RE_GET_RESPONSE.test(line)) {
24
+ return false
25
+ }
26
+ if (RE_WEBSOCKET_HANDLE_MESSAGE.test(line)) {
27
+ return false
28
+ }
29
+ if (RE_EXECUTE_COMMAND_ASYNC.test(line)) {
30
+ return false
31
+ }
32
+ if (RE_HANDLE_OTHER_MESSAGES_FROM_MESSAGE_PORT.test(line)) {
33
+ return false
34
+ }
35
+ return true
36
+ }
37
+
38
+ const isNormalStackLine = (line) => {
39
+ return RE_AT.test(line) && !RE_AT_PROMISE_INDEX.test(line)
40
+ }
41
+
42
+ const cleanLine = (line) => {
43
+ if (line.startsWith(' at exports.')) {
44
+ return ' at ' + line.slice(' at exports.'.length)
45
+ }
46
+ if (line.startsWith(' at async exports.')) {
47
+ return ' at async ' + line.slice(' at async exports.'.length)
48
+ }
49
+ if (line.startsWith(' at async Module.')) {
50
+ return ' at async ' + line.slice(' at async Module.'.length)
51
+ }
52
+ if (line.startsWith(' at Module.')) {
53
+ return ' at ' + line.slice(' at Module.'.length)
54
+ }
55
+ const objectMatch = line.match(RE_OBJECT_AS)
56
+ if (objectMatch) {
57
+ const rest = line.slice(objectMatch[0].length)
58
+ if (objectMatch[1]) {
59
+ return ' at ' + objectMatch[1] + objectMatch[2] + rest
60
+ }
61
+ return ' at ' + objectMatch[2] + rest
62
+ }
63
+ return line
64
+ }
65
+
66
+ const getDetails = (lines) => {
67
+ const index = lines.findIndex(isNormalStackLine)
68
+ return {
69
+ custom: lines.slice(0, index),
70
+ actualStack: lines.slice(index).map(cleanLine),
71
+ }
72
+ }
73
+
74
+ const RE_PATH_1 = /^\/(.*)(\d+)$/
75
+
76
+ const mergeCustom = (custom, relevantStack) => {
77
+ if (custom.length === 0) {
78
+ return relevantStack
79
+ }
80
+ const firstLine = custom[0]
81
+ if (RE_PATH_1.test(firstLine)) {
82
+ return [` at ${firstLine}`, ...relevantStack]
83
+ }
84
+ return relevantStack
85
+ }
86
+
87
+ export const cleanStack = (stack) => {
88
+ const lines = SplitLines.splitLines(stack)
89
+ const { custom, actualStack } = getDetails(lines)
90
+ const relevantStack = actualStack.filter(isRelevantLine).filter(isApplicationUsefulLine)
91
+ const merged = mergeCustom(custom, relevantStack)
92
+ return merged
93
+ }
@@ -0,0 +1,9 @@
1
+ import * as CommandState from '../CommandState/CommandState.js'
2
+
3
+ export const execute = (command, ...args) => {
4
+ const fn = CommandState.getCommand(command)
5
+ if (!fn) {
6
+ throw new Error(`Command not found ${command}`)
7
+ }
8
+ return fn(...args)
9
+ }
@@ -0,0 +1,13 @@
1
+ import * as HandleElectronMessagePort from '../HandleElectronMessagePort/HandleElectronMessagePort.js'
2
+ import * as HandleNodeMessagePort from '../HandleNodeMessagePort/HandleNodeMessagePort.js'
3
+ import * as HandleWebSocket from '../HandleWebSocket/HandleWebSocket.js'
4
+ import * as PtyController from '../PtyController/PtyController.js'
5
+
6
+ export const commandMap = {
7
+ 'HandleElectronMessagePort.handleElectronMessagePort': HandleElectronMessagePort.handleElectronMessagePort,
8
+ 'HandleNodeMessagePort.handleNodeMessagePort': HandleNodeMessagePort.handleNodeMessagePort,
9
+ 'HandleWebSocket.handleWebSocket': HandleWebSocket.handleWebSocket,
10
+ 'Terminal.create': PtyController.create,
11
+ 'Terminal.write': PtyController.write,
12
+ 'Terminal.dispose': PtyController.dispose,
13
+ }
@@ -0,0 +1,9 @@
1
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
2
+
3
+ export class CommandNotFoundError extends Error {
4
+ constructor(id) {
5
+ super(`command ${id} not found`)
6
+ this.name = 'CommandNotFoundError'
7
+ this.code = ErrorCodes.E_COMMAND_NOT_FOUND
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ export const state = {
2
+ commands: Object.create(null),
3
+ }
4
+
5
+ export const registerCommand = (key, fn) => {
6
+ state.commands[key] = fn
7
+ }
8
+
9
+ export const registerCommands = (commandMap) => {
10
+ for (const [key, value] of Object.entries(commandMap)) {
11
+ registerCommand(key, value)
12
+ }
13
+ }
14
+
15
+ export const getCommand = (key) => {
16
+ return state.commands[key]
17
+ }
@@ -0,0 +1 @@
1
+ export const Utf8 = 'utf8'
@@ -0,0 +1,18 @@
1
+ export const E_COLOR_THEME_NOT_FOUND = 'E_COLOR_THEME_NOT_FOUND'
2
+ export const E_COMMAND_NOT_FOUND = 'E_COMMAND_NOT_FOUND'
3
+ export const E_ICON_THEME_NOT_FOUND = 'E_ICON_THEME_NOT_FOUND'
4
+ export const E_INCOMPATIBLE_NATIVE_MODULE = 'E_INCOMPATIBLE_NATIVE_MODULE'
5
+ export const E_MANIFEST_NOT_FOUND = 'E_MANIFEST_NOT_FOUND'
6
+ export const E_MODULES_NOT_SUPPORTED_IN_ELECTRON = 'E_MODULES_NOT_SUPPORTED_IN_ELECTRON'
7
+ export const EACCES = 'EACCES'
8
+ export const ECONNRESET = 'ECONNRESET'
9
+ export const EEXIST = 'EEXIST'
10
+ export const EISDIR = 'EISDIR'
11
+ export const ELOOP = 'ELOOP'
12
+ export const ENOENT = 'ENOENT'
13
+ export const ENOTDIR = 'ENOTDIR'
14
+ export const EPERM = 'EPERM'
15
+ export const EPIPE = 'EPIPE'
16
+ export const ERR_IPC_CHANNEL_CLOSED = 'ERR_IPC_CHANNEL_CLOSED'
17
+ export const ERR_MODULE_NOT_FOUND = 'ERR_MODULE_NOT_FOUND'
18
+ export const EXDEV = 'EXDEV'
@@ -0,0 +1,2 @@
1
+ export const Open = 1
2
+ export const Close = 2
@@ -0,0 +1,56 @@
1
+ import { CommandNotFoundError } from '../CommandNotFoundError/CommandNotFoundError.js'
2
+ import * as ErrorCodes from '../ErrorCodes/ErrorCodes.js'
3
+ import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
4
+ import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
5
+ import * as PrettyError from '../PrettyError/PrettyError.js'
6
+ import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
7
+
8
+ const shouldLogError = (error) => {
9
+ if (error && error.code === ErrorCodes.ENOENT) {
10
+ return false
11
+ }
12
+ return true
13
+ }
14
+
15
+ export const getErrorResponse = (message, error) => {
16
+ if (error && error instanceof CommandNotFoundError) {
17
+ return {
18
+ jsonrpc: JsonRpcVersion.Two,
19
+ id: message.id,
20
+ error: {
21
+ code: JsonRpcErrorCode.MethodNotFound,
22
+ message: error.message,
23
+ data: error.stack,
24
+ },
25
+ }
26
+ }
27
+ if (!shouldLogError(error)) {
28
+ return {
29
+ jsonrpc: JsonRpcVersion.Two,
30
+ id: message.id,
31
+ error: {
32
+ code: JsonRpcErrorCode.Custom,
33
+ message: `${error}`,
34
+ data: {
35
+ code: error.code,
36
+ },
37
+ },
38
+ }
39
+ }
40
+ const prettyError = PrettyError.prepare(error)
41
+ PrintPrettyError.printPrettyError(prettyError, `[terminal-process] `)
42
+ return {
43
+ jsonrpc: JsonRpcVersion.Two,
44
+ id: message.id,
45
+ error: {
46
+ code: JsonRpcErrorCode.Custom,
47
+ message: prettyError.message,
48
+ data: {
49
+ stack: prettyError.stack,
50
+ codeFrame: prettyError.codeFrame,
51
+ type: prettyError.type,
52
+ code: prettyError.code,
53
+ },
54
+ },
55
+ }
56
+ }
@@ -0,0 +1,41 @@
1
+ import * as FirstWebSocketEventType from '../FirstWebSocketEventType/FirstWebSocketEventType.js'
2
+ import { WebSocket } from 'ws'
3
+
4
+ export const getFirstWebSocketEvent = async (webSocket) => {
5
+ switch (webSocket.readyState) {
6
+ case WebSocket.OPEN:
7
+ return {
8
+ type: FirstWebSocketEventType.Open,
9
+ event: undefined,
10
+ }
11
+ case WebSocket.CLOSED:
12
+ return {
13
+ type: FirstWebSocketEventType.Close,
14
+ event: undefined,
15
+ }
16
+ default:
17
+ break
18
+ }
19
+ const { type, event } = await new Promise((resolve) => {
20
+ const cleanup = (value) => {
21
+ webSocket.off('open', handleOpen)
22
+ webSocket.off('close', handleClose)
23
+ resolve(value)
24
+ }
25
+ const handleOpen = (event) => {
26
+ cleanup({
27
+ type: FirstWebSocketEventType.Open,
28
+ event,
29
+ })
30
+ }
31
+ const handleClose = (event) => {
32
+ cleanup({
33
+ type: FirstWebSocketEventType.Close,
34
+ event,
35
+ })
36
+ }
37
+ webSocket.on('open', handleOpen)
38
+ webSocket.on('close', handleClose)
39
+ })
40
+ return { type, event }
41
+ }
@@ -0,0 +1,15 @@
1
+ import * as Command from '../Command/Command.js'
2
+ import * as GetErrorResponse from '../GetErrorResponse/GetErrorResponse.js'
3
+ import * as GetSuccessResponse from '../GetSuccessResponse/GetSuccessResponse.js'
4
+ import * as RequiresSocket from '../RequiresSocket/RequiresSocket.js'
5
+
6
+ export const getResponse = async (message, handle) => {
7
+ try {
8
+ const result = RequiresSocket.requiresSocket(message.method)
9
+ ? await Command.execute(message.method, ...message.params, handle)
10
+ : await Command.execute(message.method, ...message.params)
11
+ return GetSuccessResponse.getSuccessResponse(message, result)
12
+ } catch (error) {
13
+ return GetErrorResponse.getErrorResponse(message, error)
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
2
+
3
+ export const getSuccessResponse = (message, result) => {
4
+ if (!message.id) {
5
+ return undefined
6
+ }
7
+ return {
8
+ jsonrpc: JsonRpcVersion.Two,
9
+ id: message.id,
10
+ result: result ?? null,
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
3
+ import * as IpcChild from '../IpcChild/IpcChild.js'
4
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
5
+
6
+ export const handleElectronMessagePort = async (messagePort) => {
7
+ Assert.object(messagePort)
8
+ const ipc = await IpcChild.listen({
9
+ method: IpcChildType.ElectronMessagePort,
10
+ messagePort,
11
+ })
12
+ HandleIpc.handleIpc(ipc)
13
+ messagePort.start()
14
+ }
@@ -0,0 +1,13 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as GetResponse from '../GetResponse/GetResponse.js'
3
+
4
+ export const handleIpc = (ipc) => {
5
+ Assert.object(ipc)
6
+ const handleMessage = async (message) => {
7
+ const response = await GetResponse.getResponse(message, ipc)
8
+ if (response) {
9
+ ipc.send(response)
10
+ }
11
+ }
12
+ ipc.on('message', handleMessage)
13
+ }
@@ -0,0 +1,12 @@
1
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
2
+ import * as IpcChild from '../IpcChild/IpcChild.js'
3
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
4
+
5
+ export const handleNodeMessagePort = async (messagePort) => {
6
+ const ipc = await IpcChild.listen({
7
+ method: IpcChildType.NodeMessagePort,
8
+ messagePort,
9
+ })
10
+ HandleIpc.handleIpc(ipc)
11
+ messagePort.start()
12
+ }
@@ -0,0 +1,18 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
3
+ import * as IpcChild from '../IpcChild/IpcChild.js'
4
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
5
+ import * as WebSocketServer from '../WebSocketServer/WebSocketServer.js'
6
+
7
+ export const handleWebSocket = async (request, handle) => {
8
+ Assert.object(request)
9
+ Assert.object(handle)
10
+ const webSocket = await WebSocketServer.handleUpgrade(request, handle)
11
+ webSocket.pause()
12
+ const ipc = await IpcChild.listen({
13
+ method: IpcChildType.WebSocket,
14
+ webSocket,
15
+ })
16
+ HandleIpc.handleIpc(ipc)
17
+ webSocket.resume()
18
+ }
@@ -1,8 +1,9 @@
1
1
  import * as IpcChildModule from '../IpcChildModule/IpcChildModule.js'
2
2
 
3
- export const listen = async ({ method }) => {
3
+ export const listen = async ({ method, ...params }) => {
4
4
  const module = await IpcChildModule.getModule(method)
5
- const rawIpc = await module.listen()
5
+ // @ts-ignore
6
+ const rawIpc = await module.listen(params)
6
7
  const ipc = module.wrap(rawIpc)
7
8
  return ipc
8
9
  }
@@ -6,6 +6,14 @@ export const getModule = (method) => {
6
6
  return import('../IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js')
7
7
  case IpcChildType.NodeWorker:
8
8
  return import('../IpcChildWithNodeWorker/IpcChildWithNodeWorker.js')
9
+ case IpcChildType.WebSocket:
10
+ return import('../IpcChildWithWebSocket/IpcChildWithWebSocket.js')
11
+ case IpcChildType.ElectronUtilityProcess:
12
+ return import('../IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js')
13
+ case IpcChildType.ElectronMessagePort:
14
+ return import('../IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js')
15
+ case IpcChildType.NodeMessagePort:
16
+ return import('../IpcChildWithNodeMessagePort/IpcChildWithNodeMessagePort.js')
9
17
  default:
10
18
  throw new Error('unexpected ipc type')
11
19
  }
@@ -1,5 +1,9 @@
1
1
  export const NodeWorker = 1
2
2
  export const NodeForkedProcess = 2
3
+ export const WebSocket = 3
4
+ export const ElectronUtilityProcess = 4
5
+ export const ElectronMessagePort = 5
6
+ export const NodeMessagePort = 6
3
7
 
4
8
  export const Auto = () => {
5
9
  const { argv } = process
@@ -9,5 +13,8 @@ export const Auto = () => {
9
13
  if (argv.includes('--ipc-type=node-forked-process')) {
10
14
  return NodeForkedProcess
11
15
  }
16
+ if (argv.includes('--ipc-type=electron-utility-process')) {
17
+ return ElectronUtilityProcess
18
+ }
12
19
  throw new Error(`[pty-host] unknown ipc type`)
13
20
  }
@@ -0,0 +1,39 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+ import * as IsMessagePortMain from '../IsMessagePortMain/IsMessagePortMain.js'
3
+
4
+ export const listen = ({ messagePort }) => {
5
+ if (!IsMessagePortMain.isMessagePortMain(messagePort)) {
6
+ throw new IpcError('port must be of type MessagePortMain')
7
+ }
8
+ return messagePort
9
+ }
10
+
11
+ const getActualData = (event) => {
12
+ return event.data
13
+ }
14
+
15
+ export const wrap = (messagePort) => {
16
+ return {
17
+ messagePort,
18
+ on(event, listener) {
19
+ if (event === 'message') {
20
+ const wrappedListener = (event) => {
21
+ const actualData = getActualData(event)
22
+ listener(actualData)
23
+ }
24
+ this.messagePort.on(event, wrappedListener)
25
+ } else {
26
+ throw new Error('unsupported event type')
27
+ }
28
+ },
29
+ off(event, listener) {
30
+ this.messagePort.off(event, listener)
31
+ },
32
+ send(message) {
33
+ this.messagePort.postMessage(message)
34
+ },
35
+ dispose() {
36
+ this.messagePort.close()
37
+ },
38
+ }
39
+ }
@@ -0,0 +1,48 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+
3
+ export const listen = () => {
4
+ // @ts-ignore
5
+ const parentPort = process.parentPort
6
+ if (!parentPort) {
7
+ throw new IpcError('parent port must be defined')
8
+ }
9
+ parentPort.postMessage('ready')
10
+ return parentPort
11
+ }
12
+
13
+ const getActualData = (event) => {
14
+ const { data, ports } = event
15
+ if (ports.length === 0) {
16
+ return data
17
+ }
18
+ return {
19
+ ...data,
20
+ params: [...data.params, ...ports],
21
+ }
22
+ }
23
+
24
+ export const wrap = (parentPort) => {
25
+ return {
26
+ parentPort,
27
+ on(event, listener) {
28
+ if (event === 'message') {
29
+ const wrappedListener = (event) => {
30
+ const actualData = getActualData(event)
31
+ listener(actualData)
32
+ }
33
+ this.parentPort.on(event, wrappedListener)
34
+ } else {
35
+ throw new Error('unsupported event type')
36
+ }
37
+ },
38
+ off(event, listener) {
39
+ this.parentPort.off(event, listener)
40
+ },
41
+ send(message) {
42
+ this.parentPort.postMessage(message)
43
+ },
44
+ dispose() {
45
+ this.parentPort.close()
46
+ },
47
+ }
48
+ }
@@ -1,16 +1,34 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+
1
3
  export const listen = async () => {
2
4
  if (!process.send) {
3
- throw new Error('process ipc is not available')
5
+ throw new IpcError('process ipc is not available')
4
6
  }
5
7
  process.send('ready')
6
8
  return process
7
9
  }
8
10
 
11
+ const getActualData = (message, handle) => {
12
+ if (handle) {
13
+ return {
14
+ ...message,
15
+ params: [...message.params, handle],
16
+ }
17
+ }
18
+ return message
19
+ }
20
+
9
21
  export const wrap = (process) => {
10
22
  return {
11
23
  process,
12
24
  on(event, listener) {
13
- this.process.on(event, listener)
25
+ if (event === 'message') {
26
+ const wrappedListener = (message, handle) => {
27
+ const actualData = getActualData(message, handle)
28
+ listener(actualData)
29
+ }
30
+ this.process.on(event, wrappedListener)
31
+ }
14
32
  },
15
33
  off(event, listener) {
16
34
  this.process.off(event, listener)
@@ -0,0 +1,27 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+ import * as IsMessagePort from '../IsMessagePort/IsMessagePort.js'
3
+
4
+ export const listen = async ({ messagePort }) => {
5
+ if (!IsMessagePort.isMessagePort(messagePort)) {
6
+ throw new IpcError(`port must be of type MessagePort`)
7
+ }
8
+ return messagePort
9
+ }
10
+
11
+ export const wrap = (port) => {
12
+ return {
13
+ port,
14
+ on(event, listener) {
15
+ this.port.on(event, listener)
16
+ },
17
+ off(event, listener) {
18
+ this.port.off(event, listener)
19
+ },
20
+ send(message) {
21
+ this.port.postMessage(message)
22
+ },
23
+ dispose() {
24
+ this.port.close()
25
+ },
26
+ }
27
+ }