diff options
Diffstat (limited to 'packages')
48 files changed, 379 insertions, 377 deletions
diff --git a/packages/main/esbuild.config.js b/packages/main/esbuild.config.js index 49fba6b..d5f6f1e 100644 --- a/packages/main/esbuild.config.js +++ b/packages/main/esbuild.config.js | |||
@@ -12,19 +12,20 @@ if (process.env.MODE !== 'development') { | |||
12 | 12 | ||
13 | const gitInfo = getRepoInfo(); | 13 | const gitInfo = getRepoInfo(); |
14 | 14 | ||
15 | export default getEsbuildConfig({ | 15 | export default getEsbuildConfig( |
16 | absWorkingDir: fileURLToDirname(import.meta.url), | 16 | { |
17 | entryPoints: [ | 17 | absWorkingDir: fileURLToDirname(import.meta.url), |
18 | 'src/index.ts', | 18 | entryPoints: ['src/index.ts'], |
19 | ], | 19 | outfile: 'dist/index.cjs', |
20 | outfile: 'dist/index.cjs', | 20 | format: 'cjs', |
21 | format: 'cjs', | 21 | platform: 'node', |
22 | platform: 'node', | 22 | target: node, |
23 | target: node, | 23 | external: externalPackages, |
24 | external: externalPackages, | 24 | }, |
25 | }, { | 25 | { |
26 | VITE_DEV_SERVER_URL: process.env.VITE_DEV_SERVER_URL || null, | 26 | VITE_DEV_SERVER_URL: process.env.VITE_DEV_SERVER_URL || null, |
27 | GIT_SHA: gitInfo.abbreviatedSha, | 27 | GIT_SHA: gitInfo.abbreviatedSha, |
28 | GIT_BRANCH: gitInfo.branch, | 28 | GIT_BRANCH: gitInfo.branch, |
29 | BUILD_DATE: new Date().getTime(), | 29 | BUILD_DATE: new Date().getTime(), |
30 | }); | 30 | }, |
31 | ); | ||
diff --git a/packages/main/src/controllers/__tests__/initConfig.spec.ts b/packages/main/src/controllers/__tests__/initConfig.spec.ts index e386a07..7b6d6ab 100644 --- a/packages/main/src/controllers/__tests__/initConfig.spec.ts +++ b/packages/main/src/controllers/__tests__/initConfig.spec.ts | |||
@@ -60,8 +60,12 @@ describe('when initializing', () => { | |||
60 | }); | 60 | }); |
61 | 61 | ||
62 | it('should bail if there is an an error creating the config file', async () => { | 62 | it('should bail if there is an an error creating the config file', async () => { |
63 | mocked(persistenceService.writeConfig).mockRejectedValue(new Error('boo')); | 63 | mocked(persistenceService.writeConfig).mockRejectedValue( |
64 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 64 | new Error('boo'), |
65 | ); | ||
66 | await expect(() => | ||
67 | initConfig(config, persistenceService), | ||
68 | ).rejects.toBeInstanceOf(Error); | ||
65 | }); | 69 | }); |
66 | }); | 70 | }); |
67 | 71 | ||
@@ -85,7 +89,9 @@ describe('when initializing', () => { | |||
85 | mocked(persistenceService.watchConfig).mockImplementationOnce(() => { | 89 | mocked(persistenceService.watchConfig).mockImplementationOnce(() => { |
86 | throw new Error('boo'); | 90 | throw new Error('boo'); |
87 | }); | 91 | }); |
88 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 92 | await expect(() => |
93 | initConfig(config, persistenceService), | ||
94 | ).rejects.toBeInstanceOf(Error); | ||
89 | }); | 95 | }); |
90 | }); | 96 | }); |
91 | 97 | ||
@@ -102,7 +108,9 @@ describe('when initializing', () => { | |||
102 | 108 | ||
103 | it('should bail if it cannot determine whether there is a config file', async () => { | 109 | it('should bail if it cannot determine whether there is a config file', async () => { |
104 | mocked(persistenceService.readConfig).mockRejectedValue(new Error('boo')); | 110 | mocked(persistenceService.readConfig).mockRejectedValue(new Error('boo')); |
105 | await expect(() => initConfig(config, persistenceService)).rejects.toBeInstanceOf(Error); | 111 | await expect(() => |
112 | initConfig(config, persistenceService), | ||
113 | ).rejects.toBeInstanceOf(Error); | ||
106 | }); | 114 | }); |
107 | }); | 115 | }); |
108 | 116 | ||
@@ -118,7 +126,9 @@ describe('when it has loaded the config', () => { | |||
118 | }); | 126 | }); |
119 | mocked(persistenceService.watchConfig).mockReturnValueOnce(watcherDisposer); | 127 | mocked(persistenceService.watchConfig).mockReturnValueOnce(watcherDisposer); |
120 | sutDisposer = await initConfig(config, persistenceService, throttleMs); | 128 | sutDisposer = await initConfig(config, persistenceService, throttleMs); |
121 | [[configChangedCallback]] = mocked(persistenceService.watchConfig).mock.calls; | 129 | [[configChangedCallback]] = mocked( |
130 | persistenceService.watchConfig, | ||
131 | ).mock.calls; | ||
122 | jest.resetAllMocks(); | 132 | jest.resetAllMocks(); |
123 | }); | 133 | }); |
124 | 134 | ||
diff --git a/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts b/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts index bd33f48..d4068af 100644 --- a/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts +++ b/packages/main/src/controllers/__tests__/initNativeTheme.spec.ts | |||
@@ -58,14 +58,18 @@ it('should synchronize themeSource changes to the nativeTheme', () => { | |||
58 | }); | 58 | }); |
59 | 59 | ||
60 | it('should synchronize shouldUseDarkColors changes to the store', () => { | 60 | it('should synchronize shouldUseDarkColors changes to the store', () => { |
61 | const listener = mocked(nativeTheme.on).mock.calls.find(([event]) => event === 'updated')![1]; | 61 | const listener = mocked(nativeTheme.on).mock.calls.find( |
62 | ([event]) => event === 'updated', | ||
63 | )![1]; | ||
62 | shouldUseDarkColors = true; | 64 | shouldUseDarkColors = true; |
63 | listener(); | 65 | listener(); |
64 | expect(store.shared.shouldUseDarkColors).toBe(true); | 66 | expect(store.shared.shouldUseDarkColors).toBe(true); |
65 | }); | 67 | }); |
66 | 68 | ||
67 | it('should remove the listener on dispose', () => { | 69 | it('should remove the listener on dispose', () => { |
68 | const listener = mocked(nativeTheme.on).mock.calls.find(([event]) => event === 'updated')![1]; | 70 | const listener = mocked(nativeTheme.on).mock.calls.find( |
71 | ([event]) => event === 'updated', | ||
72 | )![1]; | ||
69 | disposeSut(); | 73 | disposeSut(); |
70 | expect(nativeTheme.off).toBeCalledWith('updated', listener); | 74 | expect(nativeTheme.off).toBeCalledWith('updated', listener); |
71 | }); | 75 | }); |
diff --git a/packages/main/src/controllers/initConfig.ts b/packages/main/src/controllers/initConfig.ts index 1d40762..e83b8da 100644 --- a/packages/main/src/controllers/initConfig.ts +++ b/packages/main/src/controllers/initConfig.ts | |||
@@ -59,20 +59,23 @@ export default async function initConfig( | |||
59 | lastSnapshotOnDisk = snapshot; | 59 | lastSnapshotOnDisk = snapshot; |
60 | } | 60 | } |
61 | 61 | ||
62 | if (!await readConfig()) { | 62 | if (!(await readConfig())) { |
63 | log.info('Config file was not found'); | 63 | log.info('Config file was not found'); |
64 | await writeConfig(); | 64 | await writeConfig(); |
65 | log.info('Created config file'); | 65 | log.info('Created config file'); |
66 | } | 66 | } |
67 | 67 | ||
68 | const disposeOnSnapshot = onSnapshot(config, debounce((snapshot) => { | 68 | const disposeOnSnapshot = onSnapshot( |
69 | // We can compare snapshots by reference, since it is only recreated on store changes. | 69 | config, |
70 | if (lastSnapshotOnDisk !== snapshot) { | 70 | debounce((snapshot) => { |
71 | writeConfig().catch((err) => { | 71 | // We can compare snapshots by reference, since it is only recreated on store changes. |
72 | log.error('Failed to write config on config change', err); | 72 | if (lastSnapshotOnDisk !== snapshot) { |
73 | }); | 73 | writeConfig().catch((err) => { |
74 | } | 74 | log.error('Failed to write config on config change', err); |
75 | }, debounceTime)); | 75 | }); |
76 | } | ||
77 | }, debounceTime), | ||
78 | ); | ||
76 | 79 | ||
77 | const disposeWatcher = persistenceService.watchConfig(async () => { | 80 | const disposeWatcher = persistenceService.watchConfig(async () => { |
78 | try { | 81 | try { |
diff --git a/packages/main/src/devTools.ts b/packages/main/src/devTools.ts index 0486c36..69f1514 100644 --- a/packages/main/src/devTools.ts +++ b/packages/main/src/devTools.ts | |||
@@ -52,18 +52,12 @@ export async function installDevToolsExtensions(): Promise<void> { | |||
52 | @typescript-eslint/no-var-requires | 52 | @typescript-eslint/no-var-requires |
53 | */ | 53 | */ |
54 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); | 54 | } = require('electron-devtools-installer') as typeof import('electron-devtools-installer'); |
55 | await installExtension( | 55 | await installExtension([REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS], { |
56 | [ | 56 | forceDownload: false, |
57 | REACT_DEVELOPER_TOOLS, | 57 | loadExtensionOptions: { |
58 | REDUX_DEVTOOLS, | 58 | allowFileAccess: true, |
59 | ], | ||
60 | { | ||
61 | forceDownload: false, | ||
62 | loadExtensionOptions: { | ||
63 | allowFileAccess: true, | ||
64 | }, | ||
65 | }, | 59 | }, |
66 | ); | 60 | }); |
67 | } | 61 | } |
68 | 62 | ||
69 | /** | 63 | /** |
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index bc10b4c..1f80e44 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts | |||
@@ -33,12 +33,7 @@ import { | |||
33 | MainToRendererIpcMessage, | 33 | MainToRendererIpcMessage, |
34 | RendererToMainIpcMessage, | 34 | RendererToMainIpcMessage, |
35 | } from '@sophie/shared'; | 35 | } from '@sophie/shared'; |
36 | import { | 36 | import { app, BrowserView, BrowserWindow, ipcMain } from 'electron'; |
37 | app, | ||
38 | BrowserView, | ||
39 | BrowserWindow, | ||
40 | ipcMain, | ||
41 | } from 'electron'; | ||
42 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; | 37 | import { ensureDirSync, readFile, readFileSync } from 'fs-extra'; |
43 | import { autorun } from 'mobx'; | 38 | import { autorun } from 'mobx'; |
44 | import { getSnapshot, onPatch } from 'mobx-state-tree'; | 39 | import { getSnapshot, onPatch } from 'mobx-state-tree'; |
@@ -97,7 +92,9 @@ app.setAboutPanelOptions({ | |||
97 | `Node.js: ${process.versions.node}`, | 92 | `Node.js: ${process.versions.node}`, |
98 | `Platform: ${osName()}`, | 93 | `Platform: ${osName()}`, |
99 | `Arch: ${arch()}`, | 94 | `Arch: ${arch()}`, |
100 | `Build date: ${new Date(Number(import.meta.env.BUILD_DATE)).toLocaleString()}`, | 95 | `Build date: ${new Date( |
96 | Number(import.meta.env.BUILD_DATE), | ||
97 | ).toLocaleString()}`, | ||
101 | `Git SHA: ${import.meta.env.GIT_SHA}`, | 98 | `Git SHA: ${import.meta.env.GIT_SHA}`, |
102 | `Git branch: ${import.meta.env.GIT_BRANCH}`, | 99 | `Git branch: ${import.meta.env.GIT_BRANCH}`, |
103 | ].join('\n'), | 100 | ].join('\n'), |
@@ -123,11 +120,13 @@ const serviceInject: WebSource = { | |||
123 | let mainWindow: BrowserWindow | null = null; | 120 | let mainWindow: BrowserWindow | null = null; |
124 | 121 | ||
125 | const store = createMainStore(); | 122 | const store = createMainStore(); |
126 | init(store).then((disposeCompositionRoot) => { | 123 | init(store) |
127 | app.on('will-quit', disposeCompositionRoot); | 124 | .then((disposeCompositionRoot) => { |
128 | }).catch((err) => { | 125 | app.on('will-quit', disposeCompositionRoot); |
129 | log.log('Failed to initialize application', err); | 126 | }) |
130 | }); | 127 | .catch((err) => { |
128 | log.log('Failed to initialize application', err); | ||
129 | }); | ||
131 | 130 | ||
132 | const rendererBaseUrl = getResourceUrl('../renderer/'); | 131 | const rendererBaseUrl = getResourceUrl('../renderer/'); |
133 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { | 132 | function shouldCancelMainWindowRequest(url: string, method: string): boolean { |
@@ -141,12 +140,20 @@ function shouldCancelMainWindowRequest(url: string, method: string): boolean { | |||
141 | return true; | 140 | return true; |
142 | } | 141 | } |
143 | if (isDevelopment) { | 142 | if (isDevelopment) { |
144 | if (DEVMODE_ALLOWED_URL_PREFIXES.some((prefix) => normalizedUrl.startsWith(prefix))) { | 143 | if ( |
144 | DEVMODE_ALLOWED_URL_PREFIXES.some((prefix) => | ||
145 | normalizedUrl.startsWith(prefix), | ||
146 | ) | ||
147 | ) { | ||
145 | return false; | 148 | return false; |
146 | } | 149 | } |
147 | if (import.meta.env.VITE_DEV_SERVER_URL !== undefined) { | 150 | if (import.meta.env.VITE_DEV_SERVER_URL !== undefined) { |
148 | const isHttp = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL); | 151 | const isHttp = normalizedUrl.startsWith( |
149 | const isWs = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL.replace(/^http:/, 'ws:')); | 152 | import.meta.env.VITE_DEV_SERVER_URL, |
153 | ); | ||
154 | const isWs = normalizedUrl.startsWith( | ||
155 | import.meta.env.VITE_DEV_SERVER_URL.replace(/^http:/, 'ws:'), | ||
156 | ); | ||
150 | return !isHttp && !isWs; | 157 | return !isHttp && !isWs; |
151 | } | 158 | } |
152 | } | 159 | } |
@@ -168,19 +175,24 @@ async function createWindow(): Promise<unknown> { | |||
168 | 175 | ||
169 | webContents.userAgent = originalUserAgent; | 176 | webContents.userAgent = originalUserAgent; |
170 | 177 | ||
171 | webContents.session.setPermissionRequestHandler((_webContents, _permission, callback) => { | 178 | webContents.session.setPermissionRequestHandler( |
172 | callback(false); | 179 | (_webContents, _permission, callback) => { |
173 | }); | 180 | callback(false); |
181 | }, | ||
182 | ); | ||
174 | 183 | ||
175 | webContents.session.webRequest.onBeforeRequest(({ url, method }, callback) => { | 184 | webContents.session.webRequest.onBeforeRequest( |
176 | callback({ | 185 | ({ url, method }, callback) => { |
177 | cancel: shouldCancelMainWindowRequest(url, method), | 186 | callback({ |
178 | }); | 187 | cancel: shouldCancelMainWindowRequest(url, method), |
179 | }); | 188 | }); |
189 | }, | ||
190 | ); | ||
180 | 191 | ||
181 | const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined) | 192 | const pageUrl = |
182 | ? import.meta.env.VITE_DEV_SERVER_URL | 193 | isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined |
183 | : getResourceUrl('../renderer/dist/index.html'); | 194 | ? import.meta.env.VITE_DEV_SERVER_URL |
195 | : getResourceUrl('../renderer/dist/index.html'); | ||
184 | 196 | ||
185 | webContents.on('will-navigate', (event, url) => { | 197 | webContents.on('will-navigate', (event, url) => { |
186 | if (url !== pageUrl) { | 198 | if (url !== pageUrl) { |
@@ -273,9 +285,8 @@ async function createWindow(): Promise<unknown> { | |||
273 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); | 285 | webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch); |
274 | }); | 286 | }); |
275 | 287 | ||
276 | ipcMain.handle( | 288 | ipcMain.handle(ServiceToMainIpcMessage.ApiExposedInMainWorld, (event) => |
277 | ServiceToMainIpcMessage.ApiExposedInMainWorld, | 289 | event.sender.id === browserView.webContents.id ? serviceInject : null, |
278 | (event) => (event.sender.id === browserView.webContents.id ? serviceInject : null), | ||
279 | ); | 290 | ); |
280 | 291 | ||
281 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { | 292 | browserView.webContents.on('ipc-message', (_event, channel, ...args) => { |
@@ -305,7 +316,9 @@ async function createWindow(): Promise<unknown> { | |||
305 | 316 | ||
306 | browserView.webContents.session.webRequest.onBeforeSendHeaders( | 317 | browserView.webContents.session.webRequest.onBeforeSendHeaders( |
307 | ({ url, requestHeaders }, callback) => { | 318 | ({ url, requestHeaders }, callback) => { |
308 | const requestUserAgent = url.match(/^[^:]+:\/\/accounts\.google\.[^./]+\//) | 319 | const requestUserAgent = url.match( |
320 | /^[^:]+:\/\/accounts\.google\.[^./]+\//, | ||
321 | ) | ||
309 | ? chromelessUserAgent | 322 | ? chromelessUserAgent |
310 | : userAgent; | 323 | : userAgent; |
311 | callback({ | 324 | callback({ |
@@ -317,9 +330,11 @@ async function createWindow(): Promise<unknown> { | |||
317 | }, | 330 | }, |
318 | ); | 331 | ); |
319 | 332 | ||
320 | browserView.webContents.loadURL('https://gitlab.com/say-hi-to-sophie/sophie').catch((err) => { | 333 | browserView.webContents |
321 | log.error('Failed to load browser', err); | 334 | .loadURL('https://gitlab.com/say-hi-to-sophie/sophie') |
322 | }); | 335 | .catch((err) => { |
336 | log.error('Failed to load browser', err); | ||
337 | }); | ||
323 | 338 | ||
324 | return mainWindow.loadURL(pageUrl); | 339 | return mainWindow.loadURL(pageUrl); |
325 | } | 340 | } |
@@ -342,17 +357,20 @@ app.on('window-all-closed', () => { | |||
342 | } | 357 | } |
343 | }); | 358 | }); |
344 | 359 | ||
345 | app.whenReady().then(async () => { | 360 | app |
346 | if (isDevelopment) { | 361 | .whenReady() |
347 | try { | 362 | .then(async () => { |
348 | await installDevToolsExtensions(); | 363 | if (isDevelopment) { |
349 | } catch (err) { | 364 | try { |
350 | log.error('Failed to install devtools extensions', err); | 365 | await installDevToolsExtensions(); |
366 | } catch (err) { | ||
367 | log.error('Failed to install devtools extensions', err); | ||
368 | } | ||
351 | } | 369 | } |
352 | } | ||
353 | 370 | ||
354 | return createWindow(); | 371 | return createWindow(); |
355 | }).catch((err) => { | 372 | }) |
356 | log.error('Failed to create window', err); | 373 | .catch((err) => { |
357 | process.exit(1); | 374 | log.error('Failed to create window', err); |
358 | }); | 375 | process.exit(1); |
376 | }); | ||
diff --git a/packages/main/src/init.ts b/packages/main/src/init.ts index 4487cc4..f3794bb 100644 --- a/packages/main/src/init.ts +++ b/packages/main/src/init.ts | |||
@@ -27,8 +27,13 @@ import { MainStore } from './stores/MainStore'; | |||
27 | import type Disposer from './utils/Disposer'; | 27 | import type Disposer from './utils/Disposer'; |
28 | 28 | ||
29 | export default async function init(store: MainStore): Promise<Disposer> { | 29 | export default async function init(store: MainStore): Promise<Disposer> { |
30 | const configPersistenceService = new ConfigPersistenceServiceImpl(app.getPath('userData')); | 30 | const configPersistenceService = new ConfigPersistenceServiceImpl( |
31 | const disposeConfigController = await initConfig(store.config, configPersistenceService); | 31 | app.getPath('userData'), |
32 | ); | ||
33 | const disposeConfigController = await initConfig( | ||
34 | store.config, | ||
35 | configPersistenceService, | ||
36 | ); | ||
32 | const disposeNativeThemeController = initNativeTheme(store); | 37 | const disposeNativeThemeController = initNativeTheme(store); |
33 | 38 | ||
34 | return () => { | 39 | return () => { |
diff --git a/packages/main/src/services/ConfigPersistenceService.ts b/packages/main/src/services/ConfigPersistenceService.ts index 7d508c5..ee5696d 100644 --- a/packages/main/src/services/ConfigPersistenceService.ts +++ b/packages/main/src/services/ConfigPersistenceService.ts | |||
@@ -21,7 +21,9 @@ | |||
21 | import type { ConfigSnapshotOut } from '../stores/Config'; | 21 | import type { ConfigSnapshotOut } from '../stores/Config'; |
22 | import type Disposer from '../utils/Disposer'; | 22 | import type Disposer from '../utils/Disposer'; |
23 | 23 | ||
24 | export type ReadConfigResult = { found: true; data: unknown; } | { found: false; }; | 24 | export type ReadConfigResult = |
25 | | { found: true; data: unknown } | ||
26 | | { found: false }; | ||
25 | 27 | ||
26 | export default interface ConfigPersistenceService { | 28 | export default interface ConfigPersistenceService { |
27 | readConfig(): Promise<ReadConfigResult>; | 29 | readConfig(): Promise<ReadConfigResult>; |
diff --git a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts index df8c807..e92f706 100644 --- a/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts +++ b/packages/main/src/services/impl/ConfigPersistenceServiceImpl.ts | |||
@@ -32,7 +32,9 @@ import type { ReadConfigResult } from '../ConfigPersistenceService'; | |||
32 | 32 | ||
33 | const log = getLogger('configPersistence'); | 33 | const log = getLogger('configPersistence'); |
34 | 34 | ||
35 | export default class ConfigPersistenceServiceImpl implements ConfigPersistenceService { | 35 | export default class ConfigPersistenceServiceImpl |
36 | implements ConfigPersistenceService | ||
37 | { | ||
36 | private readonly configFilePath: string; | 38 | private readonly configFilePath: string; |
37 | 39 | ||
38 | private writingConfig = false; | 40 | private writingConfig = false; |
@@ -92,13 +94,19 @@ export default class ConfigPersistenceServiceImpl implements ConfigPersistenceSe | |||
92 | log.trace('Config file last modified at', mtime); | 94 | log.trace('Config file last modified at', mtime); |
93 | } catch (err) { | 95 | } catch (err) { |
94 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { | 96 | if ((err as NodeJS.ErrnoException).code === 'ENOENT') { |
95 | log.debug('Config file', this.configFilePath, 'was deleted after being changed'); | 97 | log.debug( |
98 | 'Config file', | ||
99 | this.configFilePath, | ||
100 | 'was deleted after being changed', | ||
101 | ); | ||
96 | return; | 102 | return; |
97 | } | 103 | } |
98 | throw err; | 104 | throw err; |
99 | } | 105 | } |
100 | if (!this.writingConfig | 106 | if ( |
101 | && (this.timeLastWritten === null || mtime > this.timeLastWritten)) { | 107 | !this.writingConfig && |
108 | (this.timeLastWritten === null || mtime > this.timeLastWritten) | ||
109 | ) { | ||
102 | log.debug( | 110 | log.debug( |
103 | 'Found a config file modified at', | 111 | 'Found a config file modified at', |
104 | mtime, | 112 | mtime, |
@@ -114,8 +122,10 @@ export default class ConfigPersistenceServiceImpl implements ConfigPersistenceSe | |||
114 | }); | 122 | }); |
115 | 123 | ||
116 | watcher.on('change', (eventType, filename) => { | 124 | watcher.on('change', (eventType, filename) => { |
117 | if (eventType === 'change' | 125 | if ( |
118 | && (filename === this.configFileName || filename === null)) { | 126 | eventType === 'change' && |
127 | (filename === this.configFileName || filename === null) | ||
128 | ) { | ||
119 | configChanged()?.catch((err) => { | 129 | configChanged()?.catch((err) => { |
120 | log.error('Unhandled error while listening for config changes', err); | 130 | log.error('Unhandled error while listening for config changes', err); |
121 | }); | 131 | }); |
diff --git a/packages/main/src/stores/MainStore.ts b/packages/main/src/stores/MainStore.ts index 7b26c52..eaf5b3c 100644 --- a/packages/main/src/stores/MainStore.ts +++ b/packages/main/src/stores/MainStore.ts | |||
@@ -24,26 +24,32 @@ import { applySnapshot, Instance, types } from 'mobx-state-tree'; | |||
24 | import type { Config } from './Config.js'; | 24 | import type { Config } from './Config.js'; |
25 | import { sharedStore } from './SharedStore'; | 25 | import { sharedStore } from './SharedStore'; |
26 | 26 | ||
27 | export const mainStore = types.model('MainStore', { | 27 | export const mainStore = types |
28 | browserViewBounds: types.optional(types.model('BrowserViewBounds', { | 28 | .model('MainStore', { |
29 | x: 0, | 29 | browserViewBounds: types.optional( |
30 | y: 0, | 30 | types.model('BrowserViewBounds', { |
31 | width: 0, | 31 | x: 0, |
32 | height: 0, | 32 | y: 0, |
33 | }), {}), | 33 | width: 0, |
34 | shared: types.optional(sharedStore, {}), | 34 | height: 0, |
35 | }).views((self) => ({ | 35 | }), |
36 | get config(): Config { | 36 | {}, |
37 | return self.shared.config; | 37 | ), |
38 | }, | 38 | shared: types.optional(sharedStore, {}), |
39 | })).actions((self) => ({ | 39 | }) |
40 | setBrowserViewBounds(bounds: BrowserViewBounds): void { | 40 | .views((self) => ({ |
41 | applySnapshot(self.browserViewBounds, bounds); | 41 | get config(): Config { |
42 | }, | 42 | return self.shared.config; |
43 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { | 43 | }, |
44 | self.shared.shouldUseDarkColors = shouldUseDarkColors; | 44 | })) |
45 | }, | 45 | .actions((self) => ({ |
46 | })); | 46 | setBrowserViewBounds(bounds: BrowserViewBounds): void { |
47 | applySnapshot(self.browserViewBounds, bounds); | ||
48 | }, | ||
49 | setShouldUseDarkColors(shouldUseDarkColors: boolean): void { | ||
50 | self.shared.shouldUseDarkColors = shouldUseDarkColors; | ||
51 | }, | ||
52 | })); | ||
47 | 53 | ||
48 | export interface MainStore extends Instance<typeof mainStore> {} | 54 | export interface MainStore extends Instance<typeof mainStore> {} |
49 | 55 | ||
diff --git a/packages/main/src/stores/SharedStore.ts b/packages/main/src/stores/SharedStore.ts index c023fc7..73245cd 100644 --- a/packages/main/src/stores/SharedStore.ts +++ b/packages/main/src/stores/SharedStore.ts | |||
@@ -23,7 +23,10 @@ import { Instance, types } from 'mobx-state-tree'; | |||
23 | 23 | ||
24 | import { config } from './Config'; | 24 | import { config } from './Config'; |
25 | 25 | ||
26 | export type { SharedStoreSnapshotIn, SharedStoreSnapshotOut } from '@sophie/shared'; | 26 | export type { |
27 | SharedStoreSnapshotIn, | ||
28 | SharedStoreSnapshotOut, | ||
29 | } from '@sophie/shared'; | ||
27 | 30 | ||
28 | export const sharedStore = originalSharedStore.props({ | 31 | export const sharedStore = originalSharedStore.props({ |
29 | config: types.optional(config, {}), | 32 | config: types.optional(config, {}), |
diff --git a/packages/main/src/utils/log.ts b/packages/main/src/utils/log.ts index c704797..5218721 100644 --- a/packages/main/src/utils/log.ts +++ b/packages/main/src/utils/log.ts | |||
@@ -46,9 +46,10 @@ prefix.apply(loglevel, { | |||
46 | format(level, name, timestamp) { | 46 | format(level, name, timestamp) { |
47 | const levelColor = getColor(level); | 47 | const levelColor = getColor(level); |
48 | const timeStr = timestamp.toString(); | 48 | const timeStr = timestamp.toString(); |
49 | const nameStr = typeof name === 'undefined' | 49 | const nameStr = |
50 | ? levelColor(':') | 50 | typeof name === 'undefined' |
51 | : ` ${chalk.green(`${name}:`)}`; | 51 | ? levelColor(':') |
52 | : ` ${chalk.green(`${name}:`)}`; | ||
52 | return `${chalk.gray(`[${timeStr}]`)} ${levelColor(level)}${nameStr}`; | 53 | return `${chalk.gray(`[${timeStr}]`)} ${levelColor(level)}${nameStr}`; |
53 | }, | 54 | }, |
54 | }); | 55 | }); |
diff --git a/packages/main/tsconfig.json b/packages/main/tsconfig.json index bdf68f4..dad597d 100644 --- a/packages/main/tsconfig.json +++ b/packages/main/tsconfig.json | |||
@@ -2,10 +2,7 @@ | |||
2 | "extends": "../../config/tsconfig.base.json", | 2 | "extends": "../../config/tsconfig.base.json", |
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "types": [ | 5 | "types": ["@types/jest", "node"] |
6 | "@types/jest", | ||
7 | "node" | ||
8 | ] | ||
9 | }, | 6 | }, |
10 | "references": [ | 7 | "references": [ |
11 | { | 8 | { |
diff --git a/packages/main/types/importMeta.d.ts b/packages/main/types/importMeta.d.ts index e422c30..efcf48a 100644 --- a/packages/main/types/importMeta.d.ts +++ b/packages/main/types/importMeta.d.ts | |||
@@ -7,5 +7,5 @@ interface ImportMeta { | |||
7 | GIT_SHA: string; | 7 | GIT_SHA: string; |
8 | GIT_BRANCH: string; | 8 | GIT_BRANCH: string; |
9 | BUILD_DATE: number; | 9 | BUILD_DATE: number; |
10 | } | 10 | }; |
11 | } | 11 | } |
diff --git a/packages/preload/esbuild.config.js b/packages/preload/esbuild.config.js index 66f5e84..d888987 100644 --- a/packages/preload/esbuild.config.js +++ b/packages/preload/esbuild.config.js | |||
@@ -4,15 +4,11 @@ import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | |||
4 | 4 | ||
5 | export default getEsbuildConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: ['src/index.ts'], |
8 | 'src/index.ts', | ||
9 | ], | ||
10 | outfile: 'dist/index.cjs', | 8 | outfile: 'dist/index.cjs', |
11 | format: 'cjs', | 9 | format: 'cjs', |
12 | platform: 'node', | 10 | platform: 'node', |
13 | target: chrome, | 11 | target: chrome, |
14 | sourcemap: 'inline', | 12 | sourcemap: 'inline', |
15 | external: [ | 13 | external: ['electron'], |
16 | 'electron', | ||
17 | ], | ||
18 | }); | 14 | }); |
diff --git a/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts b/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts index a38dbac..f63c3f6 100644 --- a/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts +++ b/packages/preload/src/contextBridge/__tests__/createSophieRenderer.spec.ts | |||
@@ -40,9 +40,12 @@ jest.unstable_mockModule('electron', () => ({ | |||
40 | 40 | ||
41 | const { ipcRenderer } = await import('electron'); | 41 | const { ipcRenderer } = await import('electron'); |
42 | 42 | ||
43 | const { default: createSophieRenderer } = await import('../createSophieRenderer'); | 43 | const { default: createSophieRenderer } = await import( |
44 | '../createSophieRenderer' | ||
45 | ); | ||
44 | 46 | ||
45 | const event: Electron.IpcRendererEvent = null as unknown as Electron.IpcRendererEvent; | 47 | const event: Electron.IpcRendererEvent = |
48 | null as unknown as Electron.IpcRendererEvent; | ||
46 | 49 | ||
47 | const snapshot: SharedStoreSnapshotIn = { | 50 | const snapshot: SharedStoreSnapshotIn = { |
48 | shouldUseDarkColors: true, | 51 | shouldUseDarkColors: true, |
@@ -83,7 +86,10 @@ describe('createSophieRenderer', () => { | |||
83 | 86 | ||
84 | describe('SharedStoreConnector', () => { | 87 | describe('SharedStoreConnector', () => { |
85 | let sut: SophieRenderer; | 88 | let sut: SophieRenderer; |
86 | let onSharedStorePatch: (eventArg: Electron.IpcRendererEvent, patchArg: unknown) => void; | 89 | let onSharedStorePatch: ( |
90 | eventArg: Electron.IpcRendererEvent, | ||
91 | patchArg: unknown, | ||
92 | ) => void; | ||
87 | const listener = { | 93 | const listener = { |
88 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars | 94 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars |
89 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => {}), | 95 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => {}), |
@@ -102,22 +108,25 @@ describe('SharedStoreConnector', () => { | |||
102 | it('should request a snapshot from the main process', async () => { | 108 | it('should request a snapshot from the main process', async () => { |
103 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); | 109 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); |
104 | await sut.onSharedStoreChange(listener); | 110 | await sut.onSharedStoreChange(listener); |
105 | expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot); | 111 | expect(ipcRenderer.invoke).toBeCalledWith( |
112 | RendererToMainIpcMessage.GetSharedStoreSnapshot, | ||
113 | ); | ||
106 | expect(listener.onSnapshot).toBeCalledWith(snapshot); | 114 | expect(listener.onSnapshot).toBeCalledWith(snapshot); |
107 | }); | 115 | }); |
108 | 116 | ||
109 | it('should catch IPC errors without exposing them', async () => { | 117 | it('should catch IPC errors without exposing them', async () => { |
110 | mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t')); | 118 | mocked(ipcRenderer.invoke).mockRejectedValue(new Error('s3cr3t')); |
111 | await expect(sut.onSharedStoreChange(listener)).rejects.not.toHaveProperty( | 119 | await expect( |
112 | 'message', | 120 | sut.onSharedStoreChange(listener), |
113 | expect.stringMatching(/s3cr3t/), | 121 | ).rejects.not.toHaveProperty('message', expect.stringMatching(/s3cr3t/)); |
114 | ); | ||
115 | expect(listener.onSnapshot).not.toBeCalled(); | 122 | expect(listener.onSnapshot).not.toBeCalled(); |
116 | }); | 123 | }); |
117 | 124 | ||
118 | it('should not pass on invalid snapshots', async () => { | 125 | it('should not pass on invalid snapshots', async () => { |
119 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(invalidSnapshot); | 126 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(invalidSnapshot); |
120 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); | 127 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf( |
128 | Error, | ||
129 | ); | ||
121 | expect(listener.onSnapshot).not.toBeCalled(); | 130 | expect(listener.onSnapshot).not.toBeCalled(); |
122 | }); | 131 | }); |
123 | }); | 132 | }); |
@@ -125,7 +134,10 @@ describe('SharedStoreConnector', () => { | |||
125 | describe('dispatchAction', () => { | 134 | describe('dispatchAction', () => { |
126 | it('should dispatch valid actions', () => { | 135 | it('should dispatch valid actions', () => { |
127 | sut.dispatchAction(action); | 136 | sut.dispatchAction(action); |
128 | expect(ipcRenderer.send).toBeCalledWith(RendererToMainIpcMessage.DispatchAction, action); | 137 | expect(ipcRenderer.send).toBeCalledWith( |
138 | RendererToMainIpcMessage.DispatchAction, | ||
139 | action, | ||
140 | ); | ||
129 | }); | 141 | }); |
130 | 142 | ||
131 | it('should not dispatch invalid actions', () => { | 143 | it('should not dispatch invalid actions', () => { |
@@ -142,7 +154,9 @@ describe('SharedStoreConnector', () => { | |||
142 | 154 | ||
143 | function itRefusesToRegisterAnotherListener(): void { | 155 | function itRefusesToRegisterAnotherListener(): void { |
144 | it('should refuse to register another listener', async () => { | 156 | it('should refuse to register another listener', async () => { |
145 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf(Error); | 157 | await expect(sut.onSharedStoreChange(listener)).rejects.toBeInstanceOf( |
158 | Error, | ||
159 | ); | ||
146 | }); | 160 | }); |
147 | } | 161 | } |
148 | 162 | ||
@@ -167,7 +181,9 @@ describe('SharedStoreConnector', () => { | |||
167 | }); | 181 | }); |
168 | 182 | ||
169 | it('should catch listener errors', () => { | 183 | it('should catch listener errors', () => { |
170 | mocked(listener.onPatch).mockImplementation(() => { throw new Error(); }); | 184 | mocked(listener.onPatch).mockImplementation(() => { |
185 | throw new Error(); | ||
186 | }); | ||
171 | onSharedStorePatch(event, patch); | 187 | onSharedStorePatch(event, patch); |
172 | }); | 188 | }); |
173 | 189 | ||
@@ -175,7 +191,9 @@ describe('SharedStoreConnector', () => { | |||
175 | 191 | ||
176 | describe('after the listener threw in onPatch', () => { | 192 | describe('after the listener threw in onPatch', () => { |
177 | beforeEach(() => { | 193 | beforeEach(() => { |
178 | mocked(listener.onPatch).mockImplementation(() => { throw new Error(); }); | 194 | mocked(listener.onPatch).mockImplementation(() => { |
195 | throw new Error(); | ||
196 | }); | ||
179 | onSharedStorePatch(event, patch); | 197 | onSharedStorePatch(event, patch); |
180 | listener.onPatch.mockRestore(); | 198 | listener.onPatch.mockRestore(); |
181 | }); | 199 | }); |
@@ -217,7 +235,9 @@ describe('SharedStoreConnector', () => { | |||
217 | describe('when a listener failed to register due to listener error', () => { | 235 | describe('when a listener failed to register due to listener error', () => { |
218 | beforeEach(async () => { | 236 | beforeEach(async () => { |
219 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); | 237 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot); |
220 | mocked(listener.onSnapshot).mockImplementation(() => { throw new Error(); }); | 238 | mocked(listener.onSnapshot).mockImplementation(() => { |
239 | throw new Error(); | ||
240 | }); | ||
221 | try { | 241 | try { |
222 | await sut.onSharedStoreChange(listener); | 242 | await sut.onSharedStoreChange(listener); |
223 | } catch { | 243 | } catch { |
@@ -236,15 +256,17 @@ describe('SharedStoreConnector', () => { | |||
236 | }; | 256 | }; |
237 | const listener2 = { | 257 | const listener2 = { |
238 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars | 258 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars |
239 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => { }), | 259 | onSnapshot: jest.fn((_snapshot: SharedStoreSnapshotIn) => {}), |
240 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars | 260 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars |
241 | onPatch: jest.fn((_patch: IJsonPatch) => { }), | 261 | onPatch: jest.fn((_patch: IJsonPatch) => {}), |
242 | }; | 262 | }; |
243 | 263 | ||
244 | it('should fetch a second snapshot', async () => { | 264 | it('should fetch a second snapshot', async () => { |
245 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot2); | 265 | mocked(ipcRenderer.invoke).mockResolvedValueOnce(snapshot2); |
246 | await sut.onSharedStoreChange(listener2); | 266 | await sut.onSharedStoreChange(listener2); |
247 | expect(ipcRenderer.invoke).toBeCalledWith(RendererToMainIpcMessage.GetSharedStoreSnapshot); | 267 | expect(ipcRenderer.invoke).toBeCalledWith( |
268 | RendererToMainIpcMessage.GetSharedStoreSnapshot, | ||
269 | ); | ||
248 | expect(listener2.onSnapshot).toBeCalledWith(snapshot2); | 270 | expect(listener2.onSnapshot).toBeCalledWith(snapshot2); |
249 | }); | 271 | }); |
250 | 272 | ||
diff --git a/packages/preload/src/contextBridge/createSophieRenderer.ts b/packages/preload/src/contextBridge/createSophieRenderer.ts index 2055080..b97503d 100644 --- a/packages/preload/src/contextBridge/createSophieRenderer.ts +++ b/packages/preload/src/contextBridge/createSophieRenderer.ts | |||
@@ -37,15 +37,18 @@ class SharedStoreConnector { | |||
37 | private listener: SharedStoreListener | null = null; | 37 | private listener: SharedStoreListener | null = null; |
38 | 38 | ||
39 | constructor(private readonly allowReplaceListener: boolean) { | 39 | constructor(private readonly allowReplaceListener: boolean) { |
40 | ipcRenderer.on(MainToRendererIpcMessage.SharedStorePatch, (_event, patch) => { | 40 | ipcRenderer.on( |
41 | try { | 41 | MainToRendererIpcMessage.SharedStorePatch, |
42 | // `mobx-state-tree` will validate the patch, so we can safely cast here. | 42 | (_event, patch) => { |
43 | this.listener?.onPatch(patch as IJsonPatch); | 43 | try { |
44 | } catch (err) { | 44 | // `mobx-state-tree` will validate the patch, so we can safely cast here. |
45 | log.error('Shared store listener onPatch failed', err); | 45 | this.listener?.onPatch(patch as IJsonPatch); |
46 | this.listener = null; | 46 | } catch (err) { |
47 | } | 47 | log.error('Shared store listener onPatch failed', err); |
48 | }); | 48 | this.listener = null; |
49 | } | ||
50 | }, | ||
51 | ); | ||
49 | } | 52 | } |
50 | 53 | ||
51 | async onSharedStoreChange(listener: SharedStoreListener): Promise<void> { | 54 | async onSharedStoreChange(listener: SharedStoreListener): Promise<void> { |
@@ -56,7 +59,9 @@ class SharedStoreConnector { | |||
56 | let success = false; | 59 | let success = false; |
57 | let snapshot: unknown | null = null; | 60 | let snapshot: unknown | null = null; |
58 | try { | 61 | try { |
59 | snapshot = await ipcRenderer.invoke(RendererToMainIpcMessage.GetSharedStoreSnapshot); | 62 | snapshot = await ipcRenderer.invoke( |
63 | RendererToMainIpcMessage.GetSharedStoreSnapshot, | ||
64 | ); | ||
60 | success = true; | 65 | success = true; |
61 | } catch (err) { | 66 | } catch (err) { |
62 | log.error('Failed to get initial shared store snapshot', err); | 67 | log.error('Failed to get initial shared store snapshot', err); |
@@ -87,7 +92,9 @@ function dispatchAction(actionToDispatch: Action): void { | |||
87 | } | 92 | } |
88 | } | 93 | } |
89 | 94 | ||
90 | export default function createSophieRenderer(allowReplaceListener: boolean): SophieRenderer { | 95 | export default function createSophieRenderer( |
96 | allowReplaceListener: boolean, | ||
97 | ): SophieRenderer { | ||
91 | const connector = new SharedStoreConnector(allowReplaceListener); | 98 | const connector = new SharedStoreConnector(allowReplaceListener); |
92 | return { | 99 | return { |
93 | onSharedStoreChange: connector.onSharedStoreChange.bind(connector), | 100 | onSharedStoreChange: connector.onSharedStoreChange.bind(connector), |
diff --git a/packages/preload/tsconfig.json b/packages/preload/tsconfig.json index 0cb1390..18c72b4 100644 --- a/packages/preload/tsconfig.json +++ b/packages/preload/tsconfig.json | |||
@@ -2,14 +2,8 @@ | |||
2 | "extends": "../../config/tsconfig.base.json", | 2 | "extends": "../../config/tsconfig.base.json", |
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "lib": [ | 5 | "lib": ["dom", "dom.iterable", "esnext"], |
6 | "dom", | 6 | "types": ["@types/jest"] |
7 | "dom.iterable", | ||
8 | "esnext" | ||
9 | ], | ||
10 | "types": [ | ||
11 | "@types/jest" | ||
12 | ] | ||
13 | }, | 7 | }, |
14 | "references": [ | 8 | "references": [ |
15 | { | 9 | { |
diff --git a/packages/preload/types/importMeta.d.ts b/packages/preload/types/importMeta.d.ts index 9b73170..ff3b17c 100644 --- a/packages/preload/types/importMeta.d.ts +++ b/packages/preload/types/importMeta.d.ts | |||
@@ -3,5 +3,5 @@ interface ImportMeta { | |||
3 | DEV: boolean; | 3 | DEV: boolean; |
4 | MODE: string; | 4 | MODE: string; |
5 | PROD: boolean; | 5 | PROD: boolean; |
6 | } | 6 | }; |
7 | } | 7 | } |
diff --git a/packages/renderer/.eslinrc.cjs b/packages/renderer/.eslinrc.cjs index 37d27ad..ee3cca6 100644 --- a/packages/renderer/.eslinrc.cjs +++ b/packages/renderer/.eslinrc.cjs | |||
@@ -5,10 +5,7 @@ module.exports = { | |||
5 | }, | 5 | }, |
6 | overrides: [ | 6 | overrides: [ |
7 | { | 7 | { |
8 | files: [ | 8 | files: ['.eslintrc.cjs', 'vite.config.js'], |
9 | '.eslintrc.cjs', | ||
10 | 'vite.config.js', | ||
11 | ], | ||
12 | env: { | 9 | env: { |
13 | browser: false, | 10 | browser: false, |
14 | node: true, | 11 | node: true, |
diff --git a/packages/renderer/index.html b/packages/renderer/index.html index 08469c7..039ce61 100644 --- a/packages/renderer/index.html +++ b/packages/renderer/index.html | |||
@@ -1,9 +1,12 @@ | |||
1 | <!DOCTYPE html> | 1 | <!DOCTYPE html> |
2 | <html lang="en"> | 2 | <html lang="en"> |
3 | <head> | 3 | <head> |
4 | <meta charset="UTF-8"> | 4 | <meta charset="UTF-8" /> |
5 | <meta http-equiv="Content-Security-Policy" content="script-src 'self' blob:"> | 5 | <meta |
6 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 6 | http-equiv="Content-Security-Policy" |
7 | content="script-src 'self' blob:" | ||
8 | /> | ||
9 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
7 | <title>Sophie</title> | 10 | <title>Sophie</title> |
8 | </head> | 11 | </head> |
9 | <body> | 12 | <body> |
diff --git a/packages/renderer/src/components/BrowserViewPlaceholder.tsx b/packages/renderer/src/components/BrowserViewPlaceholder.tsx index 11c09d6..8f055e7 100644 --- a/packages/renderer/src/components/BrowserViewPlaceholder.tsx +++ b/packages/renderer/src/components/BrowserViewPlaceholder.tsx | |||
@@ -29,36 +29,37 @@ export default observer(() => { | |||
29 | const store = useStore(); | 29 | const store = useStore(); |
30 | 30 | ||
31 | // eslint-disable-next-line react-hooks/exhaustive-deps -- react-hooks doesn't support `throttle`. | 31 | // eslint-disable-next-line react-hooks/exhaustive-deps -- react-hooks doesn't support `throttle`. |
32 | const onResize = useCallback(throttle(([entry]: ResizeObserverEntry[]) => { | 32 | const onResize = useCallback( |
33 | if (entry) { | 33 | throttle(([entry]: ResizeObserverEntry[]) => { |
34 | const { | 34 | if (entry) { |
35 | x, | 35 | const { x, y, width, height } = entry.target.getBoundingClientRect(); |
36 | y, | 36 | store.setBrowserViewBounds({ |
37 | width, | 37 | x, |
38 | height, | 38 | y, |
39 | } = entry.target.getBoundingClientRect(); | 39 | width, |
40 | store.setBrowserViewBounds({ | 40 | height, |
41 | x, | 41 | }); |
42 | y, | 42 | } |
43 | width, | 43 | }, 100), |
44 | height, | 44 | [store], |
45 | }); | 45 | ); |
46 | } | ||
47 | }, 100), [store]); | ||
48 | 46 | ||
49 | const resizeObserverRef = useRef<ResizeObserver | null>(null); | 47 | const resizeObserverRef = useRef<ResizeObserver | null>(null); |
50 | 48 | ||
51 | const ref = useCallback((element: HTMLElement | null) => { | 49 | const ref = useCallback( |
52 | if (resizeObserverRef.current !== null) { | 50 | (element: HTMLElement | null) => { |
53 | resizeObserverRef.current.disconnect(); | 51 | if (resizeObserverRef.current !== null) { |
54 | } | 52 | resizeObserverRef.current.disconnect(); |
55 | if (element === null) { | 53 | } |
56 | resizeObserverRef.current = null; | 54 | if (element === null) { |
57 | return; | 55 | resizeObserverRef.current = null; |
58 | } | 56 | return; |
59 | resizeObserverRef.current = new ResizeObserver(onResize); | 57 | } |
60 | resizeObserverRef.current.observe(element); | 58 | resizeObserverRef.current = new ResizeObserver(onResize); |
61 | }, [onResize, resizeObserverRef]); | 59 | resizeObserverRef.current.observe(element); |
60 | }, | ||
61 | [onResize, resizeObserverRef], | ||
62 | ); | ||
62 | 63 | ||
63 | return ( | 64 | return ( |
64 | <Box | 65 | <Box |
diff --git a/packages/renderer/src/components/StoreProvider.tsx b/packages/renderer/src/components/StoreProvider.tsx index cde6a31..bb8495c 100644 --- a/packages/renderer/src/components/StoreProvider.tsx +++ b/packages/renderer/src/components/StoreProvider.tsx | |||
@@ -32,13 +32,14 @@ export function useStore(): RendererStore { | |||
32 | return store; | 32 | return store; |
33 | } | 33 | } |
34 | 34 | ||
35 | export default function StoreProvider({ children, store }: { | 35 | export default function StoreProvider({ |
36 | children: JSX.Element | JSX.Element[], | 36 | children, |
37 | store: RendererStore, | 37 | store, |
38 | }: { | ||
39 | children: JSX.Element | JSX.Element[]; | ||
40 | store: RendererStore; | ||
38 | }): JSX.Element { | 41 | }): JSX.Element { |
39 | return ( | 42 | return ( |
40 | <StoreContext.Provider value={store}> | 43 | <StoreContext.Provider value={store}>{children}</StoreContext.Provider> |
41 | {children} | ||
42 | </StoreContext.Provider> | ||
43 | ); | 44 | ); |
44 | } | 45 | } |
diff --git a/packages/renderer/src/components/ThemeProvider.tsx b/packages/renderer/src/components/ThemeProvider.tsx index eacaa52..3943371 100644 --- a/packages/renderer/src/components/ThemeProvider.tsx +++ b/packages/renderer/src/components/ThemeProvider.tsx | |||
@@ -27,20 +27,18 @@ import React from 'react'; | |||
27 | 27 | ||
28 | import { useStore } from './StoreProvider'; | 28 | import { useStore } from './StoreProvider'; |
29 | 29 | ||
30 | export default observer(({ children }: { | 30 | export default observer( |
31 | children: JSX.Element | JSX.Element[]; | 31 | ({ children }: { children: JSX.Element | JSX.Element[] }) => { |
32 | }) => { | 32 | const { |
33 | const { shared: { shouldUseDarkColors } } = useStore(); | 33 | shared: { shouldUseDarkColors }, |
34 | } = useStore(); | ||
34 | 35 | ||
35 | const theme = createTheme({ | 36 | const theme = createTheme({ |
36 | palette: { | 37 | palette: { |
37 | mode: shouldUseDarkColors ? 'dark' : 'light', | 38 | mode: shouldUseDarkColors ? 'dark' : 'light', |
38 | }, | 39 | }, |
39 | }); | 40 | }); |
40 | 41 | ||
41 | return ( | 42 | return <MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>; |
42 | <MuiThemeProvider theme={theme}> | 43 | }, |
43 | {children} | 44 | ); |
44 | </MuiThemeProvider> | ||
45 | ); | ||
46 | }); | ||
diff --git a/packages/renderer/src/components/ToggleDarkModeButton.tsx b/packages/renderer/src/components/ToggleDarkModeButton.tsx index c8ffdf0..695756a 100644 --- a/packages/renderer/src/components/ToggleDarkModeButton.tsx +++ b/packages/renderer/src/components/ToggleDarkModeButton.tsx | |||
@@ -28,7 +28,9 @@ import { useStore } from './StoreProvider'; | |||
28 | 28 | ||
29 | export default observer(() => { | 29 | export default observer(() => { |
30 | const store = useStore(); | 30 | const store = useStore(); |
31 | const { shared: { shouldUseDarkColors } } = store; | 31 | const { |
32 | shared: { shouldUseDarkColors }, | ||
33 | } = store; | ||
32 | 34 | ||
33 | return ( | 35 | return ( |
34 | <IconButton | 36 | <IconButton |
diff --git a/packages/renderer/src/devTools.ts b/packages/renderer/src/devTools.ts index 3d3ba99..cb695c3 100644 --- a/packages/renderer/src/devTools.ts +++ b/packages/renderer/src/devTools.ts | |||
@@ -35,7 +35,9 @@ import type { IAnyStateTreeNode } from 'mobx-state-tree'; | |||
35 | * @return A promise that resolves when the store was exposed to the devtools. | 35 | * @return A promise that resolves when the store was exposed to the devtools. |
36 | * @see https://github.com/SocketCluster/socketcluster-client/issues/118#issuecomment-469064682 | 36 | * @see https://github.com/SocketCluster/socketcluster-client/issues/118#issuecomment-469064682 |
37 | */ | 37 | */ |
38 | export async function exposeToReduxDevtools(model: IAnyStateTreeNode): Promise<void> { | 38 | export async function exposeToReduxDevtools( |
39 | model: IAnyStateTreeNode, | ||
40 | ): Promise<void> { | ||
39 | (window as { global?: unknown }).global = window; | 41 | (window as { global?: unknown }).global = window; |
40 | 42 | ||
41 | // Hack to load dev dependencies on demand. | 43 | // Hack to load dev dependencies on demand. |
diff --git a/packages/renderer/src/stores/RendererStore.ts b/packages/renderer/src/stores/RendererStore.ts index e684759..0b78ce1 100644 --- a/packages/renderer/src/stores/RendererStore.ts +++ b/packages/renderer/src/stores/RendererStore.ts | |||
@@ -24,12 +24,7 @@ import { | |||
24 | SophieRenderer, | 24 | SophieRenderer, |
25 | ThemeSource, | 25 | ThemeSource, |
26 | } from '@sophie/shared'; | 26 | } from '@sophie/shared'; |
27 | import { | 27 | import { applySnapshot, applyPatch, Instance, types } from 'mobx-state-tree'; |
28 | applySnapshot, | ||
29 | applyPatch, | ||
30 | Instance, | ||
31 | types, | ||
32 | } from 'mobx-state-tree'; | ||
33 | 28 | ||
34 | import { getLogger } from '../utils/log'; | 29 | import { getLogger } from '../utils/log'; |
35 | 30 | ||
@@ -38,29 +33,31 @@ import { getEnv } from './RendererEnv'; | |||
38 | 33 | ||
39 | const log = getLogger('RendererStore'); | 34 | const log = getLogger('RendererStore'); |
40 | 35 | ||
41 | export const rendererStore = types.model('RendererStore', { | 36 | export const rendererStore = types |
42 | shared: types.optional(sharedStore, {}), | 37 | .model('RendererStore', { |
43 | }).actions((self) => ({ | 38 | shared: types.optional(sharedStore, {}), |
44 | setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { | 39 | }) |
45 | getEnv(self).dispatchMainAction({ | 40 | .actions((self) => ({ |
46 | action: 'set-browser-view-bounds', | 41 | setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { |
47 | browserViewBounds, | 42 | getEnv(self).dispatchMainAction({ |
48 | }); | 43 | action: 'set-browser-view-bounds', |
49 | }, | 44 | browserViewBounds, |
50 | setThemeSource(themeSource: ThemeSource): void { | 45 | }); |
51 | getEnv(self).dispatchMainAction({ | 46 | }, |
52 | action: 'set-theme-source', | 47 | setThemeSource(themeSource: ThemeSource): void { |
53 | themeSource, | 48 | getEnv(self).dispatchMainAction({ |
54 | }); | 49 | action: 'set-theme-source', |
55 | }, | 50 | themeSource, |
56 | toggleDarkMode(): void { | 51 | }); |
57 | if (self.shared.shouldUseDarkColors) { | 52 | }, |
58 | this.setThemeSource('light'); | 53 | toggleDarkMode(): void { |
59 | } else { | 54 | if (self.shared.shouldUseDarkColors) { |
60 | this.setThemeSource('dark'); | 55 | this.setThemeSource('light'); |
61 | } | 56 | } else { |
62 | }, | 57 | this.setThemeSource('dark'); |
63 | })); | 58 | } |
59 | }, | ||
60 | })); | ||
64 | 61 | ||
65 | export interface RendererStore extends Instance<typeof rendererStore> {} | 62 | export interface RendererStore extends Instance<typeof rendererStore> {} |
66 | 63 | ||
@@ -72,22 +69,26 @@ export interface RendererStore extends Instance<typeof rendererStore> {} | |||
72 | * | 69 | * |
73 | * @param ipc The `sophieRenderer` context bridge. | 70 | * @param ipc The `sophieRenderer` context bridge. |
74 | */ | 71 | */ |
75 | export function createAndConnectRendererStore(ipc: SophieRenderer): RendererStore { | 72 | export function createAndConnectRendererStore( |
73 | ipc: SophieRenderer, | ||
74 | ): RendererStore { | ||
76 | const env: RendererEnv = { | 75 | const env: RendererEnv = { |
77 | dispatchMainAction: ipc.dispatchAction, | 76 | dispatchMainAction: ipc.dispatchAction, |
78 | }; | 77 | }; |
79 | const store = rendererStore.create({}, env); | 78 | const store = rendererStore.create({}, env); |
80 | 79 | ||
81 | ipc.onSharedStoreChange({ | 80 | ipc |
82 | onSnapshot(snapshot) { | 81 | .onSharedStoreChange({ |
83 | applySnapshot(store.shared, snapshot); | 82 | onSnapshot(snapshot) { |
84 | }, | 83 | applySnapshot(store.shared, snapshot); |
85 | onPatch(patch) { | 84 | }, |
86 | applyPatch(store.shared, patch); | 85 | onPatch(patch) { |
87 | }, | 86 | applyPatch(store.shared, patch); |
88 | }).catch((err) => { | 87 | }, |
89 | log.error('Failed to connect to shared store', err); | 88 | }) |
90 | }); | 89 | .catch((err) => { |
90 | log.error('Failed to connect to shared store', err); | ||
91 | }); | ||
91 | 92 | ||
92 | return store; | 93 | return store; |
93 | } | 94 | } |
diff --git a/packages/renderer/tsconfig.json b/packages/renderer/tsconfig.json index 14c3e0c..5453330 100644 --- a/packages/renderer/tsconfig.json +++ b/packages/renderer/tsconfig.json | |||
@@ -3,14 +3,8 @@ | |||
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "jsx": "react", | 5 | "jsx": "react", |
6 | "lib": [ | 6 | "lib": ["dom", "dom.iterable", "esnext"], |
7 | "dom", | 7 | "types": ["vite/client"] |
8 | "dom.iterable", | ||
9 | "esnext" | ||
10 | ], | ||
11 | "types": [ | ||
12 | "vite/client" | ||
13 | ] | ||
14 | }, | 8 | }, |
15 | "references": [ | 9 | "references": [ |
16 | { | 10 | { |
diff --git a/packages/renderer/vite.config.js b/packages/renderer/vite.config.js index 6440ead..e20e0f1 100644 --- a/packages/renderer/vite.config.js +++ b/packages/renderer/vite.config.js | |||
@@ -46,9 +46,7 @@ export default { | |||
46 | preserveSymlinks: true, | 46 | preserveSymlinks: true, |
47 | }, | 47 | }, |
48 | optimizeDeps: { | 48 | optimizeDeps: { |
49 | exclude: [ | 49 | exclude: ['@sophie/shared'], |
50 | '@sophie/shared', | ||
51 | ], | ||
52 | }, | 50 | }, |
53 | build: { | 51 | build: { |
54 | target: chrome, | 52 | target: chrome, |
@@ -59,11 +57,7 @@ export default { | |||
59 | minify: !isDevelopment, | 57 | minify: !isDevelopment, |
60 | brotliSize: false, | 58 | brotliSize: false, |
61 | rollupOptions: { | 59 | rollupOptions: { |
62 | external: [ | 60 | external: ['mst-middlewares', 'remotedev', ...builtinModules], |
63 | 'mst-middlewares', | ||
64 | 'remotedev', | ||
65 | ...builtinModules, | ||
66 | ], | ||
67 | output: { | 61 | output: { |
68 | banner, | 62 | banner, |
69 | }, | 63 | }, |
diff --git a/packages/service-inject/.eslintrc.cjs b/packages/service-inject/.eslintrc.cjs index 5555f5b..3131abd 100644 --- a/packages/service-inject/.eslintrc.cjs +++ b/packages/service-inject/.eslintrc.cjs | |||
@@ -5,10 +5,7 @@ module.exports = { | |||
5 | }, | 5 | }, |
6 | overrides: [ | 6 | overrides: [ |
7 | { | 7 | { |
8 | files: [ | 8 | files: ['.eslintrc.cjs', 'esbuild.config.js'], |
9 | '.eslintrc.cjs', | ||
10 | 'esbuild.config.js', | ||
11 | ], | ||
12 | env: { | 9 | env: { |
13 | browser: false, | 10 | browser: false, |
14 | node: true, | 11 | node: true, |
diff --git a/packages/service-inject/esbuild.config.js b/packages/service-inject/esbuild.config.js index d0b04bb..795b0f6 100644 --- a/packages/service-inject/esbuild.config.js +++ b/packages/service-inject/esbuild.config.js | |||
@@ -4,9 +4,7 @@ import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | |||
4 | 4 | ||
5 | export default getEsbuildConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: ['src/index.ts'], |
8 | 'src/index.ts', | ||
9 | ], | ||
10 | outfile: 'dist/index.js', | 8 | outfile: 'dist/index.js', |
11 | format: 'iife', | 9 | format: 'iife', |
12 | platform: 'browser', | 10 | platform: 'browser', |
diff --git a/packages/service-inject/tsconfig.json b/packages/service-inject/tsconfig.json index 8f84d98..33ce1de 100644 --- a/packages/service-inject/tsconfig.json +++ b/packages/service-inject/tsconfig.json | |||
@@ -2,20 +2,12 @@ | |||
2 | "extends": "../../config/tsconfig.base.json", | 2 | "extends": "../../config/tsconfig.base.json", |
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "lib": [ | 5 | "lib": ["dom", "dom.iterable", "esnext"] |
6 | "dom", | ||
7 | "dom.iterable", | ||
8 | "esnext" | ||
9 | ] | ||
10 | }, | 6 | }, |
11 | "references": [ | 7 | "references": [ |
12 | { | 8 | { |
13 | "path": "../service-shared/tsconfig.build.json" | 9 | "path": "../service-shared/tsconfig.build.json" |
14 | } | 10 | } |
15 | ], | 11 | ], |
16 | "include": [ | 12 | "include": ["src/**/*.ts", ".eslintrc.cjs", "esbuild.config.js"] |
17 | "src/**/*.ts", | ||
18 | ".eslintrc.cjs", | ||
19 | "esbuild.config.js" | ||
20 | ] | ||
21 | } | 13 | } |
diff --git a/packages/service-preload/esbuild.config.js b/packages/service-preload/esbuild.config.js index 66f5e84..d888987 100644 --- a/packages/service-preload/esbuild.config.js +++ b/packages/service-preload/esbuild.config.js | |||
@@ -4,15 +4,11 @@ import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | |||
4 | 4 | ||
5 | export default getEsbuildConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: ['src/index.ts'], |
8 | 'src/index.ts', | ||
9 | ], | ||
10 | outfile: 'dist/index.cjs', | 8 | outfile: 'dist/index.cjs', |
11 | format: 'cjs', | 9 | format: 'cjs', |
12 | platform: 'node', | 10 | platform: 'node', |
13 | target: chrome, | 11 | target: chrome, |
14 | sourcemap: 'inline', | 12 | sourcemap: 'inline', |
15 | external: [ | 13 | external: ['electron'], |
16 | 'electron', | ||
17 | ], | ||
18 | }); | 14 | }); |
diff --git a/packages/service-preload/tsconfig.json b/packages/service-preload/tsconfig.json index 768c464..189859e 100644 --- a/packages/service-preload/tsconfig.json +++ b/packages/service-preload/tsconfig.json | |||
@@ -2,11 +2,7 @@ | |||
2 | "extends": "../../config/tsconfig.base.json", | 2 | "extends": "../../config/tsconfig.base.json", |
3 | "compilerOptions": { | 3 | "compilerOptions": { |
4 | "noEmit": true, | 4 | "noEmit": true, |
5 | "lib": [ | 5 | "lib": ["dom", "dom.iterable", "esnext"] |
6 | "dom", | ||
7 | "dom.iterable", | ||
8 | "esnext" | ||
9 | ] | ||
10 | }, | 6 | }, |
11 | "references": [ | 7 | "references": [ |
12 | { | 8 | { |
diff --git a/packages/service-preload/types/importMeta.d.ts b/packages/service-preload/types/importMeta.d.ts index 9b73170..ff3b17c 100644 --- a/packages/service-preload/types/importMeta.d.ts +++ b/packages/service-preload/types/importMeta.d.ts | |||
@@ -3,5 +3,5 @@ interface ImportMeta { | |||
3 | DEV: boolean; | 3 | DEV: boolean; |
4 | MODE: string; | 4 | MODE: string; |
5 | PROD: boolean; | 5 | PROD: boolean; |
6 | } | 6 | }; |
7 | } | 7 | } |
diff --git a/packages/service-shared/.eslintrc.cjs b/packages/service-shared/.eslintrc.cjs index c19829d..25fd252 100644 --- a/packages/service-shared/.eslintrc.cjs +++ b/packages/service-shared/.eslintrc.cjs | |||
@@ -6,10 +6,7 @@ module.exports = { | |||
6 | }, | 6 | }, |
7 | overrides: [ | 7 | overrides: [ |
8 | { | 8 | { |
9 | files: [ | 9 | files: ['.eslintrc.cjs', 'esbuild.config.js'], |
10 | '.eslintrc.cjs', | ||
11 | 'esbuild.config.js', | ||
12 | ], | ||
13 | env: { | 10 | env: { |
14 | node: true, | 11 | node: true, |
15 | }, | 12 | }, |
diff --git a/packages/service-shared/esbuild.config.js b/packages/service-shared/esbuild.config.js index ccee72c..2b0dec8 100644 --- a/packages/service-shared/esbuild.config.js +++ b/packages/service-shared/esbuild.config.js | |||
@@ -4,9 +4,7 @@ import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | |||
4 | 4 | ||
5 | export default getEsbuildConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: ['src/index.ts'], |
8 | 'src/index.ts', | ||
9 | ], | ||
10 | outfile: 'dist/index.mjs', | 8 | outfile: 'dist/index.mjs', |
11 | format: 'esm', | 9 | format: 'esm', |
12 | // The package that includes this one will have a header comment, | 10 | // The package that includes this one will have a header comment, |
@@ -14,7 +12,5 @@ export default getEsbuildConfig({ | |||
14 | banner: {}, | 12 | banner: {}, |
15 | platform: 'node', | 13 | platform: 'node', |
16 | target: [chrome, node], | 14 | target: [chrome, node], |
17 | external: [ | 15 | external: ['zod'], |
18 | 'zod', | ||
19 | ], | ||
20 | }); | 16 | }); |
diff --git a/packages/service-shared/src/index.ts b/packages/service-shared/src/index.ts index e111347..94be734 100644 --- a/packages/service-shared/src/index.ts +++ b/packages/service-shared/src/index.ts | |||
@@ -20,11 +20,5 @@ | |||
20 | 20 | ||
21 | export { MainToServiceIpcMessage, ServiceToMainIpcMessage } from './ipc'; | 21 | export { MainToServiceIpcMessage, ServiceToMainIpcMessage } from './ipc'; |
22 | 22 | ||
23 | export type { | 23 | export type { UnreadCount, WebSource } from './schemas'; |
24 | UnreadCount, | 24 | export { unreadCount, webSource } from './schemas'; |
25 | WebSource, | ||
26 | } from './schemas'; | ||
27 | export { | ||
28 | unreadCount, | ||
29 | webSource, | ||
30 | } from './schemas'; | ||
diff --git a/packages/service-shared/src/ipc.ts b/packages/service-shared/src/ipc.ts index c0dab11..e0a8755 100644 --- a/packages/service-shared/src/ipc.ts +++ b/packages/service-shared/src/ipc.ts | |||
@@ -18,8 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | export enum MainToServiceIpcMessage { | 21 | export enum MainToServiceIpcMessage {} |
22 | } | ||
23 | 22 | ||
24 | export enum ServiceToMainIpcMessage { | 23 | export enum ServiceToMainIpcMessage { |
25 | ApiExposedInMainWorld = 'sophie-service-to-main:api-exposed-in-main-world', | 24 | ApiExposedInMainWorld = 'sophie-service-to-main:api-exposed-in-main-world', |
diff --git a/packages/service-shared/tsconfig.build.json b/packages/service-shared/tsconfig.build.json index 9a0c835..d300514 100644 --- a/packages/service-shared/tsconfig.build.json +++ b/packages/service-shared/tsconfig.build.json | |||
@@ -6,7 +6,5 @@ | |||
6 | "emitDeclarationOnly": true, | 6 | "emitDeclarationOnly": true, |
7 | "rootDir": "src" | 7 | "rootDir": "src" |
8 | }, | 8 | }, |
9 | "include": [ | 9 | "include": ["src/**/*.ts"] |
10 | "src/**/*.ts" | ||
11 | ] | ||
12 | } | 10 | } |
diff --git a/packages/service-shared/tsconfig.json b/packages/service-shared/tsconfig.json index 3e6c6ff..daad7c4 100644 --- a/packages/service-shared/tsconfig.json +++ b/packages/service-shared/tsconfig.json | |||
@@ -7,9 +7,5 @@ | |||
7 | "noEmit": true, | 7 | "noEmit": true, |
8 | "rootDir": null | 8 | "rootDir": null |
9 | }, | 9 | }, |
10 | "include": [ | 10 | "include": ["src/**/*.ts", ".eslintrc.cjs", "esbuild.config.js"] |
11 | "src/**/*.ts", | ||
12 | ".eslintrc.cjs", | ||
13 | "esbuild.config.js" | ||
14 | ] | ||
15 | } | 11 | } |
diff --git a/packages/shared/.eslintrc.cjs b/packages/shared/.eslintrc.cjs index c19829d..25fd252 100644 --- a/packages/shared/.eslintrc.cjs +++ b/packages/shared/.eslintrc.cjs | |||
@@ -6,10 +6,7 @@ module.exports = { | |||
6 | }, | 6 | }, |
7 | overrides: [ | 7 | overrides: [ |
8 | { | 8 | { |
9 | files: [ | 9 | files: ['.eslintrc.cjs', 'esbuild.config.js'], |
10 | '.eslintrc.cjs', | ||
11 | 'esbuild.config.js', | ||
12 | ], | ||
13 | env: { | 10 | env: { |
14 | node: true, | 11 | node: true, |
15 | }, | 12 | }, |
diff --git a/packages/shared/esbuild.config.js b/packages/shared/esbuild.config.js index 78249ab..44501bd 100644 --- a/packages/shared/esbuild.config.js +++ b/packages/shared/esbuild.config.js | |||
@@ -4,9 +4,7 @@ import getEsbuildConfig from '../../config/getEsbuildConfig.js'; | |||
4 | 4 | ||
5 | export default getEsbuildConfig({ | 5 | export default getEsbuildConfig({ |
6 | absWorkingDir: fileURLToDirname(import.meta.url), | 6 | absWorkingDir: fileURLToDirname(import.meta.url), |
7 | entryPoints: [ | 7 | entryPoints: ['src/index.ts'], |
8 | 'src/index.ts', | ||
9 | ], | ||
10 | outfile: 'dist/index.mjs', | 8 | outfile: 'dist/index.mjs', |
11 | format: 'esm', | 9 | format: 'esm', |
12 | // The package that includes this one will have a header comment, | 10 | // The package that includes this one will have a header comment, |
@@ -14,9 +12,5 @@ export default getEsbuildConfig({ | |||
14 | banner: {}, | 12 | banner: {}, |
15 | platform: 'node', | 13 | platform: 'node', |
16 | target: [chrome, node], | 14 | target: [chrome, node], |
17 | external: [ | 15 | external: ['mobx', 'mobx-state-tree', 'zod'], |
18 | 'mobx', | ||
19 | 'mobx-state-tree', | ||
20 | 'zod', | ||
21 | ], | ||
22 | }); | 16 | }); |
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 9828ec4..6383f63 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts | |||
@@ -22,18 +22,14 @@ export type { SophieRenderer } from './contextBridge/SophieRenderer'; | |||
22 | 22 | ||
23 | export { MainToRendererIpcMessage, RendererToMainIpcMessage } from './ipc'; | 23 | export { MainToRendererIpcMessage, RendererToMainIpcMessage } from './ipc'; |
24 | 24 | ||
25 | export type { | 25 | export type { Action, BrowserViewBounds, ThemeSource } from './schemas'; |
26 | Action, | 26 | export { action, browserViewBounds, themeSource } from './schemas'; |
27 | BrowserViewBounds, | ||
28 | ThemeSource, | ||
29 | } from './schemas'; | ||
30 | export { | ||
31 | action, | ||
32 | browserViewBounds, | ||
33 | themeSource, | ||
34 | } from './schemas'; | ||
35 | 27 | ||
36 | export type { Config, ConfigSnapshotIn, ConfigSnapshotOut } from './stores/Config'; | 28 | export type { |
29 | Config, | ||
30 | ConfigSnapshotIn, | ||
31 | ConfigSnapshotOut, | ||
32 | } from './stores/Config'; | ||
37 | export { config } from './stores/Config'; | 33 | export { config } from './stores/Config'; |
38 | 34 | ||
39 | export type { | 35 | export type { |
diff --git a/packages/shared/src/stores/Config.ts b/packages/shared/src/stores/Config.ts index 432945c..1d98a33 100644 --- a/packages/shared/src/stores/Config.ts +++ b/packages/shared/src/stores/Config.ts | |||
@@ -18,12 +18,7 @@ | |||
18 | * SPDX-License-Identifier: AGPL-3.0-only | 18 | * SPDX-License-Identifier: AGPL-3.0-only |
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { | 21 | import { Instance, types, SnapshotIn, SnapshotOut } from 'mobx-state-tree'; |
22 | Instance, | ||
23 | types, | ||
24 | SnapshotIn, | ||
25 | SnapshotOut, | ||
26 | } from 'mobx-state-tree'; | ||
27 | 22 | ||
28 | import { themeSource } from '../schemas'; | 23 | import { themeSource } from '../schemas'; |
29 | 24 | ||
diff --git a/packages/shared/src/stores/SharedStore.ts b/packages/shared/src/stores/SharedStore.ts index c6c3ddc..cb14394 100644 --- a/packages/shared/src/stores/SharedStore.ts +++ b/packages/shared/src/stores/SharedStore.ts | |||
@@ -37,7 +37,8 @@ export interface SharedStore extends Instance<typeof sharedStore> {} | |||
37 | 37 | ||
38 | export interface SharedStoreSnapshotIn extends SnapshotIn<typeof sharedStore> {} | 38 | export interface SharedStoreSnapshotIn extends SnapshotIn<typeof sharedStore> {} |
39 | 39 | ||
40 | export interface SharedStoreSnapshotOut extends SnapshotOut<typeof sharedStore> {} | 40 | export interface SharedStoreSnapshotOut |
41 | extends SnapshotOut<typeof sharedStore> {} | ||
41 | 42 | ||
42 | export interface SharedStoreListener { | 43 | export interface SharedStoreListener { |
43 | onSnapshot(snapshot: SharedStoreSnapshotIn): void; | 44 | onSnapshot(snapshot: SharedStoreSnapshotIn): void; |
diff --git a/packages/shared/tsconfig.build.json b/packages/shared/tsconfig.build.json index 9a0c835..d300514 100644 --- a/packages/shared/tsconfig.build.json +++ b/packages/shared/tsconfig.build.json | |||
@@ -6,7 +6,5 @@ | |||
6 | "emitDeclarationOnly": true, | 6 | "emitDeclarationOnly": true, |
7 | "rootDir": "src" | 7 | "rootDir": "src" |
8 | }, | 8 | }, |
9 | "include": [ | 9 | "include": ["src/**/*.ts"] |
10 | "src/**/*.ts" | ||
11 | ] | ||
12 | } | 10 | } |
diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json index 3e6c6ff..daad7c4 100644 --- a/packages/shared/tsconfig.json +++ b/packages/shared/tsconfig.json | |||
@@ -7,9 +7,5 @@ | |||
7 | "noEmit": true, | 7 | "noEmit": true, |
8 | "rootDir": null | 8 | "rootDir": null |
9 | }, | 9 | }, |
10 | "include": [ | 10 | "include": ["src/**/*.ts", ".eslintrc.cjs", "esbuild.config.js"] |
11 | "src/**/*.ts", | ||
12 | ".eslintrc.cjs", | ||
13 | "esbuild.config.js" | ||
14 | ] | ||
15 | } | 11 | } |