aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/main/package.json6
-rw-r--r--packages/main/src/devTools.ts49
-rw-r--r--packages/main/src/index.ts66
-rw-r--r--packages/main/src/stores/RootStore.ts12
-rw-r--r--packages/preload/package.json4
-rw-r--r--packages/preload/src/SophieRendererImpl.ts74
-rw-r--r--packages/preload/src/index.ts11
-rw-r--r--packages/renderer/package.json6
-rw-r--r--packages/renderer/src/devTools.ts37
-rw-r--r--packages/renderer/src/index.tsx23
-rw-r--r--packages/renderer/tsconfig.json3
-rw-r--r--packages/renderer/vite.config.js3
-rw-r--r--packages/shared/package.json5
-rw-r--r--packages/shared/src/contextBridge/SophieRenderer.ts6
-rw-r--r--packages/shared/src/index.ts11
-rw-r--r--packages/shared/src/ipc/MainToRendererIpcMessage.ts4
-rw-r--r--packages/shared/src/ipc/RendererIpcMessage.ts3
-rw-r--r--packages/shared/src/ipc/RendererToMainIpcMessage.ts4
-rw-r--r--packages/shared/src/stores/SharedStore.ts23
-rw-r--r--packages/shared/vite.config.js8
20 files changed, 302 insertions, 56 deletions
diff --git a/packages/main/package.json b/packages/main/package.json
index 63da432..22afafa 100644
--- a/packages/main/package.json
+++ b/packages/main/package.json
@@ -9,11 +9,13 @@
9 }, 9 },
10 "dependencies": { 10 "dependencies": {
11 "@sophie/shared": "workspace:*", 11 "@sophie/shared": "workspace:*",
12 "electron": "^16.0.5" 12 "electron": "^16.0.5",
13 "mobx": "^6.3.10",
14 "mobx-state-tree": "^5.1.0"
13 }, 15 },
14 "devDependencies": { 16 "devDependencies": {
15 "@types/electron-devtools-installer": "^2.2.0", 17 "@types/electron-devtools-installer": "^2.2.0",
16 "@types/node": "^16.11.15", 18 "@types/node": "^16.11.17",
17 "electron-devtools-installer": "^3.2.0", 19 "electron-devtools-installer": "^3.2.0",
18 "typescript": "^4.5.4", 20 "typescript": "^4.5.4",
19 "vite": "^2.7.6" 21 "vite": "^2.7.6"
diff --git a/packages/main/src/devTools.ts b/packages/main/src/devTools.ts
new file mode 100644
index 0000000..d02bfbf
--- /dev/null
+++ b/packages/main/src/devTools.ts
@@ -0,0 +1,49 @@
1import type { App, BrowserWindow } from 'electron';
2
3/**
4 * Installs the react and redux developer tools extensions.
5 *
6 * We use the redux devtools and connect the mobx store to it with `mst-middlewares`,
7 * because the mobx-state-tree devtools are currently unmaintained.
8 *
9 * @param app The electron application instance.
10 */
11export function installDevToolsExtensions(app: App): void {
12 app.whenReady().then(async () => {
13 const {
14 default: installExtension,
15 REACT_DEVELOPER_TOOLS,
16 REDUX_DEVTOOLS,
17 } = await import('electron-devtools-installer');
18 installExtension(
19 [
20 REACT_DEVELOPER_TOOLS,
21 REDUX_DEVTOOLS,
22 ],
23 {
24 forceDownload: false,
25 loadExtensionOptions: {
26 allowFileAccess: true,
27 },
28 },
29 );
30 }).catch((err) => {
31 console.error('Failed to install devtools extension', err);
32 });
33}
34
35/**
36 * Opens the developer tools while applying a workaround to enable the redux devtools.
37 *
38 * @param browserWindow The browser window to open the devtools in.
39 * @see https://github.com/MarshallOfSound/electron-devtools-installer/issues/195#issuecomment-998872878
40 */
41export function openDevToolsWhenReady(browserWindow: BrowserWindow): void {
42 const { webContents } = browserWindow;
43 webContents.once('dom-ready', () => {
44 webContents.once('devtools-opened', () => {
45 browserWindow?.focus();
46 });
47 webContents.openDevTools();
48 });
49}
diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts
index cd04276..dbe6890 100644
--- a/packages/main/src/index.ts
+++ b/packages/main/src/index.ts
@@ -1,8 +1,18 @@
1import { app, BrowserWindow } from 'electron'; 1import { app, BrowserWindow } from 'electron';
2import { getSnapshot, onPatch } from 'mobx-state-tree';
2import { join } from 'path'; 3import { join } from 'path';
3import { RendererIpcMessage } from '@sophie/shared'; 4import {
5 MainToRendererIpcMessage,
6 RendererToMainIpcMessage,
7} from '@sophie/shared';
4import { URL } from 'url'; 8import { URL } from 'url';
5 9
10import {
11 installDevToolsExtensions,
12 openDevToolsWhenReady,
13} from './devTools';
14import { rootStore } from './stores/RootStore';
15
6const isSingleInstance = app.requestSingleInstanceLock(); 16const isSingleInstance = app.requestSingleInstanceLock();
7const isDevelopment = import.meta.env.MODE === 'development'; 17const isDevelopment = import.meta.env.MODE === 'development';
8 18
@@ -14,62 +24,46 @@ if (!isSingleInstance) {
14app.enableSandbox(); 24app.enableSandbox();
15 25
16if (isDevelopment) { 26if (isDevelopment) {
17 app.whenReady().then(async () => { 27 installDevToolsExtensions(app);
18 const {
19 default: installExtension,
20 MOBX_DEVTOOLS,
21 REACT_DEVELOPER_TOOLS,
22 } = await import('electron-devtools-installer');
23 installExtension(
24 [
25 MOBX_DEVTOOLS,
26 REACT_DEVELOPER_TOOLS,
27 ],
28 {
29 forceDownload: false,
30 loadExtensionOptions: {
31 allowFileAccess: true,
32 },
33 },
34 );
35 }).catch((err) => {
36 console.error('Failed to install devtools extension', err);
37 });
38} 28}
39 29
40let mainWindow: BrowserWindow | null = null; 30let mainWindow: BrowserWindow | null = null;
41 31
32const store = rootStore.create({
33 shared: {
34 clickCount: 1,
35 },
36});
37
42function createWindow(): Promise<void> { 38function createWindow(): Promise<void> {
43 mainWindow = new BrowserWindow({ 39 mainWindow = new BrowserWindow({
44 show: false, 40 show: false,
41 autoHideMenuBar: true,
45 webPreferences: { 42 webPreferences: {
46 nativeWindowOpen: true, 43 nativeWindowOpen: true,
47 webviewTag: false, 44 webviewTag: false,
48 sandbox: true, 45 sandbox: true,
49 preload: join(__dirname, '../../preload/dist/index.cjs'), 46 preload: join(__dirname, '../../preload/dist/index.cjs'),
50 } 47 },
51 }); 48 });
52 49
53 const { webContents } = mainWindow;
54
55 // See https://github.com/MarshallOfSound/electron-devtools-installer/issues/195#issuecomment-998872878
56 if (isDevelopment) { 50 if (isDevelopment) {
57 webContents.once('dom-ready', () => { 51 openDevToolsWhenReady(mainWindow);
58 webContents.once('devtools-opened', () => {
59 mainWindow?.focus();
60 });
61 webContents.openDevTools();
62 });
63 } 52 }
64 53
65 mainWindow.on('ready-to-show', () => { 54 mainWindow.on('ready-to-show', () => {
66 mainWindow?.show(); 55 mainWindow?.show();
67 }); 56 });
68 57
58 const { webContents } = mainWindow;
59
69 webContents.on('ipc-message', (_event, channel, ...args) => { 60 webContents.on('ipc-message', (_event, channel, ...args) => {
70 switch (channel) { 61 switch (channel) {
71 case RendererIpcMessage.ButtonClicked: 62 case RendererToMainIpcMessage.SharedStoreSnapshotRequest:
72 console.log('Button clicked'); 63 webContents.send(MainToRendererIpcMessage.SharedStoreSnapshot, getSnapshot(store.shared));
64 break;
65 case RendererToMainIpcMessage.ButtonClick:
66 store.buttonClick();
73 break; 67 break;
74 default: 68 default:
75 console.warn('Unknown IPC message:', channel, args); 69 console.warn('Unknown IPC message:', channel, args);
@@ -77,6 +71,10 @@ function createWindow(): Promise<void> {
77 } 71 }
78 }); 72 });
79 73
74 onPatch(store.shared, (patch) => {
75 webContents.send(MainToRendererIpcMessage.SharedStorePatch, patch);
76 });
77
80 const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined) 78 const pageUrl = (isDevelopment && import.meta.env.VITE_DEV_SERVER_URL !== undefined)
81 ? import.meta.env.VITE_DEV_SERVER_URL 79 ? import.meta.env.VITE_DEV_SERVER_URL
82 : new URL('../renderer/dist/index.html', `file://${__dirname}`).toString(); 80 : new URL('../renderer/dist/index.html', `file://${__dirname}`).toString();
diff --git a/packages/main/src/stores/RootStore.ts b/packages/main/src/stores/RootStore.ts
new file mode 100644
index 0000000..a9c1290
--- /dev/null
+++ b/packages/main/src/stores/RootStore.ts
@@ -0,0 +1,12 @@
1import { Instance, types } from 'mobx-state-tree';
2import { sharedStore } from '@sophie/shared';
3
4export const rootStore = types.model('RootStore', {
5 shared: sharedStore,
6}).actions((self) => ({
7 buttonClick() {
8 self.shared.clickCount += 1;
9 },
10}));
11
12export interface RootStore extends Instance<typeof rootStore> {}
diff --git a/packages/preload/package.json b/packages/preload/package.json
index 5556c10..2ad215c 100644
--- a/packages/preload/package.json
+++ b/packages/preload/package.json
@@ -10,7 +10,9 @@
10 }, 10 },
11 "dependencies": { 11 "dependencies": {
12 "@sophie/shared": "workspace:*", 12 "@sophie/shared": "workspace:*",
13 "electron": "^16.0.5" 13 "electron": "^16.0.5",
14 "mobx": "^6.3.10",
15 "mobx-state-tree": "^5.1.0"
14 }, 16 },
15 "devDependencies": { 17 "devDependencies": {
16 "typescript": "^4.5.4", 18 "typescript": "^4.5.4",
diff --git a/packages/preload/src/SophieRendererImpl.ts b/packages/preload/src/SophieRendererImpl.ts
new file mode 100644
index 0000000..e03c89e
--- /dev/null
+++ b/packages/preload/src/SophieRendererImpl.ts
@@ -0,0 +1,74 @@
1import { ipcRenderer } from 'electron';
2import type { IJsonPatch } from 'mobx-state-tree';
3import {
4 MainToRendererIpcMessage,
5 RendererToMainIpcMessage,
6 sharedStore,
7 SharedStoreListener,
8 SharedStoreSnapshotIn,
9 SophieRenderer
10} from '@sophie/shared';
11
12export type MessageSender = (channel: RendererToMainIpcMessage, ...args: unknown[]) => void;
13
14export class SophieRendererImpl implements SophieRenderer {
15 readonly #send: MessageSender;
16
17 #listener: SharedStoreListener | null = null;
18
19 #snapshot: SharedStoreSnapshotIn | null = null;
20
21 constructor(send: MessageSender) {
22 this.#send = send;
23 }
24
25 sharedStoreSnapshotReceived(snapshot: unknown): void {
26 if (sharedStore.is(snapshot)) {
27 if (this.#listener === null) {
28 this.#snapshot = snapshot;
29 } else {
30 this.#listener.onSnapshot(snapshot);
31 }
32 } else {
33 console.error('Received invalid snapshot', snapshot);
34 this.#snapshot = null;
35 }
36 }
37
38 sharedStorePatchReceived(patch: unknown): void {
39 if (this.#listener !== null) {
40 // `mobx-state-tree` will validate the patch, so we can safely cast here.
41 this.#listener.onPatch(patch as IJsonPatch);
42 }
43 }
44
45 setSharedStoreListener(listener: SharedStoreListener): void {
46 this.#listener = listener;
47 if (this.#snapshot !== null) {
48 listener.onSnapshot(this.#snapshot);
49 this.#snapshot = null;
50 }
51 this.#send(RendererToMainIpcMessage.SharedStoreSnapshotRequest);
52 }
53
54 buttonClick(): void {
55 this.#send(RendererToMainIpcMessage.ButtonClick);
56 }
57}
58
59export function createSophieRenderer(): SophieRenderer {
60 const impl = new SophieRendererImpl(ipcRenderer.send);
61
62 ipcRenderer.on(MainToRendererIpcMessage.SharedStoreSnapshot, (_event, snapshot) => {
63 impl.sharedStoreSnapshotReceived(snapshot);
64 });
65
66 ipcRenderer.on(MainToRendererIpcMessage.SharedStorePatch, (_event, patch) => {
67 impl.sharedStorePatchReceived(patch);
68 });
69
70 return {
71 setSharedStoreListener: impl.setSharedStoreListener.bind(impl),
72 buttonClick: impl.buttonClick.bind(impl),
73 };
74}
diff --git a/packages/preload/src/index.ts b/packages/preload/src/index.ts
index 830901a..19d1285 100644
--- a/packages/preload/src/index.ts
+++ b/packages/preload/src/index.ts
@@ -1,10 +1,7 @@
1import { contextBridge, ipcRenderer } from 'electron'; 1import { contextBridge } from 'electron';
2import { RendererIpcMessage, SophieRenderer } from '@sophie/shared';
3 2
4const sophieRenderer: SophieRenderer = { 3import { createSophieRenderer } from './SophieRendererImpl';
5 buttonClicked() { 4
6 ipcRenderer.send(RendererIpcMessage.ButtonClicked); 5const sophieRenderer = createSophieRenderer();
7 }
8};
9 6
10contextBridge.exposeInMainWorld('sophieRenderer', sophieRenderer); 7contextBridge.exposeInMainWorld('sophieRenderer', sophieRenderer);
diff --git a/packages/renderer/package.json b/packages/renderer/package.json
index 559e668..ee627b4 100644
--- a/packages/renderer/package.json
+++ b/packages/renderer/package.json
@@ -14,13 +14,17 @@
14 "@mui/icons-material": "^5.2.5", 14 "@mui/icons-material": "^5.2.5",
15 "@mui/material": "^5.2.5", 15 "@mui/material": "^5.2.5",
16 "@sophie/shared": "workspace:*", 16 "@sophie/shared": "workspace:*",
17 "mobx": "^6.3.10",
18 "mobx-state-tree": "^5.1.0",
17 "react": "^17.0.2", 19 "react": "^17.0.2",
18 "react-dom": "^17.0.2" 20 "react-dom": "^17.0.2"
19 }, 21 },
20 "devDependencies": { 22 "devDependencies": {
21 "@types/react": "^17.0.37", 23 "@types/react": "^17.0.38",
22 "@types/react-dom": "^17.0.11", 24 "@types/react-dom": "^17.0.11",
23 "@vitejs/plugin-react": "^1.1.3", 25 "@vitejs/plugin-react": "^1.1.3",
26 "mst-middlewares": "^5.1.0",
27 "remotedev": "^0.2.9",
24 "typescript": "^4.5.4", 28 "typescript": "^4.5.4",
25 "vite": "^2.7.6" 29 "vite": "^2.7.6"
26 } 30 }
diff --git a/packages/renderer/src/devTools.ts b/packages/renderer/src/devTools.ts
new file mode 100644
index 0000000..5930c48
--- /dev/null
+++ b/packages/renderer/src/devTools.ts
@@ -0,0 +1,37 @@
1import type { IAnyStateTreeNode } from 'mobx-state-tree';
2
3/**
4 * Connects the `model` to the redux devtools extension after loading the required
5 * dependencies asynchronously.
6 *
7 * We have to apply a workaround to load `remotedev` by shimming the `global` object,
8 * because `remotedev` uses an old version of `socketcluster-client` that refers to
9 * `global` instead of `globalThis`.
10 *
11 * Due to the old dependencies, this function is not safe to call in production.
12 * However, we don't bundle `remotedev` in production, so the call would fail anyways.
13 *
14 * @param model The store to connect to the redux devtools.
15 * @see https://github.com/SocketCluster/socketcluster-client/issues/118#issuecomment-469064682
16 */
17async function exposeToReduxDevtoolsAsync(model: IAnyStateTreeNode): Promise<void> {
18 (window as { global?: unknown }).global = window;
19
20 const [remotedev, { connectReduxDevtools }] = await Promise.all([
21 // @ts-ignore
22 import('remotedev'),
23 import('mst-middlewares'),
24 ]);
25 connectReduxDevtools(remotedev, model);
26}
27
28/**
29 * Connects the `model` to the redux devtools extension.
30 *
31 * @param model The store to connect to the redux devtools.
32 */
33export function exposeToReduxDevtools(model: IAnyStateTreeNode): void {
34 exposeToReduxDevtoolsAsync(model).catch((err) => {
35 console.error('Could not connect to Redux devtools', err);
36 });
37}
diff --git a/packages/renderer/src/index.tsx b/packages/renderer/src/index.tsx
index 452448c..37daaa6 100644
--- a/packages/renderer/src/index.tsx
+++ b/packages/renderer/src/index.tsx
@@ -2,6 +2,7 @@ import '@fontsource/roboto/300.css';
2import '@fontsource/roboto/400.css'; 2import '@fontsource/roboto/400.css';
3import '@fontsource/roboto/500.css'; 3import '@fontsource/roboto/500.css';
4import '@fontsource/roboto/700.css'; 4import '@fontsource/roboto/700.css';
5import { applyPatch, applySnapshot } from 'mobx-state-tree';
5import Button from "@mui/material/Button"; 6import Button from "@mui/material/Button";
6import CssBaseline from "@mui/material/CssBaseline"; 7import CssBaseline from "@mui/material/CssBaseline";
7import { 8import {
@@ -10,6 +11,26 @@ import {
10} from '@mui/material/styles'; 11} from '@mui/material/styles';
11import React from 'react'; 12import React from 'react';
12import { render } from 'react-dom'; 13import { render } from 'react-dom';
14import { sharedStore } from '@sophie/shared';
15
16import { exposeToReduxDevtools } from './devTools';
17
18const isDevelopment = import.meta.env.MODE === 'development';
19
20const store = sharedStore.create();
21
22if (isDevelopment) {
23 exposeToReduxDevtools(store);
24}
25
26window.sophieRenderer.setSharedStoreListener({
27 onSnapshot(snapshot) {
28 applySnapshot(store, snapshot);
29 },
30 onPatch(patch) {
31 applyPatch(store, patch);
32 },
33});
13 34
14const theme = createTheme({ 35const theme = createTheme({
15 palette: { 36 palette: {
@@ -24,7 +45,7 @@ function App() {
24 <CssBaseline enableColorScheme /> 45 <CssBaseline enableColorScheme />
25 <Button 46 <Button
26 variant="contained" 47 variant="contained"
27 onClick={window.sophieRenderer.buttonClicked} 48 onClick={window.sophieRenderer.buttonClick}
28 > 49 >
29 Hello Sophie! 50 Hello Sophie!
30 </Button> 51 </Button>
diff --git a/packages/renderer/tsconfig.json b/packages/renderer/tsconfig.json
index 668356c..8746462 100644
--- a/packages/renderer/tsconfig.json
+++ b/packages/renderer/tsconfig.json
@@ -7,6 +7,9 @@
7 "dom", 7 "dom",
8 "dom.iterable", 8 "dom.iterable",
9 "esnext" 9 "esnext"
10 ],
11 "types": [
12 "vite/client"
10 ] 13 ]
11 }, 14 },
12 "references": [ 15 "references": [
diff --git a/packages/renderer/vite.config.js b/packages/renderer/vite.config.js
index ff34b6d..87c2d0c 100644
--- a/packages/renderer/vite.config.js
+++ b/packages/renderer/vite.config.js
@@ -3,7 +3,6 @@
3/* eslint-env node */ 3/* eslint-env node */
4 4
5import { builtinModules } from 'module'; 5import { builtinModules } from 'module';
6import { join } from 'path';
7import react from '@vitejs/plugin-react'; 6import react from '@vitejs/plugin-react';
8 7
9// `resolveJsonModule` is disabled for this package, but vite will load the json nevertheless. 8// `resolveJsonModule` is disabled for this package, but vite will load the json nevertheless.
@@ -36,6 +35,8 @@ const config = {
36 assetsDir: '.', 35 assetsDir: '.',
37 rollupOptions: { 36 rollupOptions: {
38 external: [ 37 external: [
38 'mst-middlewares',
39 'remotedev',
39 ...builtinModules, 40 ...builtinModules,
40 ], 41 ],
41 }, 42 },
diff --git a/packages/shared/package.json b/packages/shared/package.json
index ccde705..f49be47 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -3,6 +3,7 @@
3 "version": "0.1.0", 3 "version": "0.1.0",
4 "private": true, 4 "private": true,
5 "main": "dist/index.cjs", 5 "main": "dist/index.cjs",
6 "module": "dist/index.es.js",
6 "types": "dist/index.d.ts", 7 "types": "dist/index.d.ts",
7 "scripts": { 8 "scripts": {
8 "build": "vite build", 9 "build": "vite build",
@@ -11,5 +12,9 @@
11 "devDependencies": { 12 "devDependencies": {
12 "typescript": "^4.5.4", 13 "typescript": "^4.5.4",
13 "vite": "^2.7.6" 14 "vite": "^2.7.6"
15 },
16 "dependencies": {
17 "mobx": "^6.3.10",
18 "mobx-state-tree": "^5.1.0"
14 } 19 }
15} 20}
diff --git a/packages/shared/src/contextBridge/SophieRenderer.ts b/packages/shared/src/contextBridge/SophieRenderer.ts
index 91a0a3c..c878595 100644
--- a/packages/shared/src/contextBridge/SophieRenderer.ts
+++ b/packages/shared/src/contextBridge/SophieRenderer.ts
@@ -1,3 +1,7 @@
1import { SharedStoreListener } from '../stores/SharedStore';
2
1export interface SophieRenderer { 3export interface SophieRenderer {
2 buttonClicked(): void; 4 setSharedStoreListener(listener: SharedStoreListener): void;
5
6 buttonClick(): void;
3} 7}
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts
index f95675d..7f192bd 100644
--- a/packages/shared/src/index.ts
+++ b/packages/shared/src/index.ts
@@ -1,3 +1,12 @@
1export type { SophieRenderer } from './contextBridge/SophieRenderer'; 1export type { SophieRenderer } from './contextBridge/SophieRenderer';
2 2
3export { RendererIpcMessage } from './ipc/RendererIpcMessage'; 3export { MainToRendererIpcMessage } from './ipc/MainToRendererIpcMessage';
4export { RendererToMainIpcMessage } from './ipc/RendererToMainIpcMessage';
5
6export type {
7 SharedStore,
8 SharedStoreListener,
9 SharedStoreSnapshotIn,
10 SharedStoreSnapshotOut,
11} from './stores/SharedStore';
12export { sharedStore } from './stores/SharedStore';
diff --git a/packages/shared/src/ipc/MainToRendererIpcMessage.ts b/packages/shared/src/ipc/MainToRendererIpcMessage.ts
new file mode 100644
index 0000000..2ddca80
--- /dev/null
+++ b/packages/shared/src/ipc/MainToRendererIpcMessage.ts
@@ -0,0 +1,4 @@
1export enum MainToRendererIpcMessage {
2 SharedStoreSnapshot = "sophie-shared-store-snapshot",
3 SharedStorePatch = "sophie-shared-store-patch",
4}
diff --git a/packages/shared/src/ipc/RendererIpcMessage.ts b/packages/shared/src/ipc/RendererIpcMessage.ts
deleted file mode 100644
index cfb87ae..0000000
--- a/packages/shared/src/ipc/RendererIpcMessage.ts
+++ /dev/null
@@ -1,3 +0,0 @@
1export enum RendererIpcMessage {
2 ButtonClicked = "button-clicked"
3}
diff --git a/packages/shared/src/ipc/RendererToMainIpcMessage.ts b/packages/shared/src/ipc/RendererToMainIpcMessage.ts
new file mode 100644
index 0000000..c4c682d
--- /dev/null
+++ b/packages/shared/src/ipc/RendererToMainIpcMessage.ts
@@ -0,0 +1,4 @@
1export enum RendererToMainIpcMessage {
2 SharedStoreSnapshotRequest = "sophie-shared-store-snapshot-request",
3 ButtonClick = "sophie-button-click"
4}
diff --git a/packages/shared/src/stores/SharedStore.ts b/packages/shared/src/stores/SharedStore.ts
new file mode 100644
index 0000000..8933bca
--- /dev/null
+++ b/packages/shared/src/stores/SharedStore.ts
@@ -0,0 +1,23 @@
1import {
2 IJsonPatch,
3 Instance,
4 types,
5 SnapshotIn,
6 SnapshotOut,
7} from 'mobx-state-tree';
8
9export const sharedStore = types.model("SharedStore", {
10 clickCount: 0
11});
12
13export interface SharedStore extends Instance<typeof sharedStore> {}
14
15export interface SharedStoreSnapshotIn extends SnapshotIn<typeof sharedStore> {}
16
17export interface SharedStoreSnapshotOut extends SnapshotOut<typeof sharedStore> {}
18
19export interface SharedStoreListener {
20 onSnapshot(snapshot: SharedStoreSnapshotIn): void;
21
22 onPatch(patch: IJsonPatch): void;
23}
diff --git a/packages/shared/vite.config.js b/packages/shared/vite.config.js
index cbebb8a..05ec118 100644
--- a/packages/shared/vite.config.js
+++ b/packages/shared/vite.config.js
@@ -26,15 +26,15 @@ const config = {
26 outDir: 'dist', 26 outDir: 'dist',
27 lib: { 27 lib: {
28 entry: 'src/index.ts', 28 entry: 'src/index.ts',
29 formats: ['cjs'], 29 formats: ['cjs', 'es'],
30 fileName: (format) => format === 'cjs' ? 'index.cjs' : `index.${format}.js`,
30 }, 31 },
31 rollupOptions: { 32 rollupOptions: {
32 external: [ 33 external: [
34 'mobx',
35 'mobx-state-tree',
33 ...builtinModules, 36 ...builtinModules,
34 ], 37 ],
35 output: {
36 entryFileNames: '[name].cjs',
37 },
38 }, 38 },
39 emptyOutDir: false, // Do not remove `.d.ts` files. 39 emptyOutDir: false, // Do not remove `.d.ts` files.
40 brotliSize: false, 40 brotliSize: false,