@lvce-editor/extension-host-helper-process 0.15.21 → 0.15.22

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 (39) hide show
  1. package/package.json +1 -1
  2. package/src/extensionHostHelperProcessMain.js +2 -41
  3. package/src/parts/Ajax/Ajax.js +3 -0
  4. package/src/parts/Callback/Callback.js +42 -0
  5. package/src/parts/Command/Command.js +6 -78
  6. package/src/parts/CommandMap/CommandMap.js +11 -0
  7. package/src/parts/CommandNotFoundError/CommandNotFoundError.js +9 -0
  8. package/src/parts/CommandState/CommandState.js +34 -0
  9. package/src/parts/ErrorCodes/ErrorCodes.js +18 -0
  10. package/src/parts/Exec/Exec.js +3 -0
  11. package/src/parts/FirstWebSocketEventType/FirstWebSocketEventType.js +2 -0
  12. package/src/parts/GetFirstWebSocketEvent/GetFirstWebSocketEvent.js +41 -0
  13. package/src/parts/HandleElectronMessagePort/HandleElectronMessagePort.js +14 -0
  14. package/src/parts/HandleIpc/HandleIpc.js +12 -0
  15. package/src/parts/HandleJsonRpcMessage/HandleJsonRpcMessage.js +10 -0
  16. package/src/parts/HandleWebSocket/HandleWebSocket.js +18 -0
  17. package/src/parts/Id/Id.js +7 -0
  18. package/src/parts/IpcChildModule/IpcChildModule.js +2 -0
  19. package/src/parts/IpcChildType/IpcChildType.js +3 -0
  20. package/src/parts/IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js +35 -11
  21. package/src/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +3 -1
  22. package/src/parts/IpcChildWithElectronUtilityProcessMessagePort/IpcChildWithElectronUtilityProcessMessagePort.js +1 -0
  23. package/src/parts/IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js +36 -0
  24. package/src/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +28 -21
  25. package/src/parts/IpcError/IpcError.js +6 -0
  26. package/src/parts/IsMessagePort/IsMessagePort.js +3 -0
  27. package/src/parts/IsMessagePortMain/IsMessagePortMain.js +3 -0
  28. package/src/parts/IsSocket/IsSocket.js +5 -0
  29. package/src/parts/IsWebSocket/IsWebSocket.js +5 -0
  30. package/src/parts/IsWebSocketOpen/IsWebSocketOpen.js +5 -0
  31. package/src/parts/LoadFile/LoadFile.js +21 -0
  32. package/src/parts/Main/Main.js +11 -0
  33. package/src/parts/WebSocketSerialization/WebSocketSerialization.js +7 -0
  34. package/src/parts/WebSocketServer/WebSocketServer.ipc.js +7 -0
  35. package/src/parts/WebSocketServer/WebSocketServer.js +21 -0
  36. package/src/extensionHostHelperProcessMain.cjs +0 -5
  37. package/src/parts/IpcChildWithMessagePort/IpcChildWithMessagePort.js +0 -9
  38. package/src/parts/IpcChildWithParent/IpcChildWithParent.js +0 -21
  39. package/src/parts/Rpc/Rpc.js +0 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/extension-host-helper-process",
3
- "version": "0.15.21",
3
+ "version": "0.15.22",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,42 +1,3 @@
1
- import * as GetErrorResponse from './parts/GetErrorResponse/GetErrorResponse.js'
2
- import * as GetSuccessResponse from './parts/GetSuccessResponse/GetSuccessResponse.js'
3
- import * as ImportScript from './parts/ImportScript/ImportScript.js'
4
- import * as IpcChild from './parts/IpcChild/IpcChild.js'
5
- import * as IpcChildType from './parts/IpcChildType/IpcChildType.js'
6
- import * as Rpc from './parts/Rpc/Rpc.js'
7
- import * as GetResponse from './parts/GetResponse/GetResponse.js'
1
+ import * as Main from './parts/Main/Main.js'
8
2
 
