@lvce-editor/extension-host-helper-process 0.14.15 → 0.15.1

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 (35) hide show
  1. package/package.json +3 -1
  2. package/src/extensionHostHelperProcessMain.cjs +5 -0
  3. package/src/extensionHostHelperProcessMain.js +33 -1
  4. package/src/parts/CleanImportError/CleanImportError.js +20 -0
  5. package/src/parts/GetErrorResponse/GetErrorResponse.js +33 -0
  6. package/src/parts/GetModulesErrorStack/GetModulesErrorStack.js +49 -0
  7. package/src/parts/GetNewLineIndex/GetNewLineIndex.js +9 -0
  8. package/src/parts/GetResponse/GetResponse.js +6 -35
  9. package/src/parts/GetSuccessResponse/GetSuccessResponse.js +9 -0
  10. package/src/parts/ImportScript/ImportScript.js +12 -0
  11. package/src/parts/IpcChild/IpcChild.js +5 -18
  12. package/src/parts/IpcChildModule/IpcChildModule.js +20 -0
  13. package/src/parts/IpcChildType/IpcChildType.js +27 -13
  14. package/src/parts/{IpcChild → IpcChildWithElectronMessagePort}/IpcChildWithElectronMessagePort.js +5 -1
  15. package/src/parts/IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js +27 -0
  16. package/src/parts/IpcChildWithElectronUtilityProcessMessagePort/IpcChildWithElectronUtilityProcessMessagePort.js +63 -0
  17. package/src/parts/{IpcChild → IpcChildWithMessagePort}/IpcChildWithMessagePort.js +5 -0
  18. package/src/parts/{CreateProcessIpc/CreateProcessIpc.js → IpcChildWithParent/IpcChildWithParent.js} +8 -3
  19. package/src/parts/IpcChildWithWebSocket/IpcChildWithWebSocket.js +45 -0
  20. package/src/parts/JoinLines/JoinLines.js +3 -0
  21. package/src/parts/JsonRpc/JsonRpc.js +0 -2
  22. package/src/parts/JsonRpcErrorCode/JsonRpcErrorCode.js +2 -0
  23. package/src/parts/JsonRpcVersion/JsonRpcVersion.js +1 -0
  24. package/src/parts/Logger/Logger.js +50 -0
  25. package/src/parts/MergeStacks/MergeStacks.js +20 -0
  26. package/src/parts/NormalizeErrorLine/NormalizeErrorLine.js +9 -0
  27. package/src/parts/ParseCliArgs/ParseCliArgs.js +7 -0
  28. package/src/parts/PrettyError/PrettyError.js +1 -0
  29. package/src/parts/PrintPrettyError/PrintPrettyError.js +5 -0
  30. package/src/parts/Rpc/Rpc.js +4 -5
  31. package/src/parts/SplitLines/SplitLines.js +8 -0
  32. package/src/parts/VError/VError.js +27 -0
  33. package/src/parts/CreateWebSocketIpc/CreateWebSocketIpc.js +0 -23
  34. package/src/parts/IpcChild/IpcChildWithParent.js +0 -5
  35. package/src/parts/IpcChild/IpcChildWithWebSocket.js +0 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/extension-host-helper-process",
3
- "version": "0.14.15",
3
+ "version": "0.15.1",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -21,6 +21,8 @@
21
21
  "execa": "^6.1.0",
22
22
  "got": "^12.5.3",
23
23
  "lines-and-columns": "^2.0.3",
24
+ "minimist": "^1.2.8",
25
+ "verror": "^1.10.1",
24
26
  "ws": "^8.11.0"
25
27
  }
26
28
  }
@@ -0,0 +1,5 @@
1
+ const main = async () => {
2
+ await import('./extensionHostHelperProcessMain.js')
3
+ }
4
+
5
+ main()
@@ -1,10 +1,42 @@
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'
1
4
  import * as IpcChild from './parts/IpcChild/IpcChild.js'
2
5
  import * as IpcChildType from './parts/IpcChildType/IpcChildType.js'
3
6
  import * as Rpc from './parts/Rpc/Rpc.js'
7
+ import * as GetResponse from './parts/GetResponse/GetResponse.js'
8
+
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
+ }
4
22
 
