Skip to content

Commit

Permalink
refactor: reduce cyclomatic complexity (#60)
Browse files Browse the repository at this point in the history
  • Loading branch information
mato533 authored Oct 31, 2024
1 parent fb5d549 commit 8588f1a
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 326 deletions.
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ Generate api on the bridge across isolated contexts of the electron.

# Why use this library?

There are following reasends.
There are following reasons.

1. When implementing IPC using contextBridge, we want to use it in a type-safe.

<img width="824" alt="image" src="https://github.com/user-attachments/assets/cbe58812-bda6-4294-bb28-911f549c6a3e">

1. We want to be freed from channel management.

This library is automaticaly generate channel ids with uuid.
This library is automatically generate channel ids with uuid.
We can feel free to manage channel strings.(don't worry about typos. e.g. say-hello or do-hello??)

# How to use it?
Expand All @@ -28,15 +28,15 @@ There are following reasends.
npm install electron-typed-ipc-bridge
```

## Implimentation
## How to implement this library??

### Core

**There are 5 STEPS to use this library.**

1. #### Create api on **`main`** script

1. Impliment the API of the IPC context bridge
1. Implement the API of the IPC context bridge

- `invoke` : **renderer --(data)--> main --(return data)--> renderer**
return data is the option
Expand All @@ -57,7 +57,7 @@ npm install electron-typed-ipc-bridge

1. Generate and export type definitions

- `IpcBridgeApiEmitter`: For the type of Emtter to use message from main to renderer.(defined at `on` by step.1-1)
- `IpcBridgeApiEmitter`: For the type of Emitter to use message from main to renderer.(defined at `on` by step.1-1)
- `IpcBridgeApi` : For the type of exposed api(exposed to renderer, defined at `invoke` and `on` by step.1-1)

```typescript
Expand All @@ -82,14 +82,14 @@ npm install electron-typed-ipc-bridge
```

1. Generate the Ipc context bridge API Emitter(apis defined at `on`)
The type of `ipcApi` is same as `IpcBridgeApiEmitter` expoted by [Step1](#create-api-on-main-script)
The type of `ipcApi` is same as `IpcBridgeApiEmitter` exported by [Step1](#create-api-on-main-script)

```typescript
const ipcApi = getIpcBridgeApiEmitter(api)
// When send a message to renderer,
// use as folloing code
//(see the playgrond code of `setMenu(mainWindow, api)`
// use as following code
//(see the playground code of `setMenu(mainWindow, api)`
// at the `createWindow(ipcApi)`)
ipcApi.send.updateCounter(mainWindow, 1)
```
Expand All @@ -110,7 +110,7 @@ npm install electron-typed-ipc-bridge

See the playground code: [`preload/index.ts`](playground/src/preload/index.ts)

1. #### Add type decolation
1. #### Add type decoration

Extends the window object.
Import the type exported by [Step1](#create-api-on-main-script) and use it as follow.
Expand Down Expand Up @@ -144,17 +144,17 @@ npm install electron-typed-ipc-bridge

See the playground code: [`renderer/src/App.vue`](playground/src/renderer/src/App.vue)

### Logging for this libraly
### Logging for this library

This libraly is implimented the logger using `console.log`, `console.error` and `console.debug`.
This library is implemented the logger using `console.log`, `console.error` and `console.debug`.

But you may want to disable logging or use another logging library(e.g. [`electron-log`](https://github.com/megahertz/electron-log/tree/master)).
This libraly provides a way in which you can do so.
This library provides a way in which you can do so.

#### Disable logging

Import the `initialise` function and set empty object to `logger`.
Call it before calling another fuctions expoted by this library.
Call it before calling another functions exported by this library.

- main.ts

Expand All @@ -172,7 +172,7 @@ Call it before calling another fuctions expoted by this library.
initialise({ logger: {} })
```
#### implimente custom logger.
#### Implement custom logger.
<details>
Expand Down Expand Up @@ -228,16 +228,16 @@ Set to the logger to this library.
</details>
#### Loglevel
#### Log Level
Each log levels are output following infomations.
Each log levels are output following information.
(This is what we do now, but this may change in the future.)
| level | overview |
| :-----: | ---------------------------------------------------------------------- |
| info | Output the start and end of processing by the library |
| warn | - (Not used) |
| error | Output the message when runtime error occurd. |
| error | Output the message when runtime error occurred. |
| verbose | - (Not used) |
| debug | Output detailed log regarding `IpcBridgeApi` generation process |
| silly | Output the function name and channel every time `IpcBridgeApi` is used |
135 changes: 22 additions & 113 deletions src/__tests__/channel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { getApiChannelMap, haveSameStructure } from '../channel'
import { getApiChannelMap } from '../channel'
import * as uuid from '../utils/uuid'

import type { IpcMainInvokeEvent } from 'electron'

const apiHandlers = {
invoke: {
fn1: (e: IpcMainInvokeEvent) => console.log(e),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
name1: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
on: {
fn1: () => console.log('sss'),
name2: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
} as const
describe('Generate api channel map', () => {
const dummyUUID = '1234-abcd-1234-abcd-1234'
const uuidSpy = vi.spyOn(uuid, 'genUUID').mockReturnValue(dummyUUID)

it('generate vaild structure', () => {
const apiHandlers = {
invoke: {
fn1: (e: IpcMainInvokeEvent) => console.log(e),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
name1: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
on: {
fn1: () => console.log('sss'),
},
} as const
const result = getApiChannelMap(apiHandlers)
assert.deepEqual(result, {
invoke: {
Expand All @@ -33,113 +37,18 @@ describe('Generate api channel map', () => {
},
on: {
fn1: dummyUUID,
name2: {
fn1: dummyUUID,
fn2: dummyUUID,
},
},
})
})

it('same channelmap are retured when multiple called', () => {
uuidSpy.mockRestore()
const apiHandlers = {
invoke: {
fn1: (e: IpcMainInvokeEvent) => console.log(e),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
name1: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
on: {
fn1: () => console.log('sss'),
name2: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
} as const
const result1 = getApiChannelMap(apiHandlers)
const result2 = getApiChannelMap(apiHandlers)
assert.deepEqual(result1, result2)
})
})

describe('haveSameStructure', () => {
it('success', () => {
const apiHandlers = {
invoke: {
fn1: (e: IpcMainInvokeEvent) => console.log(e),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
name1: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
on: {
fn1: () => console.log('sss'),
name2: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
} as const

const channelMap = {
invoke: {
fn1: 'uuid-fn1',
fn2: 'uuid-fn2',
name1: {
fn1: 'uuid-name1-fn1',
fn2: 'uuid-name1-fn2',
},
},
on: {
fn1: 'uuid-fn1',
name2: {
fn1: 'uuid-name2-fn1',
fn2: 'uuid-name2-fn2',
},
},
}
expect(haveSameStructure(apiHandlers, channelMap)).toBeTruthy()
})

it('fail', () => {
const apiHandlers = {
invoke: {
fn1: (e: IpcMainInvokeEvent) => console.log(e),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
name1: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
on: {
fn1: () => console.log('sss'),
name2: {
fn1: () => console.log(),
fn2: (e: IpcMainInvokeEvent) => console.log(e),
},
},
} as const

const channelMap = {
invoke: {
fn1: 'uuid-fn1',
fn2: 'uuid-fn2',
name1: {
fn1: 'uuid-name1-fn1',
// fn2: 'uuid-name1-fn2', // unmatch
fn3: 'uuid-name1-fn3', // unmatch
},
},
on: {
fn1: 'uuid-fn1',
name2: {
fn1: 'uuid-name2-fn1',
// fn2: 'uuid-name2-fn2', // unmatch
},
},
}
// @ts-expect-error
expect(haveSameStructure(apiHandlers, channelMap)).toBeFalsy()
})
})
Loading

0 comments on commit 8588f1a

Please sign in to comment.