0.1.0 • Published 4 years ago

@yagisumi/e7ipc-child-process v0.1.0

Weekly downloads
1
License
MIT
Repository
github
Last release
4 years ago

@yagisumi/e7ipc-child-process

Node.js child_process communication wrapper similar to Electron v7.

NPM version install size DefinitelyTyped
Build Status Coverage percentage

Installation

$ npm i @yagisumi/e7ipc-child-process

Usage

// messages.ts
export const CHANNEL = 'app'

type MapType<T, U = keyof T> = U extends keyof T ? T[U] : never

export interface Requests {
  hello: {
    type: 'hello'
  }
  bye: {
    type: 'bye'
  }
}

export type Request = MapType<Requests>

export interface Responses {
  ok: {
    type: 'ok'
  }
  error: {
    type: 'error'
    message: string
  }
}

export type Response = MapType<Responses>

export const unexpected = (): Response => {
  return { type: 'error', message: 'unexpected' }
}
// handler.ts
import { Handler } from '@yagisumi/e7ipc-types'
import { Request, Response } from './messages'

export const handler: Handler<Request, Response> = async (_, req) => {
  if (req.type === 'hello') {
    return { type: 'ok' }
  } else if (req.type === 'bye') {
    process.removeAllListeners('message')
    return { type: 'error', message: `Don't say goodbye.` }
  } else {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const unreachable: never = req
    throw 'unreachable'
  }
}
// child.ts
import { createServer } from '@yagisumi/e7ipc-child-process'
import { CHANNEL, Request, Response } from './messages'
import { handler } from './handler'

const server = createServer<Request, Response>(CHANNEL, process)
server.handle(handler)
// main.ts
import { fork } from 'child_process'
import { CHANNEL, Request, Response, unexpected } from './messages'
import { createClient } from '@yagisumi/e7ipc-child-process'

const child = fork('./child')
const client = createClient<Request, Response>(CHANNEL, child)

async function main() {
  const r1 = await client.invoke({ type: 'hello' }).catch(unexpected)
  // r1: { type: 'ok' }
  const r2 = await client.invoke({ type: 'bye' }).catch(unexpected)
  // r2: { type: 'error', message: "Don't say goodbye." }
}

main()

Test

You can test handler with @yagisumi/e7ipc-mock

import { Mock } from '@yagisumi/e7ipc-mock'
import { Request, Response } from '@/messages'
import { handler } from '@/handler'

describe('handler', () => {
  test('request', async () => {
    const mock = new Mock<Request, Response>()
    mock.handle(handler)

    const r1 = await mock.invoke({ type: 'hello' })
    expect(r1.type).toBe('ok')

    const r2 = await mock.invoke({ type: 'bye' })
    expect(r2.type).toBe('error')
  })
})

License

MIT License