5
23
  const main = async () => {
6
24
  const ipc = await IpcChild.listen({ method: IpcChildType.Auto() })
7
- Rpc.listen(ipc)
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)
8
40
  }
9
41
 
10
42
  main()
@@ -0,0 +1,20 @@
1
+ import * as GetModulesErrorStack from '../GetModulesErrorStack/GetModulesErrorStack.js'
2
+ import * as JoinLines from '../JoinLines/JoinLines.js'
3
+ import * as SplitLines from '../SplitLines/SplitLines.js'
4
+
5
+ const cleanImportSyntaxError = (error) => {
6
+ const cleanStackLines = GetModulesErrorStack.getModulesErrorStack(error.stack)
7
+ const cleanError = new SyntaxError(error.message)
8
+ const currentStack = JoinLines.joinLines(SplitLines.splitLines(new Error().stack).slice(3))
9
+ const cleanStack = JoinLines.joinLines(cleanStackLines)
10
+ const mergedStack = cleanStack + '\n' + currentStack
11
+ cleanError.stack = mergedStack
12
+ return cleanError
13
+ }
14
+
15
+ export const cleanImportError = (error) => {
16
+ if (error && error instanceof SyntaxError) {
17
+ return cleanImportSyntaxError(error)
18
+ }
19
+ return error
20
+ }
@@ -0,0 +1,33 @@
1
+ import * as JsonRpcErrorCode from '../JsonRpcErrorCode/JsonRpcErrorCode.js'
2
+ import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
3
+ import * as PrettyError from '../PrettyError/PrettyError.js'
4
+ import * as PrintPrettyError from '../PrintPrettyError/PrintPrettyError.js'
5
+
6
+ export const getErrorResponse = (message, error) => {
7
+ if (error && error instanceof Error && error.message && error.message.startsWith('method not found')) {
8
+ return {
9
+ jsonrpc: JsonRpcVersion.Two,
10
+ id: message.id,
11
+ error: {
12
+ code: JsonRpcErrorCode.MethodNotFound,
13
+ message: error.message,
14
+ data: error.stack,
15
+ },
16
+ }
17
+ }
18
+ const prettyError = PrettyError.prepare(error)
19
+ PrintPrettyError.printPrettyError(prettyError, `[extension-host-helper-process] `)
20
+ return {
21
+ jsonrpc: JsonRpcVersion.Two,
22
+ id: message.id,
23
+ error: {
24
+ code: JsonRpcErrorCode.Custom,
25
+ message: prettyError.message,
26
+ data: {
27
+ stack: prettyError.stack,
28
+ codeFrame: prettyError.codeFrame,
29
+ type: prettyError.type,
30
+ },
31
+ },
32
+ }
33
+ }
@@ -0,0 +1,49 @@
1
+ import * as SplitLines from '../SplitLines/SplitLines.js'
2
+
3
+ const RE_AT = /^ at /
4
+ const RE_JUST_PATH = /^(?:\/|\\).*\:\d+$/
5
+
6
+ const isStackLine = (line) => {
7
+ return RE_AT.test(line)
8
+ }
9
+
10
+ const isJustPath = (line) => {
11
+ return RE_JUST_PATH.test(line)
12
+ }
13
+
14
+ export const getModulesErrorStack = (stderr) => {
15
+ const lines = SplitLines.splitLines(stderr)
16
+ let startIndex = -1
17
+ const extraLines = []
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i]
20
+ if (isJustPath(line)) {
21
+ extraLines.push(` at ${line}`)
22
+ break
23
+ }
24
+ }
25
+ for (let i = 0; i < lines.length; i++) {
26
+ const line = lines[i]
27
+ if (isStackLine(line)) {
28
+ startIndex = i
29
+ break
30
+ }
31
+ }
32
+ if (startIndex === -1) {
33
+ return []
34
+ }
35
+ let endIndex = -1
36
+ for (let i = startIndex + 1; i < lines.length; i++) {
37
+ const line = lines[i]
38
+ if (!isStackLine(line)) {
39
+ endIndex = i
40
+ break
41
+ }
42
+ }
43
+ if (endIndex === -1) {
44
+ endIndex = lines.length - 1
45
+ }
46
+ const stackLines = lines.slice(startIndex, endIndex)
47
+ const stack = [lines[startIndex - 1], ...extraLines, ...stackLines]
48
+ return stack
49
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ *
3
+ * @param {string} string
4
+ * @param {number|undefined} startIndex
5
+ * @returns
6
+ */
7
+ export const getNewLineIndex = (string, startIndex = undefined) => {
8
+ return string.indexOf('\n', startIndex)
9
+ }
@@ -1,40 +1,11 @@
1
- import * as Command from '../Command/Command.js'
2
- import * as JsonRpc from '../JsonRpc/JsonRpc.js'
3
- import * as PrettyError from '../PrettyError/PrettyError.js'
1
+ import * as GetErrorResponse from '../GetErrorResponse/GetErrorResponse.js'
2
+ import * as GetSuccessResponse from '../GetSuccessResponse/GetSuccessResponse.js'
4
3
 
