diff options
Diffstat (limited to 'packages/preload')
-rw-r--r-- | packages/preload/.eslintrc.cjs | 6 | ||||
-rw-r--r-- | packages/preload/esbuild.config.js | 6 | ||||
-rw-r--r-- | packages/preload/jest.config.js | 2 | ||||
-rw-r--r-- | packages/preload/package.json | 6 | ||||
-rw-r--r-- | packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts (renamed from packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts) | 26 | ||||
-rw-r--r-- | packages/preload/src/contextBridge/createSophieRenderer.ts (renamed from packages/preload/src/contextBridge/SophieRendererImpl.ts) | 42 | ||||
-rw-r--r-- | packages/preload/src/index.ts | 2 | ||||
-rw-r--r-- | packages/preload/tsconfig.json | 8 |
8 files changed, 52 insertions, 46 deletions
diff --git a/packages/preload/.eslintrc.cjs b/packages/preload/.eslintrc.cjs new file mode 100644 index 0000000..02fab21 --- /dev/null +++ b/packages/preload/.eslintrc.cjs | |||
@@ -0,0 +1,6 @@ | |||
1 | module.exports = { | ||
2 | env: { | ||
3 | node: true, | ||
4 | browser: true, | ||
5 | }, | ||
6 | }; | ||
diff --git a/packages/preload/esbuild.config.js b/packages/preload/esbuild.config.js index b73a071..66f5e84 100644 --- a/packages/preload/esbuild.config.js +++ b/packages/preload/esbuild.config.js | |||
@@ -1,8 +1,8 @@ | |||
1 | import { chrome } from '../../config/buildConstants.js'; | 1 | import { chrome } from '../../config/buildConstants.js'; |
2 | import { getConfig } from '../../config/esbuildConfig.js'; | 2 | import fileURLToDirname from '../../config/fileURLToDirname.js'; |
3 | import { fileURLToDirname } from '../../config/utils.js'; | 3 | import getEsbuildConfig from '../../config/getEsbuildConfig.js'; |
4 | 4 | ||
5 | export default getConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: [ |
8 | 'src/index.ts', | 8 | 'src/index.ts', |
diff --git a/packages/preload/jest.config.js b/packages/preload/jest.config.js index e474c4c..27af475 100644 --- a/packages/preload/jest.config.js +++ b/packages/preload/jest.config.js | |||
@@ -1,6 +1,6 @@ | |||
1 | import rootConfig from '../../config/jest.config.base.js'; | 1 | import rootConfig from '../../config/jest.config.base.js'; |
2 | 2 | ||
3 | /** @type {import('ts-jest').InitialOptionsTsJest} */ | 3 | /** @type {import('@jest/types').Config.InitialOptions} */ |
4 | export default { | 4 | export default { |
5 | ...rootConfig, | 5 | ...rootConfig, |
6 | testEnvironment: 'jsdom', | 6 | testEnvironment: 'jsdom', |
diff --git a/packages/preload/package.json b/packages/preload/package.json index 0957aaf..a03d7d9 100644 --- a/packages/preload/package.json +++ b/packages/preload/package.json | |||
@@ -6,7 +6,7 @@ | |||
6 | "type": "module", | 6 | "type": "module", |
7 | "types": "dist-types/index.d.ts", | 7 | "types": "dist-types/index.d.ts", |
8 | "scripts": { | 8 | "scripts": { |
9 | "typecheck": "tsc" | 9 | "typecheck:workspace": "yarn g:typecheck" |
10 | }, | 10 | }, |
11 | "dependencies": { | 11 | "dependencies": { |
12 | "@sophie/shared": "workspace:*", | 12 | "@sophie/shared": "workspace:*", |
@@ -20,8 +20,6 @@ | |||
20 | "@types/jest": "^27.4.0", | 20 | "@types/jest": "^27.4.0", |
21 | "jest": "^27.4.7", | 21 | "jest": "^27.4.7", |
22 | "jest-mock": "^27.4.6", | 22 | "jest-mock": "^27.4.6", |
23 | "jsdom": "^19.0.0", | 23 | "jsdom": "^19.0.0" |
24 | "rimraf": "^3.0.2", | ||
25 | "typescript": "^4.5.4" | ||
26 | } | 24 | } |
27 | } | 25 | } |
diff --git a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts b/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts index ff77a63..a38dbac 100644 --- a/packages/preload/src/contextBridge/__tests__/SophieRendererImpl.spec.ts +++ b/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts | |||
@@ -19,9 +19,6 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { jest } from '@jest/globals'; | 21 | import { jest } from '@jest/globals'; |
22 | import { mocked } from 'jest-mock'; | ||
23 | import log from 'loglevel'; | ||
24 | import type { IJsonPatch } from 'mobx-state-tree'; | ||
25 | import { | 22 | import { |
26 | Action, | 23 | Action, |
27 | MainToRendererIpcMessage, | 24 | MainToRendererIpcMessage, |
@@ -29,6 +26,9 @@ import { | |||
29 | SharedStoreSnapshotIn, | 26 | SharedStoreSnapshotIn, |
30 | SophieRenderer, | 27 | SophieRenderer, |
31 | } from '@sophie/shared'; | 28 | } from '@sophie/shared'; |
29 | import { mocked } from 'jest-mock'; | ||
30 | import log from 'loglevel'; | ||
31 | import type { IJsonPatch } from 'mobx-state-tree'; | ||
32 | 32 | ||
33 | jest.unstable_mockModule('electron', () => ({ | 33 | jest.unstable_mockModule('electron', () => ({ |
34 | ipcRenderer: { | 34 | ipcRenderer: { |
@@ -40,7 +40,7 @@ jest.unstable_mockModule('electron', () => ({ | |||
40 | 40 | ||
41 | const { ipcRenderer } = await import('electron'); | 41 | const { ipcRenderer } = await import('electron'); |
42 | 42 | ||
43 | const { createSophieRenderer } = await import('../SophieRendererImpl'); | 43 | const { default: createSophieRenderer } = await import('../createSophieRenderer'); |
44 | 44 | ||
45 | const event: Electron.IpcRendererEvent = null as unknown as Electron.IpcRendererEvent; | 45 | const event: Electron.IpcRendererEvent = null as unknown as Electron.IpcRendererEvent; |
46 | 46 | ||
@@ -81,10 +81,10 @@ describe('createSophieRenderer', () => { | |||
81 | }); | 81 | }); |
82 | }); | 82 | }); |
83 | 83 | ||
84 | describe('SophieRendererImpl', () => { | 84 | describe('SharedStoreConnector', () => { |
85 | let sut: SophieRenderer; | 85 | let sut: SophieRenderer; |
86 | let onSharedStorePatch: (event1: Electron.IpcRendererEvent, patch1: unknown) => void; | 86 | let onSharedStorePatch: (eventArg: Electron.IpcRendererEvent, patchArg: unknown) => void; |
87 | let listener = { | 87 | const listener = { |
88 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars | 88 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars |
89 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => {}), | 89 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => {}), |
90 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars | 90 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars |
@@ -93,9 +93,9 @@ describe('SophieRendererImpl', () => { | |||
93 | 93 | ||
94 | beforeEach(() => { | 94 | beforeEach(() => { |
95 | sut = createSophieRenderer(false); | 95 | sut = createSophieRenderer(false); |
96 | onSharedStorePatch = mocked(ipcRenderer.on).mock.calls.find(([channel]) => { | 96 | [, onSharedStorePatch] = mocked(ipcRenderer.on).mock.calls.find( |
97 | return channel === MainToRendererIpcMessage.SharedStorePatch; | 97 | ([channel]) => channel === MainToRendererIpcMessage.SharedStorePatch, |
98 | })?.[1]!; | 98 | )!; |
99 | }); | 99 | }); |
100 | 100 | ||
101 | describe('onSharedStoreChange', () => { | 101 | describe('onSharedStoreChange', () => { |
@@ -140,15 +140,15 @@ describe('SophieRendererImpl', () => { | |||
140 | }); | 140 | }); |
141 | }); | 141 | }); |
142 | 142 | ||
143 | function itRefusesToRegisterAnotherListener() { | 143 | function itRefusesToRegisterAnotherListener(): void { |
144 | it('should refuse to register another listener', async () => { | 144 | it('should refuse to register another listener', async () => { |
145 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); | 145 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); |
146 | }); | 146 | }); |
147 | } | 147 | } |
148 | 148 | ||
149 | function itDoesNotPassPatchesToTheListener( | 149 | function itDoesNotPassPatchesToTheListener( |
150 | name: string = 'should not pass patches to the listener', | 150 | name = 'should not pass patches to the listener', |
151 | ) { | 151 | ): void { |
152 | it(name, () => { | 152 | it(name, () => { |
153 | onSharedStorePatch(event, patch); | 153 | onSharedStorePatch(event, patch); |
154 | expect(listener.onPatch).not.toBeCalled(); | 154 | expect(listener.onPatch).not.toBeCalled(); |
diff --git a/packages/preload/src/contextBridge/SophieRendererImpl.ts b/packages/preload/src/contextBridge/createSophieRenderer.ts index f3c07c5..2055080 100644 --- a/packages/preload/src/contextBridge/SophieRendererImpl.ts +++ b/packages/preload/src/contextBridge/createSophieRenderer.ts | |||
@@ -18,9 +18,6 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ipcRenderer } from 'electron'; | ||
22 | import log from 'loglevel'; | ||
23 | import type { IJsonPatch } from 'mobx-state-tree'; | ||
24 | import { | 21 | import { |
25 | Action, | 22 | Action, |
26 | action, | 23 | action, |
@@ -30,9 +27,12 @@ import { | |||
30 | SharedStoreListener, | 27 | SharedStoreListener, |
31 | SophieRenderer, | 28 | SophieRenderer, |
32 | } from '@sophie/shared'; | 29 | } from '@sophie/shared'; |
30 | import { ipcRenderer } from 'electron'; | ||
31 | import log from 'loglevel'; | ||
32 | import type { IJsonPatch } from 'mobx-state-tree'; | ||
33 | 33 | ||
34 | class SophieRendererImpl implements SophieRenderer { | 34 | class SharedStoreConnector { |
35 | private onSharedStoreChangeCalled: boolean = false; | 35 | private onSharedStoreChangeCalled = false; |
36 | 36 | ||
37 | private listener: SharedStoreListener | null = null; | 37 | private listener: SharedStoreListener | null = null; |
38 | 38 | ||
@@ -71,26 +71,26 @@ class SophieRendererImpl implements SophieRenderer { | |||
71 | } | 71 | } |
72 | throw new Error('Failed to connect to shared store'); | 72 | throw new Error('Failed to connect to shared store'); |
73 | } | 73 | } |
74 | } | ||
74 | 75 | ||
75 | dispatchAction(actionToDispatch: Action): void { | 76 | function dispatchAction(actionToDispatch: Action): void { |
76 | // Let the full zod parse error bubble up to the main world, | 77 | // Let the full zod parse error bubble up to the main world, |
77 | // since all data it may contain was provided from the main world. | 78 | // since all data it may contain was provided from the main world. |
78 | const parsedAction = action.parse(actionToDispatch); | 79 | const parsedAction = action.parse(actionToDispatch); |
79 | try { | 80 | try { |
80 | ipcRenderer.send(RendererToMainIpcMessage.DispatchAction, parsedAction); | 81 | ipcRenderer.send(RendererToMainIpcMessage.DispatchAction, parsedAction); |
81 | } catch (err) { | 82 | } catch (err) { |
82 | // Do not leak IPC failure details into the main world. | 83 | // Do not leak IPC failure details into the main world. |
83 | const message = 'Failed to dispatch action'; | 84 | const message = 'Failed to dispatch action'; |
84 | log.error(message, actionToDispatch, err); | 85 | log.error(message, actionToDispatch, err); |
85 | throw new Error(message); | 86 | throw new Error(message); |
86 | } | ||
87 | } | 87 | } |
88 | } | 88 | } |
89 | 89 | ||
90 | export function createSophieRenderer(allowReplaceListener: boolean): SophieRenderer { | 90 | export default function createSophieRenderer(allowReplaceListener: boolean): SophieRenderer { |
91 | const impl = new SophieRendererImpl(allowReplaceListener); | 91 | const connector = new SharedStoreConnector(allowReplaceListener); |
92 | return { | 92 | return { |
93 | onSharedStoreChange: impl.onSharedStoreChange.bind(impl), | 93 | onSharedStoreChange: connector.onSharedStoreChange.bind(connector), |
94 | dispatchAction: impl.dispatchAction.bind(impl), | 94 | dispatchAction, |
95 | }; | 95 | }; |
96 | } | 96 | } |
diff --git a/packages/preload/src/index.ts b/packages/preload/src/index.ts index de91742..f13220c 100644 --- a/packages/preload/src/index.ts +++ b/packages/preload/src/index.ts | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | import { contextBridge } from 'electron'; | 21 | import { contextBridge } from 'electron'; |
22 | 22 | ||
23 | import { createSophieRenderer } from './contextBridge/SophieRendererImpl'; | 23 | import createSophieRenderer from './contextBridge/createSophieRenderer'; |
24 | 24 | ||
25 | const isDevelopment = import.meta.env.MODE === 'development'; | 25 | const isDevelopment = import.meta.env.MODE === 'development'; |
26 | 26 | ||
diff --git a/packages/preload/tsconfig.json b/packages/preload/tsconfig.json index 741d435..ff49538 100644 --- a/packages/preload/tsconfig.json +++ b/packages/preload/tsconfig.json | |||
@@ -1,5 +1,5 @@ | |||
1 | { | 1 | { |
2 | "extends": "../../tsconfig.json", | 2 | "extends": "../../config/tsconfig.base.json", |
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "lib": [ | 5 | "lib": [ |
@@ -13,11 +13,13 @@ | |||
13 | }, | 13 | }, |
14 | "references": [ | 14 | "references": [ |
15 | { | 15 | { |
16 | "path": "../shared" | 16 | "path": "../shared/tsconfig.build.json" |
17 | } | 17 | } |
18 | ], | 18 | ], |
19 | "include": [ | 19 | "include": [ |
20 | "src/**/*.ts", | 20 | "src/**/*.ts", |
21 | "types/**/*.d.ts" | 21 | "types/**/*.d.ts", |
22 | "esbuild.config.js", | ||
23 | "jest.config.js" | ||
22 | ] | 24 | ] |
23 | } | 25 | } |