9
- const waitForFirstMessage = async (ipc) => {
10
- const { message } = await new Promise((resolve) => {
11
- const cleanup = (value) => {
12
- ipc.off('message', handleMessage)
13
- resolve(value)
14
- }
15
- const handleMessage = (message) => {
16
- cleanup({ message })
17
- }
18
- ipc.on('message', handleMessage)
19
- })
20
- return message
21
- }
22
-
23
- const main = async () => {
24
- const ipc = await IpcChild.listen({ method: IpcChildType.Auto() })
25
- const firstMessage = await waitForFirstMessage(ipc)
26
- let module
27
- try {
28
- module = await ImportScript.importScript(firstMessage.params[0])
29
- if (!module || !module.execute) {
30
- throw new Error(`missing export const execute function`)
31
- }
32
- const response = GetSuccessResponse.getSuccessResponse(firstMessage, null)
33
- ipc.send(response)
34
- } catch (error) {
35
- const response = await GetErrorResponse.getErrorResponse(firstMessage, error)
36
- ipc.send(response)
37
- return
38
- }
39
- Rpc.listen(ipc, module.execute)
40
- }
41
-
42
- main()
3
+ Main.main()
@@ -1,5 +1,8 @@
1
1
  import got from 'got'
2
2
 
3
+ /**
4
+ * @deprecated use node api directly
5
+ */
3
6
  export const getJson = async (url) => {
4
7
  const json = await got(url, {
5
8
  retry: {
@@ -0,0 +1,42 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as Id from '../Id/Id.js'
3
+
4
+ export const state = {
5
+ callbacks: Object.create(null),
6
+ }
7
+
8
+ export const registerPromise = () => {
9
+ const id = Id.create()
10
+ const promise = new Promise((resolve, reject) => {
11
+ state.callbacks[id] = {
12
+ resolve,
13
+ reject,
14
+ }
15
+ })
16
+ return { id, promise }
17
+ }
18
+
19
+ export const unregister = (id) => {
20
+ delete state.callbacks[id]
21
+ }
22
+
23
+ export const resolve = (id, args) => {
24
+ Assert.number(id)
25
+ if (!(id in state.callbacks)) {
26
+ console.log(args)
27
+ console.warn(`callback ${id} may already be disposed`)
28
+ return
29
+ }
30
+ state.callbacks[id].resolve(args)
31
+ delete state.callbacks[id]
32
+ }
33
+
34
+ export const reject = (id, error) => {
35
+ Assert.number(id)
36
+ if (!(id in state.callbacks)) {
37
+ console.warn(`callback ${id} may already be disposed`)
38
+ return
39
+ }
40
+ state.callbacks[id].reject(error)
41
+ delete state.callbacks[id]
42
+ }
@@ -1,82 +1,10 @@
1
- import * as Module from '../Module/Module.js'
2
- import * as ModuleMap from '../ModuleMap/ModuleMap.js'
3
-
4
- const commands = Object.create(null)
5
- const pendingModules = Object.create(null)
6
-
7
- const initializeModule = (module) => {
8
- if (module.Commands) {
9
- for (const [key, value] of Object.entries(module.Commands)) {
10
- if (module.name) {
11
- const actualKey = `${module.name}.${key}`
12
- register(actualKey, value)
13
- } else {
14
- register(key, value)
15
- }
16
- }
17
- return
18
- }
19
- throw new Error(`module ${module.name} is missing commands`)
20
- }
21
-
22
- const getOrLoadModule = (moduleId) => {
23
- if (!pendingModules[moduleId]) {
24
- const importPromise = Module.load(moduleId)
25
- pendingModules[moduleId] = importPromise
26
- .then(initializeModule)
27
- .catch((error) => {
28
- console.error(error)
29
- })
30
- }
31
- return pendingModules[moduleId]
32
- }
33
-
34
- const loadCommand = (command) => getOrLoadModule(ModuleMap.getModuleId(command))
35
-
36
- export const register = (commandId, listener) => {
37
- commands[commandId] = listener
38
- }
39
-
40
- export const invoke = async (command, ...args) => {
41
- if (!(command in commands)) {
42
- await loadCommand(command)
43
- if (!(command in commands)) {
44
- console.warn(
45
- `[extension host helper process] Unknown command "${command}"`
46
- )
47
- throw new Error(`Command ${command} not found`)
48
- }
49
- }
50
- if (typeof commands[command] !== 'function') {
51
- throw new TypeError(`Command ${command} is not a function`)
52
- }
53
- return commands[command](...args)
54
- }
1
+ import { CommandNotFoundError } from '../CommandNotFoundError/CommandNotFoundError.js'
2
+ import * as CommandState from '../CommandState/CommandState.js'
55
3
 
56
4
  export const execute = (command, ...args) => {
57
- if (command in commands) {
58
- return commands[command](...args)
59
- } else {
60
- return (
61
- loadCommand(command)
62
- // TODO can skip then block in prod (only to prevent endless loop in dev)
63
- .then(() => {
64
- if (!(command in commands)) {
65
- console.warn(`Unknown command "${command}"`)
66
- return
67
- }
68
- try {
69
- execute(command, ...args)
70
- } catch (error) {
71
- console.error(
72
- '[extension host helper process] command failed to execute'
73
- )
74
- console.error(error)
75
- }
76
- })
77
- .catch((error) => {
78
- console.error(error)
79
- })
80
- )
5
+ const fn = CommandState.getCommand(command)
6
+ if (!fn) {
7
+ throw new CommandNotFoundError(command)
81
8
  }
9
+ return fn(...args)
82
10
  }
@@ -0,0 +1,11 @@
1
+ import * as Ajax from '../Ajax/Ajax.js'
2
+ import * as Exec from '../Exec/Exec.js'
3
+ import * as HandleWebSocket from '../HandleWebSocket/HandleWebSocket.js'
4
+ import * as LoadFile from '../LoadFile/LoadFile.js'
5
+
6
+ export const commandMap = {
7
+ 'Exec.exec': Exec.exec,
8
+ 'Ajax.getJson': Ajax.getJson,
9
+ 'HandleWebSocket.handleWebSocket': HandleWebSocket.handleWebSocket,
10
+ 'LoadFile.loadFile': LoadFile.loadFile,
11
+ }
@@ -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,34 @@
1
+ export const state = {
2
+ commands: Object.create(null),
3
+ /**
4
+ * @type {any}
5
+ */
6
+ execute: undefined,
7
+ }
8
+
9
+ export const registerCommand = (key, fn) => {
10
+ state.commands[key] = fn
11
+ }
12
+
13
+ export const registerCommands = (commandMap) => {
14
+ for (const [key, value] of Object.entries(commandMap)) {
15
+ registerCommand(key, value)
16
+ }
17
+ }
18
+
19
+ export const getCommand = (key) => {
20
+ const { commands, execute } = state
21
+ if (key in commands) {
22
+ return commands[key]
23
+ }
24
+ if (execute) {
25
+ return (...args) => {
26
+ return execute(key, ...args)
27
+ }
28
+ }
29
+ return undefined
30
+ }
31
+
32
+ export const setExecute = (fn) => {
33
+ state.execute = fn
34
+ }
@@ -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'
@@ -1,6 +1,9 @@
1
1
  import { execa } from 'execa'
2
2
  import * as Assert from '../Assert/Assert.js'
3
3
 
4
+ /**
5
+ * @deprecated use node api directly
6
+ */
4
7
  export const exec = async (file, args, options) => {
5
8
  Assert.string(file)
6
9
  Assert.array(args)
@@ -0,0 +1,2 @@
1
+ export const Open = 1
2
+ export const Close = 2
@@ -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,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,12 @@
1
+ import * as Assert from '../Assert/Assert.js'
2
+ import * as Command from '../Command/Command.js'
3
+ import * as Callback from '../Callback/Callback.js'
4
+ import * as HandleJsonRpcMessage from '../HandleJsonRpcMessage/HandleJsonRpcMessage.js'
5
+
6
+ export const handleIpc = (ipc) => {
7
+ Assert.object(ipc)
8
+ const handleMessage = async (message) => {
9
+ return HandleJsonRpcMessage.handleJsonRpcMessage(ipc, message, Command.execute, Callback.resolve)
10
+ }
11
+ ipc.on('message', handleMessage)
12
+ }
@@ -0,0 +1,10 @@
1
+ import * as GetResponse from '../GetResponse/GetResponse.js'
2
+
3
+ export const handleJsonRpcMessage = async (ipc, message, execute, resolve) => {
4
+ if ('result' in message || 'error' in message) {
5
+ resolve(message.id, message)
6
+ return
7
+ }
8
+ const response = await GetResponse.getResponse(message, execute)
9
+ ipc.send(response)
10
+ }
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ export const state = {
2
+ id: 0,
3
+ }
4
+
5
+ export const create = () => {
6
+ return ++state.id
7
+ }
@@ -8,6 +8,8 @@ export const getModule = (method) => {
8
8
  return import('../IpcChildWithWebSocket/IpcChildWithWebSocket.js')
9
9
  case IpcChildType.Parent:
10
10
  return import('../IpcChildWithParent/IpcChildWithParent.js')
11
+ case IpcChildType.NodeForkedProcess:
12
+ return import('../IpcChildWithNodeForkedProcess/IpcChildWithNodeForkedProcess.js')
11
13
  case IpcChildType.ElectronMessagePort:
12
14
  return import('../IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js')
13
15
  case IpcChildType.ElectronUtilityProcess:
@@ -6,6 +6,7 @@ export const Parent = 3
6
6
  export const ElectronMessagePort = 4
7
7
  export const ElectronUtilityProcess = 5
8
8
  export const ElectronUtilityProcessMessagePort = 6
9
+ export const NodeForkedProcess = 7
9
10
 
10
11
  const getRawIpcType = () => {
11
12
  const { argv } = process
@@ -29,6 +30,8 @@ export const Auto = () => {
29
30
  return ElectronUtilityProcess
30
31
  case 'electron-utility-process-message-port':
31
32
  return ElectronUtilityProcessMessagePort
33
+ case 'node-forked-process':
34
+ return NodeForkedProcess
32
35
  default:
33
36
  throw new Error(`[extension-host-helper-process] unknown ipc type ${ipcType}`)
34
37
  }
@@ -1,15 +1,39 @@
1
- import { once } from 'events'
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+ import * as IsMessagePortMain from '../IsMessagePortMain/IsMessagePortMain.js'
2
3
 
3
- export const listen = async () => {
4
- // const [message, handle] = await once(process, 'message')
5
- // if (process.send) {
6
- // process.send('ready')
7
- // }
8
- // return {
9
- // }
4
+ export const listen = ({ messagePort }) => {
5
+ if (!IsMessagePortMain.isMessagePortMain(messagePort)) {
6
+ throw new IpcError('port must be of type MessagePortMain')
7
+ }
8
+ return messagePort
10
9
  }
11
10
 
12
- export const wrap = () => {
13
- // TODO
14
- return {}
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
+ }
15
39
  }
@@ -1,8 +1,10 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+
1
3
  export const listen = () => {
2
4
  // @ts-ignore
3
5
  const parentPort = process.parentPort
4
6
  if (!parentPort) {
5
- throw new Error('parent port must be defined')
7
+ throw new IpcError('parent port must be defined')
6
8
  }
7
9
  parentPort.postMessage('ready')
8
10
  return parentPort
@@ -3,6 +3,7 @@ import * as getFirstUtilityProcessEvent from '../GetFirstUtilityProcessEvent/Get
3
3
  import * as IpcChildType from '../IpcChildType/IpcChildType.js'
4
4
  import * as IpcChildWithElectronUtilityProcess from '../IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js'
5
5
 
6
+ // TODO remove this and use HandleElectronMessagePort function instead
6
7
  export const listen = async () => {
7
8
  const parentPort = IpcChildWithElectronUtilityProcess.listen()
8
9
  const { type, event } = await getFirstUtilityProcessEvent.getFirstUtilityProcessEvent(parentPort)
@@ -0,0 +1,36 @@
1
+ import { IpcError } from '../IpcError/IpcError.js'
2
+
3
+ export const listen = async () => {
4
+ if (!process.send) {
5
+ throw new IpcError('process ipc is not available')
6
+ }
7
+ process.send('ready')
8
+ return process
9
+ }
10
+
11
+ export const wrap = (process) => {
12
+ return {
13
+ process,
14
+ send(message) {
15
+ this.process.send(message)
16
+ },
17
+ on(event, listener) {
18
+ switch (event) {
19
+ case 'message':
20
+ this.process.on('message', listener)
21
+ break
22
+ default:
23
+ throw new Error('unknown event listener type')
24
+ }
25
+ },
26
+ off(event, listener) {
27
+ switch (event) {
28
+ case 'message':
29
+ this.process.off('message', listener)
30
+ break
31
+ default:
32
+ throw new Error('unknown event listener type')
33
+ }
34
+ },
35
+ }
36
+ }
@@ -1,10 +1,20 @@
1
- import { once } from 'events'
2
- import * as GetWebSocket from '../GetWebSocket/GetWebSocket.js'
3
- import * as Json from '../Json/Json.js'
1
+ import * as GetFirstWebSocketEvent from '../GetFirstWebSocketEvent/GetFirstWebSocketEvent.js'
2
+ import { IpcError } from '../IpcError/IpcError.js'
3
+ import * as IsWebSocket from '../IsWebSocket/IsWebSocket.js'
4
+ import * as IsWebSocketOpen from '../IsWebSocketOpen/IsWebSocketOpen.js'
5
+ import * as WebSocketSerialization from '../WebSocketSerialization/WebSocketSerialization.js'
4
6
 
5
- export const listen = async () => {
6
- const [message, handle] = await once(process, 'message')
7
- const webSocket = await GetWebSocket.getWebSocket(message, handle)
7
+ export const listen = async ({ webSocket }) => {
8
+ if (!webSocket) {
9
+ throw new IpcError('webSocket must be defined')
10
+ }
11
+ if (!IsWebSocket.isWebSocket(webSocket)) {
12
+ throw new IpcError(`webSocket must be of type WebSocket`)
13
+ }
14
+ if (!IsWebSocketOpen.isWebSocketOpen(webSocket)) {
15
+ const { type, event } = await GetFirstWebSocketEvent.getFirstWebSocketEvent(webSocket)
16
+ console.log({ type, event })
17
+ }
8
18
  return webSocket
9
19
  }
10
20
 
@@ -15,31 +25,28 @@ export const wrap = (webSocket) => {
15
25
  * @type {any}
16
26
  */
17
27
  wrappedListener: undefined,
18
- send(message) {
19
- const stringifiedMessage = Json.stringify(message)
20
- this.webSocket.send(stringifiedMessage)
21
- },
22
28
  on(event, listener) {
23
29
  switch (event) {
24
30
  case 'message':
25
- this.wrappedListener = (message) => {
26
- const parsed = Json.parse(message.toString())
27
- listener(parsed)
31
+ const wrappedListener = (message) => {
32
+ const data = WebSocketSerialization.deserialize(message)
33
+ listener(data)
28
34
  }
29
- this.webSocket.on('message', this.wrappedListener)
35
+ webSocket.on('message', wrappedListener)
30
36
  break
31
37
  default:
32
38
  throw new Error('unknown event listener type')
33
39
  }
34
40
  },
35
41
  off(event, listener) {
36
- switch (event) {
37
- case 'message':
38
- this.webSocket.off('message', this.wrappedListener)
39
- break
40
- default:
41
- throw new Error('unknown event listener type')
42
- }
42
+ this.webSocket.off(event, listener)
43
+ },
44
+ send(message) {
45
+ const stringifiedMessage = WebSocketSerialization.serialize(message)
46
+ this.webSocket.send(stringifiedMessage)
47
+ },
48
+ dispose() {
49
+ this.webSocket.close()
43
50
  },
44
51
  }
45
52
  }
@@ -0,0 +1,6 @@
1
+ export class IpcError extends Error {
2
+ constructor(message) {
3
+ super(message)
4
+ this.name = 'IpcError'
5
+ }
6
+ }
@@ -0,0 +1,3 @@
1
+ export const isMessagePort = (value) => {
2
+ return value && value instanceof MessagePort
3
+ }
@@ -0,0 +1,3 @@
1
+ export const isMessagePortMain = (value) => {
2
+ return value && value.constructor && value.constructor.name === 'MessagePortMain'
3
+ }
@@ -0,0 +1,5 @@
1
+ import { Socket } from 'node:net'
2
+
3
+ export const isSocket = (value) => {
4
+ return value instanceof Socket
5
+ }
@@ -0,0 +1,5 @@
1
+ import { WebSocket } from 'ws'
2
+
3
+ export const isWebSocket = (value) => {
4
+ return value instanceof WebSocket
5
+ }
@@ -0,0 +1,5 @@
1
+ import { WebSocket } from 'ws'
2
+
3
+ export const isWebSocketOpen = (webSocket) => {
4
+ return webSocket.readyState === WebSocket.OPEN
5
+ }
@@ -0,0 +1,21 @@
1
+ import { VError } from '../VError/VError.js'
2
+ import * as CommandState from '../CommandState/CommandState.js'
3
+ import * as ImportScript from '../ImportScript/ImportScript.js'
4
+ import * as Assert from '../Assert/Assert.js'
5
+
6
+ export const loadFile = async (path) => {
7
+ try {
8
+ Assert.string(path)
9
+ const module = await ImportScript.importScript(path)
10
+ if (module && module.commandMap) {
11
+ const commandMap = module.commandMap
12
+ CommandState.registerCommands(commandMap)
13
+ } else if (module && module.execute) {
14
+ CommandState.setExecute(module.execute)
15
+ } else {
16
+ throw new Error(`missing export const execute function`)
17
+ }
18
+ } catch (error) {
19
+ throw new VError(error, `Failed to load ${path}`)
20
+ }
21
+ }
@@ -0,0 +1,11 @@
1
+ import * as CommandMap from '../CommandMap/CommandMap.js'
2
+ import * as CommandState from '../CommandState/CommandState.js'
3
+ import * as HandleIpc from '../HandleIpc/HandleIpc.js'
4
+ import * as IpcChild from '../IpcChild/IpcChild.js'
5
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
6
+
7
+ export const main = async () => {
8
+ CommandState.registerCommands(CommandMap.commandMap)
9
+ const ipc = await IpcChild.listen({ method: IpcChildType.Auto() })
10
+ HandleIpc.handleIpc(ipc)
11
+ }
@@ -0,0 +1,7 @@
1
+ export const serialize = (message) => {
2
+ return JSON.stringify(message)
3
+ }
4
+
5
+ export const deserialize = (message) => {
6
+ return JSON.parse(message.toString())
7
+ }
@@ -0,0 +1,7 @@
1
+ import * as WebSocketServer from './WebSocketServer.js'
2
+
3
+ export const name = 'WebSocketServer'
4
+
5
+ export const Commands = {
6
+ handleUpgrade: WebSocketServer.handleUpgrade,
7
+ }
@@ -0,0 +1,21 @@
1
+ import { Buffer } from 'node:buffer'
2
+ import * as _ws from 'ws'
3
+
4
+ // workaround for jest or node bug
5
+ const WebSocketServer = _ws.WebSocketServer
6
+ ? _ws.WebSocketServer
7
+ : // @ts-ignore
8
+ _ws.default.WebSocketServer
9
+
10
+ const webSocketServer = new WebSocketServer({
11
+ noServer: true,
12
+ })
13
+
14
+ export const handleUpgrade = (request, socket) => {
15
+ return new Promise((resolve, reject) => {
16
+ const upgradeCallback = (ws) => {
17
+ resolve(ws)
18
+ }
19
+ webSocketServer.handleUpgrade(request, socket, Buffer.alloc(0), upgradeCallback)
20
+ })
21
+ }
@@ -1,5 +0,0 @@
1
- const main = async () => {
2
- await import('./extensionHostHelperProcessMain.js')
3
- }
4
-
5
- main()
@@ -1,9 +0,0 @@
1
- export const listen = () => {
2
- // TODO wait for electron message port to be passed in
3
- return {}
4
- }
5
-
6
- export const wrap = () => {
7
- // TODO
8
- return {}
9
- }
@@ -1,21 +0,0 @@
1
- export const listen = () => {
2
- return process
3
- }
4
-
5
- export const wrap = (process) => {
6
- return {
7
- process,
8
- send(message) {
9
- this.process.send(message)
10
- },
11
- on(event, listener) {
12
- switch (event) {
13
- case 'message':
14
- this.process.on('message', listener)
15
- break
16
- default:
17
- throw new Error('unknown event listener type')
18
- }
19
- },
20
- }
21
- }
@@ -1,13 +0,0 @@
1
- import * as GetResponse from '../GetResponse/GetResponse.js'
2
-
3
- export const listen = (ipc, execute) => {
4
- const handleMessage = async (message) => {
5
- if ('method' in message) {
6
- const response = await GetResponse.getResponse(message, execute)
7
- ipc.send(response)
8
- } else {
9
- console.log({ message })
10
- }
11
- }
12
- ipc.on('message', handleMessage)
13
- }