5
- export const getResponse = async (message) => {
4
+ export const getResponse = async (message, execute) => {
6
5
  try {
7
- const result = await Command.invoke(message.method, ...message.params)
8
- return {
9
- jsonrpc: JsonRpc.Version,
10
- id: message.id,
11
- result,
12
- }
6
+ const result = await execute(message.method, ...message.params)
7
+ return GetSuccessResponse.getSuccessResponse(message, result)
13
8
  } catch (error) {
14
- if (error && error instanceof Error && error.message && error.message.startsWith('method not found')) {
15
- return {
16
- jsonrpc: JsonRpc.Version,
17
- id: message.id,
18
- error: {
19
- code: JsonRpc.ErrorMethodNotFound,
20
- message: error.message,
21
- data: error.stack,
22
- },
23
- }
24
- }
25
- const prettyError = PrettyError.prepare(error)
26
- return {
27
- jsonrpc: JsonRpc.Version,
28
- id: message.id,
29
- error: {
30
- code: -32001,
31
- message: prettyError.message,
32
- data: {
33
- stack: prettyError.stack,
34
- codeFrame: prettyError.codeFrame,
35
- code: prettyError.code,
36
- },
37
- },
38
- }
9
+ return GetErrorResponse.getErrorResponse(message, error)
39
10
  }
40
11
  }
@@ -0,0 +1,9 @@
1
+ import * as JsonRpcVersion from '../JsonRpcVersion/JsonRpcVersion.js'
2
+
3
+ export const getSuccessResponse = (message, result) => {
4
+ return {
5
+ jsonrpc: JsonRpcVersion.Two,
6
+ id: message.id,
7
+ result: result ?? null,
8
+ }
9
+ }
@@ -0,0 +1,12 @@
1
+ import { VError } from '../VError/VError.js'
2
+ import * as CleanImportError from '../CleanImportError/CleanImportError.js'
3
+
4
+ export const importScript = async (path) => {
5
+ try {
6
+ const module = await import(path)
7
+ return module
8
+ } catch (error) {
9
+ const cleanError = CleanImportError.cleanImportError(error)
10
+ throw new VError(cleanError, `Failed to load ${path}`)
11
+ }
12
+ }
@@ -1,21 +1,8 @@
1
- import * as IpcChildType from '../IpcChildType/IpcChildType.js'
2
-
3
- const getModule = (method) => {
4
- switch (method) {
5
- case IpcChildType.MessagePort:
6
- return import('./IpcChildWithMessagePort.js')
7
- case IpcChildType.WebSocket:
8
- return import('./IpcChildWithWebSocket.js')
9
- case IpcChildType.Parent:
10
- return import('./IpcChildWithParent.js')
11
- case IpcChildType.ElectronMessagePort:
12
- return import('./IpcChildWithElectronMessagePort.js')
13
- default:
14
- throw new Error('unexpected ipc type')
15
- }
16
- }
1
+ import * as IpcChildModule from '../IpcChildModule/IpcChildModule.js'
17
2
 
18
3
  export const listen = async ({ method }) => {
19
- const module = await getModule(method)
20
- return module.listen()
4
+ const module = await IpcChildModule.getModule(method)
5
+ const rawIpc = await module.listen()
6
+ const ipc = module.wrap(rawIpc)
7
+ return ipc
21
8
  }
@@ -0,0 +1,20 @@
1
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
2
+
3
+ export const getModule = (method) => {
4
+ switch (method) {
5
+ case IpcChildType.MessagePort:
6
+ return import('../IpcChildWithMessagePort/IpcChildWithMessagePort.js')
7
+ case IpcChildType.WebSocket:
8
+ return import('../IpcChildWithWebSocket/IpcChildWithWebSocket.js')
9
+ case IpcChildType.Parent:
10
+ return import('../IpcChildWithParent/IpcChildWithParent.js')
11
+ case IpcChildType.ElectronMessagePort:
12
+ return import('../IpcChildWithElectronMessagePort/IpcChildWithElectronMessagePort.js')
13
+ case IpcChildType.ElectronUtilityProcess:
14
+ return import('../IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js')
15
+ case IpcChildType.ElectronUtilityProcessMessagePort:
16
+ return import('../IpcChildWithElectronUtilityProcessMessagePort/IpcChildWithElectronUtilityProcessMessagePort.js')
17
+ default:
18
+ throw new Error('unexpected ipc type')
19
+ }
20
+ }
@@ -1,21 +1,35 @@
1
+ import * as ParseCliArgs from '../ParseCliArgs/ParseCliArgs.js'
2
+
1
3
  export const WebSocket = 1
2
4
  export const MessagePort = 2
3
5
  export const Parent = 3
4
6
  export const ElectronMessagePort = 4
7
+ export const ElectronUtilityProcess = 5
8
+ export const ElectronUtilityProcessMessagePort = 6
5
9
 
6
- export const Auto = () => {
10
+ const getRawIpcType = () => {
7
11
  const { argv } = process
8
- if (argv.includes('--ipc-type=websocket')) {
9
- return WebSocket
10
- }
11
- if (argv.includes('--ipc-type=message-port')) {
12
- return MessagePort
13
- }
14
- if (argv.includes('--ipc-type=parent')) {
15
- return Parent
16
- }
17
- if (argv.includes('--ipc-type=electron-message-port')) {
18
- return ElectronMessagePort
12
+ const parsedArgs = ParseCliArgs.parseCliArgs(argv.slice(2))
13
+ const ipcType = parsedArgs['ipc-type']
14
+ return ipcType
15
+ }
16
+
17
+ export const Auto = () => {
18
+ const ipcType = getRawIpcType()
19
+ switch (ipcType) {
20
+ case 'websocket':
21
+ return WebSocket
22
+ case 'message-port':
23
+ return MessagePort
24
+ case 'parent':
25
+ return Parent
26
+ case 'electron-message-port':
27
+ return ElectronMessagePort
28
+ case 'electron-utility-process':
29
+ return ElectronUtilityProcess
30
+ case 'electron-utility-process-message-port':
31
+ return ElectronUtilityProcessMessagePort
32
+ default:
33
+ throw new Error(`[extension-host-helper-process] unknown ipc type ${ipcType}`)
19
34
  }
20
- throw new Error('[extension-host-helper-process] unknown ipc type')
21
35
  }
@@ -2,10 +2,14 @@ import { once } from 'events'
2
2
 
3
3
  export const listen = async () => {
4
4
  // const [message, handle] = await once(process, 'message')
5
- // console.log({ message, handle })
6
5
  // if (process.send) {
7
6
  // process.send('ready')
8
7
  // }
9
8
  // return {
10
9
  // }
11
10
  }
11
+
12
+ export const wrap = () => {
13
+ // TODO
14
+ return {}
15
+ }
@@ -0,0 +1,27 @@
1
+ export const listen = () => {
2
+ // @ts-ignore
3
+ const parentPort = process.parentPort
4
+ if (!parentPort) {
5
+ throw new Error('parent port must be defined')
6
+ }
7
+ parentPort.postMessage('ready')
8
+ return parentPort
9
+ }
10
+
11
+ export const wrap = (parentPort) => {
12
+ return {
13
+ parentPort,
14
+ on(event, listener) {
15
+ this.parentPort.on(event, listener)
16
+ },
17
+ off(event, listener) {
18
+ this.parentPort.off(event, listener)
19
+ },
20
+ send(message) {
21
+ this.parentPort.postMessage(message)
22
+ },
23
+ dispose() {
24
+ this.parentPort.close()
25
+ },
26
+ }
27
+ }
@@ -0,0 +1,63 @@
1
+ import * as IpcChildWithElectronUtilityProcess from '../IpcChildWithElectronUtilityProcess/IpcChildWithElectronUtilityProcess.js'
2
+ import * as IpcChildType from '../IpcChildType/IpcChildType.js'
3
+
4
+ const waitForFirstMessage = async (parentPort) => {
5
+ const { type, event } = await new Promise((resolve) => {
6
+ const cleanup = (value) => {
7
+ parentPort.off('message', handleMessage)
8
+ resolve(value)
9
+ }
10
+ const handleMessage = (event) => {
11
+ cleanup({ type: 'message', event })
12
+ }
13
+ parentPort.on('message', handleMessage)
14
+ })
15
+ return {
16
+ type,
17
+ event,
18
+ }
19
+ }
20
+
21
+ export const listen = async () => {
22
+ const parentPort = IpcChildWithElectronUtilityProcess.listen()
23
+ const { type, event } = await waitForFirstMessage(parentPort)
24
+ if (type !== 'message') {
25
+ throw new Error('expected message event')
26
+ }
27
+ const { ports } = event
28
+ if (ports.length === 0) {
29
+ throw new Error(`expected message port to be passed`)
30
+ }
31
+ const port = ports[0]
32
+ port.start()
33
+ return port
34
+ }
35
+
36
+ export const wrap = (port) => {
37
+ return {
38
+ type: IpcChildType.ElectronUtilityProcessMessagePort,
39
+ port,
40
+ on(event, listener) {
41
+ switch (event) {
42
+ case 'message':
43
+ const wrappedListener = (event) => {
44
+ listener(event.data)
45
+ }
46
+ this.port.on(event, wrappedListener)
47
+ break
48
+ default:
49
+ this.port.on(event, listener)
50
+ break
51
+ }
52
+ },
53
+ off(event, listener) {
54
+ this.port.off(event, listener)
55
+ },
56
+ send(message) {
57
+ this.port.postMessage(message)
58
+ },
59
+ dispose() {
60
+ this.port.close()
61
+ },
62
+ }
63
+ }
@@ -2,3 +2,8 @@ export const listen = () => {
2
2
  // TODO wait for electron message port to be passed in
3
3
  return {}
4
4
  }
5
+
6
+ export const wrap = () => {
7
+ // TODO
8
+ return {}
9
+ }
@@ -1,12 +1,17 @@
1
- export const createProcessIpc = (process) => {
1
+ export const listen = () => {
2
+ return process
3
+ }
4
+
5
+ export const wrap = (process) => {
2
6
  return {
7
+ process,
3
8
  send(message) {
4
- process.send(message)
9
+ this.process.send(message)
5
10
  },
6
11
  on(event, listener) {
7
12
  switch (event) {
8
13
  case 'message':
9
- process.on('message', listener)
14
+ this.process.on('message', listener)
10
15
  break
11
16
  default:
12
17
  throw new Error('unknown event listener type')
@@ -0,0 +1,45 @@
1
+ import { once } from 'events'
2
+ import * as GetWebSocket from '../GetWebSocket/GetWebSocket.js'
3
+ import * as Json from '../Json/Json.js'
4
+
5
+ export const listen = async () => {
6
+ const [message, handle] = await once(process, 'message')
7
+ const webSocket = await GetWebSocket.getWebSocket(message, handle)
8
+ return webSocket
9
+ }
10
+
11
+ export const wrap = (webSocket) => {
12
+ return {
13
+ webSocket,
14
+ /**
15
+ * @type {any}
16
+ */
17
+ wrappedListener: undefined,
18
+ send(message) {
19
+ const stringifiedMessage = Json.stringify(message)
20
+ this.webSocket.send(stringifiedMessage)
21
+ },
22
+ on(event, listener) {
23
+ switch (event) {
24
+ case 'message':
25
+ this.wrappedListener = (message) => {
26
+ const parsed = Json.parse(message.toString())
27
+ listener(parsed)
28
+ }
29
+ this.webSocket.on('message', this.wrappedListener)
30
+ break
31
+ default:
32
+ throw new Error('unknown event listener type')
33
+ }
34
+ },
35
+ 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
+ }
43
+ },
44
+ }
45
+ }
@@ -0,0 +1,3 @@
1
+ export const joinLines = (lines) => {
2
+ return lines.join('\n')
3
+ }
@@ -1,3 +1 @@
1
- export const Version = '2.0'
2
-
3
1
  export const ErrorMethodNotFound = -32601
@@ -0,0 +1,2 @@
1
+ export const MethodNotFound = -32601
2
+ export const Custom = -32001
@@ -0,0 +1 @@
1
+ export const Two = '2.0'
@@ -0,0 +1,50 @@
1
+ import { Console } from 'node:console'
2
+ import { createWriteStream } from 'node:fs'
3
+ import { tmpdir } from 'node:os'
4
+
5
+ // TODO mock this module when used in unit tests
6
+
7
+ const state = {
8
+ /**
9
+ * @type {Console|undefined}
10
+ */
11
+ console: undefined,
12
+ }
13
+
14
+ const createConsole = () => {
15
+ const logFile = `${tmpdir()}/log-extension-host-helper-process.txt`
16
+ const writeStream = createWriteStream(logFile)
17
+ const logger = new Console(writeStream)
18
+ return logger
19
+ }
20
+
21
+ const getOrCreateLogger = () => {
22
+ if (!state.console) {
23
+ state.console = createConsole()
24
+ }
25
+ return state.console
26
+ }
27
+
28
+ export const log = (...args) => {
29
+ const logger = getOrCreateLogger()
30
+ logger.log(...args)
31
+ console.log(...args)
32
+ }
33
+
34
+ export const info = (...args) => {
35
+ const logger = getOrCreateLogger()
36
+ logger.info(...args)
37
+ console.info(...args)
38
+ }
39
+
40
+ export const warn = (...args) => {
41
+ const logger = getOrCreateLogger()
42
+ logger.warn(...args)
43
+ console.warn(...args)
44
+ }
45
+
46
+ export const error = (...args) => {
47
+ const logger = getOrCreateLogger()
48
+ logger.error(...args)
49
+ console.error(...args)
50
+ }
@@ -0,0 +1,20 @@
1
+ import * as GetNewLineIndex from '../GetNewLineIndex/GetNewLineIndex.js'
2
+ import * as NormalizeErrorLine from '../NormalizeErrorLine/NormalizeErrorLine.js'
3
+
4
+ export const mergeStacks = (parent, child) => {
5
+ if (!child) {
6
+ return parent
7
+ }
8
+ const parentNewLineIndex = GetNewLineIndex.getNewLineIndex(parent)
9
+ const childNewLineIndex = GetNewLineIndex.getNewLineIndex(child)
10
+ if (childNewLineIndex === -1) {
11
+ return parent
12
+ }
13
+ const parentFirstLine = parent.slice(0, parentNewLineIndex)
14
+ const childRest = child.slice(childNewLineIndex)
15
+ const childFirstLine = NormalizeErrorLine.normalizeLine(child.slice(0, childNewLineIndex))
16
+ if (parentFirstLine.includes(childFirstLine)) {
17
+ return parentFirstLine + childRest
18
+ }
19
+ return child
20
+ }
@@ -0,0 +1,9 @@
1
+ export const normalizeLine = (line) => {
2
+ if (line.startsWith('Error: ')) {
3
+ return line.slice(`Error: `.length)
4
+ }
5
+ if (line.startsWith('VError: ')) {
6
+ return line.slice(`VError: `.length)
7
+ }
8
+ return line
9
+ }
@@ -0,0 +1,7 @@
1
+ import minimist from 'minimist'
2
+
3
+ export const parseCliArgs = (args) => {
4
+ const CLI_OPTIONS = {}
5
+ const parsedArgs = minimist(args, CLI_OPTIONS)
6
+ return parsedArgs
7
+ }
@@ -50,5 +50,6 @@ export const prepare = (error) => {
50
50
  stack: relevantStack,
51
51
  codeFrame,
52
52
  code: error.code,
53
+ type: error.constructor.name,
53
54
  }
54
55
  }
@@ -0,0 +1,5 @@
1
+ import * as Logger from '../Logger/Logger.js'
2
+
3
+ export const printPrettyError = (prettyError, prefix = '') => {
4
+ Logger.error(`${prefix}${prettyError.type}: ${prettyError.message}\n\n${prettyError.codeFrame}\n\n${prettyError.stack}\n`)
5
+ }
@@ -1,14 +1,13 @@
1
1
  import * as GetResponse from '../GetResponse/GetResponse.js'
2
2
 
3
- export const listen = (ipc) => {
3
+ export const listen = (ipc, execute) => {
4
4
  const handleMessage = async (message) => {
5
5
  if ('method' in message) {
6
- const response = await GetResponse.getResponse(message)
6
+ const response = await GetResponse.getResponse(message, execute)
7
7
  ipc.send(response)
8
+ } else {
9
+ console.log({ message })
8
10
  }
9
11
  }
10
12
  ipc.on('message', handleMessage)
11
- if (process.send) {
12
- process.send('ready')
13
- }
14
13
  }
@@ -1,3 +1,11 @@
1
+ /**
2
+ *
3
+ * @param {string|undefined} lines
4
+ * @returns string[]
5
+ */
1
6
  export const splitLines = (lines) => {
7
+ if (!lines) {
8
+ return []
9
+ }
2
10
  return lines.split('\n')
3
11
  }
@@ -0,0 +1,27 @@
1
+ import * as MergeStacks from '../MergeStacks/MergeStacks.js'
2
+ import * as NormalizeErrorLine from '../NormalizeErrorLine/NormalizeErrorLine.js'
3
+
4
+ const getCombinedMessage = (error, message) => {
5
+ const stringifiedError = NormalizeErrorLine.normalizeLine(`${error}`)
6
+ if (message) {
7
+ return `${message}: ${stringifiedError}`
8
+ }
9
+ return stringifiedError
10
+ }
11
+
12
+ export class VError extends Error {
13
+ constructor(error, message) {
14
+ const combinedMessage = getCombinedMessage(error, message)
15
+ super(combinedMessage)
16
+ this.name = 'VError'
17
+ if (error instanceof Error) {
18
+ this.stack = MergeStacks.mergeStacks(this.stack, error.stack)
19
+ }
20
+ if (error.codeFrame) {
21
+ this.codeFrame = error.codeFrame
22
+ }
23
+ if (error.code) {
24
+ this.code = error.code
25
+ }
26
+ }
27
+ }
@@ -1,23 +0,0 @@
1
- import * as Json from '../Json/Json.js'
2
-
3
- export const createWebSocketIpc = (webSocket) => {
4
- return {
5
- send(message) {
6
- const stringifiedMessage = Json.stringify(message)
7
- webSocket.send(stringifiedMessage)
8
- },
9
- on(event, listener) {
10
- switch (event) {
11
- case 'message':
12
- const wrappedListener = (message) => {
13
- const parsed = Json.parse(message.toString())
14
- listener(parsed)
15
- }
16
- webSocket.on('message', wrappedListener)
17
- break
18
- default:
19
- throw new Error('unknown event listener type')
20
- }
21
- },
22
- }
23
- }
@@ -1,5 +0,0 @@
1
- import * as CreateProcessIpc from '../CreateProcessIpc/CreateProcessIpc.js'
2
-
3
- export const listen = () => {
4
- return CreateProcessIpc.createProcessIpc(process)
5
- }
@@ -1,10 +0,0 @@
1
- import { once } from 'events'
2
- import * as CreateWebSocketIpc from '../CreateWebSocketIpc/CreateWebSocketIpc.js'
3
- import * as GetWebSocket from '../GetWebSocket/GetWebSocket.js'
4
-
5
- export const listen = async () => {
6
- const [message, handle] = await once(process, 'message')
7
- const webSocket = await GetWebSocket.getWebSocket(message, handle)
8
- const ipc = CreateWebSocketIpc.createWebSocketIpc(webSocket)
9
- return ipc
10
- }