@todesktop/plugin-recall 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/preload.ts ADDED
@@ -0,0 +1,237 @@
1
+ /**
2
+ * ToDesktop Recall Desktop SDK Plugin - Preload Script
3
+ *
4
+ * This file runs in the renderer process with Node.js access and exposes
5
+ * safe APIs to the web application through the contextBridge.
6
+ */
7
+
8
+ import { contextBridge, ipcRenderer } from 'electron';
9
+ import {
10
+ IPC_CHANNELS,
11
+ ApiResponse,
12
+ PluginStatus,
13
+ StartRecordingRequest,
14
+ StopRecordingRequest,
15
+ PauseRecordingRequest,
16
+ ResumeRecordingRequest,
17
+ UploadRecordingRequest,
18
+ PermissionType,
19
+ RecallSdkConfig,
20
+ PrepareDesktopAudioResponse,
21
+ RecallSdkEventType
22
+ } from './shared';
23
+
24
+ /**
25
+ * Recall Desktop SDK API exposed to the renderer process
26
+ */
27
+ const recallDesktopApi = {
28
+ /**
29
+ * Initialize the Recall SDK
30
+ * @returns Promise resolving to initialization result
31
+ */
32
+ async initSdk(): Promise<ApiResponse> {
33
+ return ipcRenderer.invoke(IPC_CHANNELS.INIT_SDK);
34
+ },
35
+
36
+ /**
37
+ * Shutdown the Recall SDK
38
+ * @returns Promise resolving to shutdown result
39
+ */
40
+ async shutdownSdk(): Promise<ApiResponse> {
41
+ return ipcRenderer.invoke(IPC_CHANNELS.SHUTDOWN_SDK);
42
+ },
43
+
44
+ /**
45
+ * Get current plugin and SDK status
46
+ * @returns Promise resolving to plugin status
47
+ */
48
+ async getStatus(): Promise<PluginStatus> {
49
+ return ipcRenderer.invoke(IPC_CHANNELS.GET_STATUS);
50
+ },
51
+
52
+ /**
53
+ * Start recording a meeting
54
+ * @param windowId The meeting window ID
55
+ * @param uploadToken Upload token from your backend
56
+ * @returns Promise resolving to recording start result
57
+ */
58
+ async startRecording(windowId: string, uploadToken: string): Promise<ApiResponse> {
59
+ const request: StartRecordingRequest = { windowId, uploadToken };
60
+ return ipcRenderer.invoke(IPC_CHANNELS.START_RECORDING, request);
61
+ },
62
+
63
+ /**
64
+ * Stop recording a meeting
65
+ * @param windowId The meeting window ID
66
+ * @returns Promise resolving to recording stop result
67
+ */
68
+ async stopRecording(windowId: string): Promise<ApiResponse> {
69
+ const request: StopRecordingRequest = { windowId };
70
+ return ipcRenderer.invoke(IPC_CHANNELS.STOP_RECORDING, request);
71
+ },
72
+
73
+ /**
74
+ * Pause recording a meeting
75
+ * @param windowId The meeting window ID
76
+ * @returns Promise resolving to recording pause result
77
+ */
78
+ async pauseRecording(windowId: string): Promise<ApiResponse> {
79
+ const request: PauseRecordingRequest = { windowId };
80
+ return ipcRenderer.invoke(IPC_CHANNELS.PAUSE_RECORDING, request);
81
+ },
82
+
83
+ /**
84
+ * Resume recording a meeting
85
+ * @param windowId The meeting window ID
86
+ * @returns Promise resolving to recording resume result
87
+ */
88
+ async resumeRecording(windowId: string): Promise<ApiResponse> {
89
+ const request: ResumeRecordingRequest = { windowId };
90
+ return ipcRenderer.invoke(IPC_CHANNELS.RESUME_RECORDING, request);
91
+ },
92
+
93
+ /**
94
+ * Upload a completed recording
95
+ * @param windowId The meeting window ID
96
+ * @returns Promise resolving to upload start result
97
+ */
98
+ async uploadRecording(windowId: string): Promise<ApiResponse> {
99
+ const request: UploadRecordingRequest = { windowId };
100
+ return ipcRenderer.invoke(IPC_CHANNELS.UPLOAD_RECORDING, request);
101
+ },
102
+
103
+ /**
104
+ * Prepare desktop audio recording for non-meeting audio capture
105
+ * @returns Promise resolving to desktop audio preparation result
106
+ */
107
+ async prepareDesktopAudioRecording(): Promise<ApiResponse<PrepareDesktopAudioResponse>> {
108
+ return ipcRenderer.invoke(IPC_CHANNELS.PREPARE_DESKTOP_AUDIO);
109
+ },
110
+
111
+ /**
112
+ * Request a specific permission from the user
113
+ * @param permission The permission to request
114
+ * @returns Promise resolving to permission request result
115
+ */
116
+ async requestPermission(permission: PermissionType): Promise<ApiResponse> {
117
+ return ipcRenderer.invoke(IPC_CHANNELS.REQUEST_PERMISSION, permission);
118
+ },
119
+
120
+ /**
121
+ * Update plugin configuration
122
+ * @param config Configuration updates
123
+ * @returns Promise resolving to update result
124
+ */
125
+ async setConfig(config: Partial<RecallSdkConfig>): Promise<ApiResponse> {
126
+ return ipcRenderer.invoke(IPC_CHANNELS.SET_CONFIG, config);
127
+ },
128
+
129
+ /**
130
+ * Get current plugin configuration
131
+ * @returns Promise resolving to current configuration
132
+ */
133
+ async getConfig(): Promise<ApiResponse<RecallSdkConfig>> {
134
+ return ipcRenderer.invoke(IPC_CHANNELS.GET_CONFIG);
135
+ },
136
+
137
+ /**
138
+ * Subscribe to SDK events
139
+ * @param eventType The type of event to listen for
140
+ * @param callback Function to call when event occurs
141
+ * @returns Function to unsubscribe from the event
142
+ */
143
+ addEventListener(eventType: RecallSdkEventType, callback: (data: any) => void): () => void {
144
+ const channel = `recall-desktop:event:${eventType}`;
145
+
146
+ // Fire-and-forget subscribe to main
147
+ ipcRenderer.invoke(IPC_CHANNELS.SUBSCRIBE_EVENTS, eventType).catch(console.error);
148
+
149
+ const listener = (_event: any, data: any) => {
150
+ callback(data);
151
+ };
152
+ ipcRenderer.on(channel, listener);
153
+
154
+ // Return unsubscribe function
155
+ return () => {
156
+ ipcRenderer.removeListener(channel, listener);
157
+ ipcRenderer.invoke(IPC_CHANNELS.UNSUBSCRIBE_EVENTS, eventType).catch(console.error);
158
+ };
159
+ },
160
+
161
+ /**
162
+ * Get plugin version
163
+ * @returns Plugin version string
164
+ */
165
+ getVersion(): string {
166
+ return '1.0.0';
167
+ },
168
+
169
+ /**
170
+ * Convenience method for handling meeting detection events
171
+ * @param callback Function to call when a meeting is detected
172
+ * @returns Function to unsubscribe from the event
173
+ */
174
+ onMeetingDetected(callback: (meetingData: any) => void): () => void {
175
+ return this.addEventListener('meeting-detected', callback);
176
+ },
177
+
178
+ /**
179
+ * Convenience method for handling recording state changes
180
+ * @param callback Function to call when recording state changes
181
+ * @returns Function to unsubscribe from the event
182
+ */
183
+ onRecordingStateChange(callback: (stateData: any) => void): () => void {
184
+ return this.addEventListener('sdk-state-change', callback);
185
+ },
186
+
187
+ /**
188
+ * Convenience method for handling upload progress updates
189
+ * @param callback Function to call when upload progress updates
190
+ * @returns Function to unsubscribe from the event
191
+ */
192
+ onUploadProgress(callback: (progressData: any) => void): () => void {
193
+ return this.addEventListener('upload-progress', callback);
194
+ },
195
+
196
+ /**
197
+ * Convenience method for handling permission status updates
198
+ * @param callback Function to call when permission status changes
199
+ * @returns Function to unsubscribe from the event
200
+ */
201
+ onPermissionStatusChange(callback: (permissionData: any) => void): () => void {
202
+ return this.addEventListener('permission-status', callback);
203
+ },
204
+
205
+ /**
206
+ * Convenience method for handling SDK errors
207
+ * @param callback Function to call when SDK errors occur
208
+ * @returns Function to unsubscribe from the event
209
+ */
210
+ onError(callback: (errorData: any) => void): () => void {
211
+ return this.addEventListener('error', callback);
212
+ },
213
+
214
+ /**
215
+ * Convenience method for handling real-time events (transcription, participants, etc.)
216
+ * @param callback Function to call when real-time events occur
217
+ * @returns Function to unsubscribe from the event
218
+ */
219
+ onRealtimeEvent(callback: (realtimeData: any) => void): () => void {
220
+ return this.addEventListener('realtime-event', callback);
221
+ }
222
+ };
223
+
224
+ // Export the API type for TypeScript support
225
+ export type RecallDesktopApi = typeof recallDesktopApi;
226
+
227
+ // Expose the API to the renderer process
228
+ contextBridge.exposeInMainWorld('recallDesktop', recallDesktopApi);
229
+
230
+ // Extend the global Window interface for TypeScript
231
+ declare global {
232
+ interface Window {
233
+ recallDesktop: RecallDesktopApi;
234
+ }
235
+ }
236
+
237
+ console.log('RecallDesktop: Preload script loaded successfully');
package/src/shared.ts ADDED
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Shared types and constants for Recall Desktop SDK integration
3
+ */
4
+
5
+ // IPC channel names - use unique namespace to avoid conflicts
6
+ export const IPC_CHANNELS = {
7
+ // SDK lifecycle
8
+ INIT_SDK: 'recall-desktop:init-sdk',
9
+ SHUTDOWN_SDK: 'recall-desktop:shutdown-sdk',
10
+ GET_STATUS: 'recall-desktop:get-status',
11
+
12
+ // Recording management
13
+ START_RECORDING: 'recall-desktop:start-recording',
14
+ STOP_RECORDING: 'recall-desktop:stop-recording',
15
+ PAUSE_RECORDING: 'recall-desktop:pause-recording',
16
+ RESUME_RECORDING: 'recall-desktop:resume-recording',
17
+ UPLOAD_RECORDING: 'recall-desktop:upload-recording',
18
+
19
+ // Desktop audio recording
20
+ PREPARE_DESKTOP_AUDIO: 'recall-desktop:prepare-desktop-audio',
21
+
22
+ // Permission management
23
+ REQUEST_PERMISSION: 'recall-desktop:request-permission',
24
+
25
+ // Configuration
26
+ SET_CONFIG: 'recall-desktop:set-config',
27
+ GET_CONFIG: 'recall-desktop:get-config',
28
+
29
+ // Event subscription
30
+ SUBSCRIBE_EVENTS: 'recall-desktop:subscribe-events',
31
+ UNSUBSCRIBE_EVENTS: 'recall-desktop:unsubscribe-events',
32
+ } as const;
33
+
34
+ // Recall SDK Configuration (mirrors RecallAiSdkConfig where applicable)
35
+ export interface RecallSdkConfig {
36
+ enabled: boolean;
37
+ apiUrl: string;
38
+ requestPermissionsOnStartup: boolean;
39
+ }
40
+
41
+ // Meeting window information from SDK
42
+ export interface MeetingWindow {
43
+ id: string;
44
+ title?: string;
45
+ url?: string;
46
+ platform: string;
47
+ }
48
+
49
+ // Recording request/response types
50
+ export interface StartRecordingRequest {
51
+ windowId: string;
52
+ uploadToken: string;
53
+ }
54
+
55
+ export interface StopRecordingRequest {
56
+ windowId: string;
57
+ }
58
+
59
+ export interface PauseRecordingRequest {
60
+ windowId: string;
61
+ }
62
+
63
+ export interface ResumeRecordingRequest {
64
+ windowId: string;
65
+ }
66
+
67
+ export interface UploadRecordingRequest {
68
+ windowId: string;
69
+ }
70
+
71
+ // SDK Events from Recall SDK (mirror upstream)
72
+ export type RecallSdkEventType =
73
+ | 'recording-started'
74
+ | 'recording-ended'
75
+ | 'upload-progress'
76
+ | 'meeting-detected'
77
+ | 'meeting-updated'
78
+ | 'meeting-closed'
79
+ | 'sdk-state-change'
80
+ | 'error'
81
+ | 'media-capture-status'
82
+ | 'participant-capture-status'
83
+ | 'permissions-granted'
84
+ | 'permission-status'
85
+ | 'realtime-event'
86
+ | 'shutdown';
87
+
88
+ export interface RecallSdkEvent {
89
+ type: RecallSdkEventType;
90
+ data: any;
91
+ }
92
+
93
+ // SDK Event payloads
94
+ export interface MeetingDetectedEvent {
95
+ window: MeetingWindow;
96
+ }
97
+
98
+ export interface SdkStateChangeEvent {
99
+ sdk: {
100
+ state: {
101
+ code: 'recording' | 'idle' | 'paused';
102
+ };
103
+ };
104
+ }
105
+
106
+ export interface RecordingStartedEvent {
107
+ window: MeetingWindow;
108
+ }
109
+
110
+ export interface RecordingEndedEvent {
111
+ window: MeetingWindow;
112
+ }
113
+
114
+ export interface MeetingClosedEvent {
115
+ window: MeetingWindow;
116
+ }
117
+
118
+ export interface UploadProgressEvent {
119
+ window: { id: string };
120
+ progress: number; // 0-100
121
+ }
122
+
123
+ export interface MeetingUpdatedEvent {
124
+ window: MeetingWindow;
125
+ }
126
+
127
+ export interface MediaCaptureStatusEvent {
128
+ window: MeetingWindow;
129
+ type: 'video' | 'audio';
130
+ capturing: boolean;
131
+ }
132
+
133
+ export interface ParticipantCaptureStatusEvent {
134
+ window: MeetingWindow;
135
+ type: 'video' | 'audio' | 'screenshare';
136
+ capturing: boolean;
137
+ }
138
+
139
+ export interface RealtimeEvent {
140
+ window: MeetingWindow;
141
+ event: string;
142
+ data: any;
143
+ }
144
+
145
+ export interface SdkErrorEvent {
146
+ window?: MeetingWindow;
147
+ type: string;
148
+ message: string;
149
+ }
150
+
151
+ export interface PermissionStatusEvent {
152
+ permission: PermissionType;
153
+ status: string;
154
+ }
155
+
156
+ export interface ShutdownEvent {
157
+ code: number;
158
+ signal: string;
159
+ }
160
+
161
+ // Permission types (mirror upstream)
162
+ export type PermissionType = 'accessibility' | 'screen-capture' | 'microphone' | 'system-audio';
163
+
164
+ // API Response types
165
+ export interface ApiResponse<T = any> {
166
+ success: boolean;
167
+ message: string;
168
+ data?: T;
169
+ }
170
+
171
+ // Plugin status
172
+ export interface PluginStatus {
173
+ initialized: boolean;
174
+ sdkInitialized: boolean;
175
+ version: string;
176
+ config: RecallSdkConfig;
177
+ sdkState?: 'recording' | 'idle' | 'paused';
178
+ permissions?: {
179
+ accessibility: boolean;
180
+ screenCapture: boolean;
181
+ microphone: boolean;
182
+ systemAudio: boolean;
183
+ };
184
+ }
185
+
186
+ // Error types
187
+ export class RecallSdkError extends Error {
188
+ constructor(message: string, public code?: string) {
189
+ super(message);
190
+ this.name = 'RecallSdkError';
191
+ }
192
+ }
193
+
194
+ // SDK Initialization options
195
+ export interface SdkInitOptions {
196
+ apiUrl: string;
197
+ acquirePermissionsOnStartup?: PermissionType[];
198
+ restartOnError?: boolean;
199
+ }
200
+
201
+ // Desktop audio recording response
202
+ export interface PrepareDesktopAudioResponse {
203
+ windowId: string;
204
+ }
package/src/store.ts ADDED
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Recall Desktop SDK plugin state management and storage
3
+ */
4
+
5
+ import { RecallSdkConfig, MeetingWindow, PermissionType } from './shared';
6
+
7
+ class RecallSdkStore {
8
+ private config: RecallSdkConfig = {
9
+ enabled: true,
10
+ apiUrl: 'https://us-east-1.recall.ai',
11
+ requestPermissionsOnStartup: true,
12
+ };
13
+
14
+ private initialized = false;
15
+ private sdkInitialized = false;
16
+ private currentSdkState: 'recording' | 'idle' | 'paused' = 'idle';
17
+
18
+ // Active meetings and recordings
19
+ private activeMeetings = new Map<string, MeetingWindow>();
20
+ private activeRecordings = new Map<string, { window: MeetingWindow; uploadToken: string }>();
21
+
22
+ // Permission status
23
+ private permissions = {
24
+ accessibility: false,
25
+ screenCapture: false,
26
+ microphone: false,
27
+ systemAudio: false,
28
+ };
29
+
30
+ // Event listeners for SDK events
31
+ private eventListeners = new Set<(event: any) => void>();
32
+
33
+ /**
34
+ * Initialize the plugin store
35
+ */
36
+ async initialize(): Promise<void> {
37
+ // Load configuration from ToDesktop preferences
38
+ try {
39
+ // In a real implementation, this would load from ToDesktop's preference system
40
+ // For now, we'll use the defaults
41
+ this.initialized = true;
42
+ console.log('RecallSdkStore: Initialized successfully');
43
+ } catch (error) {
44
+ console.error('RecallSdkStore: Failed to initialize:', error);
45
+ throw error;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Get current plugin configuration
51
+ */
52
+ getConfig(): RecallSdkConfig {
53
+ return { ...this.config };
54
+ }
55
+
56
+ /**
57
+ * Update plugin configuration
58
+ */
59
+ setConfig(updates: Partial<RecallSdkConfig>): void {
60
+ this.config = { ...this.config, ...updates };
61
+ console.log('RecallSdkStore: Configuration updated:', this.config);
62
+ }
63
+
64
+ /**
65
+ * Load configuration from ToDesktop preferences
66
+ */
67
+ loadFromPreferences(preferences: Record<string, any>): void {
68
+ if (preferences.enabled !== undefined) {
69
+ this.config.enabled = preferences.enabled;
70
+ }
71
+ if (preferences.apiUrl !== undefined) {
72
+ this.config.apiUrl = preferences.apiUrl;
73
+ }
74
+ // autoRecord removed by design
75
+ if (preferences.requestPermissionsOnStartup !== undefined) {
76
+ this.config.requestPermissionsOnStartup = preferences.requestPermissionsOnStartup;
77
+ }
78
+ console.log('RecallSdkStore: Loaded configuration from preferences:', this.config);
79
+ }
80
+
81
+ /**
82
+ * Check if plugin is initialized
83
+ */
84
+ isInitialized(): boolean {
85
+ return this.initialized;
86
+ }
87
+
88
+ /**
89
+ * Check if plugin is enabled
90
+ */
91
+ isEnabled(): boolean {
92
+ return this.config.enabled;
93
+ }
94
+
95
+ /**
96
+ * Set SDK initialization status
97
+ */
98
+ setSdkInitialized(initialized: boolean): void {
99
+ this.sdkInitialized = initialized;
100
+ }
101
+
102
+ /**
103
+ * Check if SDK is initialized
104
+ */
105
+ isSdkInitialized(): boolean {
106
+ return this.sdkInitialized;
107
+ }
108
+
109
+ /**
110
+ * Set current SDK state
111
+ */
112
+ setSdkState(state: 'recording' | 'idle' | 'paused'): void {
113
+ this.currentSdkState = state;
114
+ }
115
+
116
+ /**
117
+ * Get current SDK state
118
+ */
119
+ getSdkState(): 'recording' | 'idle' | 'paused' {
120
+ return this.currentSdkState;
121
+ }
122
+
123
+ /**
124
+ * Add an active meeting
125
+ */
126
+ addMeeting(meeting: MeetingWindow): void {
127
+ this.activeMeetings.set(meeting.id, meeting);
128
+ console.log(`RecallSdkStore: Added meeting ${meeting.id}:`, meeting);
129
+ }
130
+
131
+ /**
132
+ * Remove a meeting
133
+ */
134
+ removeMeeting(windowId: string): void {
135
+ this.activeMeetings.delete(windowId);
136
+ console.log(`RecallSdkStore: Removed meeting ${windowId}`);
137
+ }
138
+
139
+ /**
140
+ * Get active meeting by window ID
141
+ */
142
+ getMeeting(windowId: string): MeetingWindow | undefined {
143
+ return this.activeMeetings.get(windowId);
144
+ }
145
+
146
+ /**
147
+ * Get all active meetings
148
+ */
149
+ getAllMeetings(): MeetingWindow[] {
150
+ return Array.from(this.activeMeetings.values());
151
+ }
152
+
153
+ /**
154
+ * Start a recording
155
+ */
156
+ startRecording(windowId: string, uploadToken: string): void {
157
+ const window = this.activeMeetings.get(windowId);
158
+ if (window) {
159
+ this.activeRecordings.set(windowId, { window, uploadToken });
160
+ console.log(`RecallSdkStore: Started recording for ${windowId}`);
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Stop a recording
166
+ */
167
+ stopRecording(windowId: string): void {
168
+ this.activeRecordings.delete(windowId);
169
+ console.log(`RecallSdkStore: Stopped recording for ${windowId}`);
170
+ }
171
+
172
+ /**
173
+ * Get active recording by window ID
174
+ */
175
+ getRecording(windowId: string): { window: MeetingWindow; uploadToken: string } | undefined {
176
+ return this.activeRecordings.get(windowId);
177
+ }
178
+
179
+ /**
180
+ * Get all active recordings
181
+ */
182
+ getAllRecordings(): { window: MeetingWindow; uploadToken: string }[] {
183
+ return Array.from(this.activeRecordings.values());
184
+ }
185
+
186
+ /**
187
+ * Update permission status
188
+ */
189
+ setPermissionStatus(permission: PermissionType, status: string): void {
190
+ const granted = status === 'granted' || status === 'authorized' || status === 'ALLOWED';
191
+ if (permission === 'screen-capture') {
192
+ this.permissions.screenCapture = granted;
193
+ } else if (permission === 'system-audio') {
194
+ this.permissions.systemAudio = granted;
195
+ } else {
196
+ // permission is 'accessibility' | 'microphone'
197
+ // @ts-ignore - index by key
198
+ this.permissions[permission] = granted;
199
+ }
200
+ console.log(`RecallSdkStore: Permission ${permission} status: ${status}`);
201
+ }
202
+
203
+ /**
204
+ * Get permission status
205
+ */
206
+ getPermissions(): { accessibility: boolean; screenCapture: boolean; microphone: boolean; systemAudio: boolean } {
207
+ return { ...this.permissions };
208
+ }
209
+
210
+ /**
211
+ * Check if all required permissions are granted
212
+ */
213
+ arePermissionsGranted(): boolean {
214
+ return (
215
+ this.permissions.accessibility &&
216
+ this.permissions.screenCapture &&
217
+ this.permissions.microphone
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Add event listener for SDK events
223
+ */
224
+ addEventListener(listener: (event: any) => void): void {
225
+ this.eventListeners.add(listener);
226
+ }
227
+
228
+ /**
229
+ * Remove event listener
230
+ */
231
+ removeEventListener(listener: (event: any) => void): void {
232
+ this.eventListeners.delete(listener);
233
+ }
234
+
235
+ /**
236
+ * Emit event to all listeners
237
+ */
238
+ emitEvent(event: any): void {
239
+ this.eventListeners.forEach(listener => {
240
+ try {
241
+ listener(event);
242
+ } catch (error) {
243
+ console.error('RecallSdkStore: Error in event listener:', error);
244
+ }
245
+ });
246
+ }
247
+
248
+ /**
249
+ * Clear all state (useful for shutdown/reset)
250
+ */
251
+ clearState(): void {
252
+ this.activeMeetings.clear();
253
+ this.activeRecordings.clear();
254
+ this.setSdkInitialized(false);
255
+ this.setSdkState('idle');
256
+ this.permissions = {
257
+ accessibility: false,
258
+ screenCapture: false,
259
+ microphone: false,
260
+ systemAudio: false,
261
+ };
262
+ console.log('RecallSdkStore: Cleared all state');
263
+ }
264
+ }
265
+
266
+ export const recallSdkStore = new RecallSdkStore();
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "composite": true,
7
+ "types": ["node", "electron"]
8
+ },
9
+ "include": ["src/**/*"],
10
+ "exclude": ["dist", "node_modules", "**/*.test.ts", "**/*.spec.ts"]
11
+ }