@rimori/client 1.4.0 → 1.4.4
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/README.md +77 -71
- package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
- package/dist/cli/scripts/init/dev-registration.js +4 -4
- package/dist/cli/scripts/init/main.js +1 -1
- package/dist/cli/scripts/init/package-setup.d.ts +1 -1
- package/dist/cli/scripts/init/package-setup.js +3 -3
- package/dist/cli/scripts/init/router-transformer.js +19 -12
- package/dist/cli/scripts/init/vite-config.d.ts +2 -2
- package/dist/cli/scripts/init/vite-config.js +2 -2
- package/dist/cli/scripts/release/release-config-upload.js +9 -9
- package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
- package/dist/cli/scripts/release/release-db-update.js +9 -9
- package/dist/cli/scripts/release/release-file-upload.js +1 -1
- package/dist/cli/scripts/release/release.js +2 -2
- package/dist/components/CRUDModal.d.ts +1 -1
- package/dist/components/CRUDModal.js +3 -3
- package/dist/components/MarkdownEditor.js +16 -16
- package/dist/components/Spinner.js +2 -2
- package/dist/components/ai/Assistant.js +7 -8
- package/dist/components/ai/Avatar.d.ts +2 -2
- package/dist/components/ai/Avatar.js +10 -5
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
- package/dist/components/audio/Playbutton.js +10 -7
- package/dist/components/components/ContextMenu.d.ts +1 -1
- package/dist/components/components/ContextMenu.js +19 -16
- package/dist/components.d.ts +10 -10
- package/dist/components.js +10 -10
- package/dist/core/controller/AIController.d.ts +2 -2
- package/dist/core/controller/AIController.js +12 -12
- package/dist/core/controller/ExerciseController.d.ts +2 -2
- package/dist/core/controller/ExerciseController.js +2 -2
- package/dist/core/controller/ObjectController.js +5 -5
- package/dist/core/controller/SettingsController.d.ts +22 -7
- package/dist/core/controller/SettingsController.js +73 -8
- package/dist/core/controller/SharedContentController.d.ts +3 -3
- package/dist/core/controller/SharedContentController.js +38 -20
- package/dist/core/controller/VoiceController.js +6 -4
- package/dist/core/core.d.ts +15 -15
- package/dist/core/core.js +7 -7
- package/dist/fromRimori/EventBus.js +23 -23
- package/dist/fromRimori/PluginTypes.d.ts +4 -4
- package/dist/hooks/UseChatHook.d.ts +3 -3
- package/dist/hooks/UseChatHook.js +9 -3
- package/dist/index.d.ts +10 -10
- package/dist/index.js +9 -9
- package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
- package/dist/plugin/AccomplishmentHandler.js +31 -27
- package/dist/plugin/AudioController.d.ts +1 -1
- package/dist/plugin/AudioController.js +6 -6
- package/dist/plugin/Logger.js +15 -13
- package/dist/plugin/PluginController.d.ts +7 -1
- package/dist/plugin/PluginController.js +32 -27
- package/dist/plugin/RimoriClient.d.ts +17 -18
- package/dist/plugin/RimoriClient.js +31 -31
- package/dist/plugin/StandaloneClient.d.ts +1 -1
- package/dist/plugin/StandaloneClient.js +35 -16
- package/dist/plugin/ThemeSetter.js +4 -4
- package/dist/providers/PluginProvider.js +44 -14
- package/dist/utils/Language.js +57 -57
- package/dist/utils/PluginUtils.js +3 -3
- package/dist/utils/difficultyConverter.d.ts +1 -1
- package/dist/utils/difficultyConverter.js +1 -1
- package/dist/utils/endpoint.js +2 -2
- package/dist/worker/WorkerSetup.d.ts +1 -1
- package/dist/worker/WorkerSetup.js +6 -6
- package/example/docs/devdocs.md +50 -40
- package/example/docs/overview.md +1 -1
- package/example/docs/userdocs.md +4 -1
- package/example/rimori.config.ts +51 -49
- package/example/worker/vite.config.ts +3 -3
- package/example/worker/worker.ts +2 -2
- package/package.json +14 -8
- package/prettier.config.js +1 -1
- package/src/cli/scripts/init/dev-registration.ts +5 -8
- package/src/cli/scripts/init/env-setup.ts +1 -1
- package/src/cli/scripts/init/file-operations.ts +1 -1
- package/src/cli/scripts/init/html-cleaner.ts +2 -5
- package/src/cli/scripts/init/main.ts +16 -13
- package/src/cli/scripts/init/package-setup.ts +11 -15
- package/src/cli/scripts/init/router-transformer.ts +40 -37
- package/src/cli/scripts/init/tailwind-config.ts +17 -26
- package/src/cli/scripts/init/vite-config.ts +3 -3
- package/src/cli/scripts/release/release-config-upload.ts +11 -11
- package/src/cli/scripts/release/release-db-update.ts +12 -12
- package/src/cli/scripts/release/release-file-upload.ts +2 -2
- package/src/cli/scripts/release/release.ts +4 -4
- package/src/cli/types/DatabaseTypes.ts +2 -10
- package/src/components/CRUDModal.tsx +64 -48
- package/src/components/MarkdownEditor.tsx +58 -27
- package/src/components/Spinner.tsx +24 -17
- package/src/components/ai/Assistant.tsx +70 -70
- package/src/components/ai/Avatar.tsx +17 -14
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +3 -4
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
- package/src/components/ai/utils.ts +4 -4
- package/src/components/audio/Playbutton.tsx +101 -93
- package/src/components/components/ContextMenu.tsx +47 -35
- package/src/components.ts +10 -10
- package/src/core/controller/AIController.ts +29 -19
- package/src/core/controller/ExerciseController.ts +16 -23
- package/src/core/controller/ObjectController.ts +15 -10
- package/src/core/controller/SettingsController.ts +89 -16
- package/src/core/controller/SharedContentController.ts +80 -44
- package/src/core/controller/VoiceController.ts +10 -8
- package/src/core/core.ts +15 -16
- package/src/fromRimori/EventBus.ts +76 -47
- package/src/fromRimori/PluginTypes.ts +26 -17
- package/src/fromRimori/readme.md +2 -2
- package/src/hooks/UseChatHook.ts +25 -15
- package/src/index.ts +10 -10
- package/src/plugin/AccomplishmentHandler.ts +53 -35
- package/src/plugin/AudioController.ts +18 -12
- package/src/plugin/Logger.ts +28 -21
- package/src/plugin/PluginController.ts +60 -44
- package/src/plugin/RimoriClient.ts +102 -72
- package/src/plugin/StandaloneClient.ts +51 -24
- package/src/plugin/ThemeSetter.ts +5 -5
- package/src/providers/PluginProvider.tsx +90 -36
- package/src/style.scss +3 -3
- package/src/utils/Language.ts +58 -58
- package/src/utils/PluginUtils.ts +16 -20
- package/src/utils/difficultyConverter.ts +2 -2
- package/src/utils/endpoint.ts +3 -2
- package/src/worker/WorkerSetup.ts +8 -9
- package/tsconfig.json +2 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { EventBus } from
|
|
1
|
+
import { EventBus } from '../fromRimori/EventBus';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* AudioController is a class that provides methods to record audio. It is a wrapper around the Capacitor Voice Recorder plugin. For more information, see https://github.com/tchvu3/capacitor-voice-recorder.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* @example
|
|
7
7
|
* const audioController = new AudioController();
|
|
8
8
|
* await audioController.startRecording();
|
|
@@ -16,43 +16,49 @@ export class AudioController {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Start the recording.
|
|
19
|
-
*
|
|
19
|
+
*
|
|
20
20
|
* @example
|
|
21
21
|
* const audioController = new AudioController();
|
|
22
22
|
* await audioController.startRecording();
|
|
23
23
|
* @returns void
|
|
24
24
|
*/
|
|
25
25
|
public async startRecording(): Promise<void> {
|
|
26
|
-
EventBus.emit(this.pluginId,
|
|
26
|
+
EventBus.emit(this.pluginId, 'global.microphone.triggerStartRecording');
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Stop the recording and return the audio data.
|
|
31
31
|
* @returns The audio data.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
34
|
* const audioRef = new Audio(`data:${mimeType};base64,${base64Sound}`)
|
|
35
35
|
* audioRef.oncanplaythrough = () => audioRef.play()
|
|
36
36
|
* audioRef.load()
|
|
37
37
|
*/
|
|
38
|
-
public async stopRecording(): Promise<{ recording: Blob
|
|
39
|
-
const result = await EventBus.request<{ recording: Blob
|
|
38
|
+
public async stopRecording(): Promise<{ recording: Blob; msDuration: number; mimeType: string }> {
|
|
39
|
+
const result = await EventBus.request<{ recording: Blob; msDuration: number; mimeType: string }>(
|
|
40
|
+
this.pluginId,
|
|
41
|
+
'global.microphone.triggerStopRecording',
|
|
42
|
+
);
|
|
40
43
|
|
|
41
44
|
return result.data;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
public async pauseRecording(): Promise<boolean> {
|
|
45
|
-
const result = await EventBus.request<boolean>(this.pluginId,
|
|
48
|
+
const result = await EventBus.request<boolean>(this.pluginId, 'global.microphone.triggerPauseRecording');
|
|
46
49
|
return result.data;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
public async resumeRecording(): Promise<boolean> {
|
|
50
|
-
const result = await EventBus.request<boolean>(this.pluginId,
|
|
53
|
+
const result = await EventBus.request<boolean>(this.pluginId, 'global.microphone.triggerResumeRecording');
|
|
51
54
|
return result.data;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
|
-
public async getCurrentStatus(): Promise<
|
|
55
|
-
const result = await EventBus.request<
|
|
57
|
+
public async getCurrentStatus(): Promise<'RECORDING' | 'PAUSED' | 'NONE'> {
|
|
58
|
+
const result = await EventBus.request<'RECORDING' | 'PAUSED' | 'NONE'>(
|
|
59
|
+
this.pluginId,
|
|
60
|
+
'global.microphone.triggerGetCurrentStatus',
|
|
61
|
+
);
|
|
56
62
|
return result.data;
|
|
57
63
|
}
|
|
58
64
|
}
|
package/src/plugin/Logger.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class Logger {
|
|
|
62
62
|
info: console.info,
|
|
63
63
|
warn: console.warn,
|
|
64
64
|
error: console.error,
|
|
65
|
-
debug: console.debug
|
|
65
|
+
debug: console.debug,
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
// Override console methods globally
|
|
@@ -82,8 +82,8 @@ export class Logger {
|
|
|
82
82
|
const logs = {
|
|
83
83
|
logs: this.logs,
|
|
84
84
|
pluginId: rimori.plugin.pluginId,
|
|
85
|
-
timestamp: new Date().toISOString()
|
|
86
|
-
}
|
|
85
|
+
timestamp: new Date().toISOString(),
|
|
86
|
+
};
|
|
87
87
|
this.logs = [];
|
|
88
88
|
this.logIdCounter = 0;
|
|
89
89
|
return logs;
|
|
@@ -129,7 +129,7 @@ export class Logger {
|
|
|
129
129
|
if (typeof window === 'undefined' || typeof history === 'undefined') return;
|
|
130
130
|
|
|
131
131
|
// Clear logs on browser back/forward
|
|
132
|
-
window.addEventListener('popstate', () => this.logs = []);
|
|
132
|
+
window.addEventListener('popstate', () => (this.logs = []));
|
|
133
133
|
|
|
134
134
|
// Override history methods to clear logs on programmatic navigation
|
|
135
135
|
const originalPushState = history.pushState;
|
|
@@ -158,7 +158,7 @@ export class Logger {
|
|
|
158
158
|
setInterval(checkUrlChange, 100);
|
|
159
159
|
|
|
160
160
|
// Also listen for hash changes (for hash-based routing)
|
|
161
|
-
window.addEventListener('hashchange', () => this.logs = []);
|
|
161
|
+
window.addEventListener('hashchange', () => (this.logs = []));
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
/**
|
|
@@ -206,8 +206,8 @@ export class Logger {
|
|
|
206
206
|
* @returns Object with location string and CSS style, or empty values for production
|
|
207
207
|
*/
|
|
208
208
|
private getCallerLocation(): { location: string; style: string } {
|
|
209
|
-
const emptyResult = { location:
|
|
210
|
-
const style =
|
|
209
|
+
const emptyResult = { location: '', style: '' };
|
|
210
|
+
const style = 'color: #0063A2; font-weight: bold;';
|
|
211
211
|
|
|
212
212
|
if (this.isProduction) return emptyResult;
|
|
213
213
|
|
|
@@ -251,7 +251,7 @@ export class Logger {
|
|
|
251
251
|
this.mousePosition = {
|
|
252
252
|
x: event.clientX,
|
|
253
253
|
y: event.clientY,
|
|
254
|
-
timestamp: new Date().toISOString()
|
|
254
|
+
timestamp: new Date().toISOString(),
|
|
255
255
|
};
|
|
256
256
|
};
|
|
257
257
|
|
|
@@ -272,14 +272,16 @@ export class Logger {
|
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
// Convert console arguments to message and data
|
|
275
|
-
const message = args
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
275
|
+
const message = args
|
|
276
|
+
.map((arg) => {
|
|
277
|
+
if (typeof arg !== 'object') return arg;
|
|
278
|
+
try {
|
|
279
|
+
return JSON.stringify(arg);
|
|
280
|
+
} catch (error: any) {
|
|
281
|
+
return 'Error adding object to log: ' + error.message + ' ' + String(arg);
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
.join(' ');
|
|
283
285
|
|
|
284
286
|
const data = args.length > 1 ? args.slice(1) : undefined;
|
|
285
287
|
|
|
@@ -299,7 +301,7 @@ export class Logger {
|
|
|
299
301
|
onLine: navigator.onLine,
|
|
300
302
|
screenResolution: `${screen.width}x${screen.height}`,
|
|
301
303
|
windowSize: `${window.innerWidth}x${window.innerHeight}`,
|
|
302
|
-
timestamp: new Date().toISOString()
|
|
304
|
+
timestamp: new Date().toISOString(),
|
|
303
305
|
};
|
|
304
306
|
}
|
|
305
307
|
|
|
@@ -324,7 +326,12 @@ export class Logger {
|
|
|
324
326
|
* @param data - Additional data
|
|
325
327
|
* @returns Log entry
|
|
326
328
|
*/
|
|
327
|
-
private async createLogEntry(
|
|
329
|
+
private async createLogEntry(
|
|
330
|
+
level: LogLevel,
|
|
331
|
+
message: string,
|
|
332
|
+
data?: any,
|
|
333
|
+
forceScreenshot?: boolean,
|
|
334
|
+
): Promise<LogEntry> {
|
|
328
335
|
const context: Partial<LogEntry['context']> = {};
|
|
329
336
|
|
|
330
337
|
// Add URL if available
|
|
@@ -335,7 +342,7 @@ export class Logger {
|
|
|
335
342
|
level,
|
|
336
343
|
message,
|
|
337
344
|
data,
|
|
338
|
-
}
|
|
345
|
+
};
|
|
339
346
|
}
|
|
340
347
|
|
|
341
348
|
context.url = window.location.href;
|
|
@@ -346,7 +353,7 @@ export class Logger {
|
|
|
346
353
|
|
|
347
354
|
// Add screenshot and mouse position if level is error or warn
|
|
348
355
|
if (level === 'error' || level === 'warn' || forceScreenshot) {
|
|
349
|
-
context.screenshot = await this.captureScreenshot() || undefined;
|
|
356
|
+
context.screenshot = (await this.captureScreenshot()) || undefined;
|
|
350
357
|
context.mousePosition = this.mousePosition || undefined;
|
|
351
358
|
}
|
|
352
359
|
|
|
@@ -356,7 +363,7 @@ export class Logger {
|
|
|
356
363
|
level,
|
|
357
364
|
message,
|
|
358
365
|
data,
|
|
359
|
-
context: context as LogEntry['context']
|
|
366
|
+
context: context as LogEntry['context'],
|
|
360
367
|
};
|
|
361
368
|
}
|
|
362
369
|
|
|
@@ -2,7 +2,7 @@ import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
|
2
2
|
import { UserInfo } from '../core/controller/SettingsController';
|
|
3
3
|
import { EventBus, EventBusMessage } from '../fromRimori/EventBus';
|
|
4
4
|
import { ActivePlugin, Plugin } from '../fromRimori/PluginTypes';
|
|
5
|
-
import { RimoriClient } from
|
|
5
|
+
import { RimoriClient } from './RimoriClient';
|
|
6
6
|
import { StandaloneClient } from './StandaloneClient';
|
|
7
7
|
import { setTheme } from './ThemeSetter';
|
|
8
8
|
import { Logger } from './Logger';
|
|
@@ -10,18 +10,25 @@ import { Logger } from './Logger';
|
|
|
10
10
|
// Add declaration for WorkerGlobalScope
|
|
11
11
|
declare const WorkerGlobalScope: any;
|
|
12
12
|
|
|
13
|
+
export interface Guild {
|
|
14
|
+
id: string;
|
|
15
|
+
longTermGoalOverride: string;
|
|
16
|
+
allowUserPluginSettings: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export interface RimoriInfo {
|
|
14
|
-
url: string
|
|
15
|
-
key: string
|
|
16
|
-
backendUrl: string
|
|
17
|
-
token: string
|
|
18
|
-
expiration: Date
|
|
19
|
-
tablePrefix: string
|
|
20
|
-
pluginId: string
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
url: string;
|
|
21
|
+
key: string;
|
|
22
|
+
backendUrl: string;
|
|
23
|
+
token: string;
|
|
24
|
+
expiration: Date;
|
|
25
|
+
tablePrefix: string;
|
|
26
|
+
pluginId: string;
|
|
27
|
+
guild: Guild;
|
|
28
|
+
installedPlugins: Plugin[];
|
|
29
|
+
profile: UserInfo;
|
|
30
|
+
mainPanelPlugin?: ActivePlugin;
|
|
31
|
+
sidePanelPlugin?: ActivePlugin;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
export class PluginController {
|
|
@@ -54,12 +61,16 @@ export class PluginController {
|
|
|
54
61
|
|
|
55
62
|
private initMessageChannel(worker: boolean = false) {
|
|
56
63
|
const listener = (event: MessageEvent) => {
|
|
57
|
-
console.log(
|
|
64
|
+
console.log('[PluginController] window message', { origin: event.origin, data: event.data });
|
|
58
65
|
const { type, pluginId, queryParams, rimoriInfo } = event.data || {};
|
|
59
66
|
const [transferredPort] = event.ports || [];
|
|
60
67
|
|
|
61
|
-
if (type !==
|
|
62
|
-
console.log(
|
|
68
|
+
if (type !== 'rimori:init' || !transferredPort || pluginId !== this.pluginId) {
|
|
69
|
+
console.log('[PluginController] message ignored (not init or wrong plugin)', {
|
|
70
|
+
type,
|
|
71
|
+
pluginId,
|
|
72
|
+
hasPort: !!transferredPort,
|
|
73
|
+
});
|
|
63
74
|
return;
|
|
64
75
|
}
|
|
65
76
|
|
|
@@ -70,7 +81,7 @@ export class PluginController {
|
|
|
70
81
|
if (rimoriInfo) {
|
|
71
82
|
this.rimoriInfo = rimoriInfo;
|
|
72
83
|
this.supabase = createClient(rimoriInfo.url, rimoriInfo.key, {
|
|
73
|
-
accessToken: () => Promise.resolve(rimoriInfo.token)
|
|
84
|
+
accessToken: () => Promise.resolve(rimoriInfo.token),
|
|
74
85
|
});
|
|
75
86
|
}
|
|
76
87
|
|
|
@@ -98,8 +109,8 @@ export class PluginController {
|
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
// Forward plugin events to parent (only after MessageChannel is ready)
|
|
101
|
-
EventBus.on(
|
|
102
|
-
if (ev.sender === this.pluginId && !ev.topic.startsWith(
|
|
112
|
+
EventBus.on('*', (ev) => {
|
|
113
|
+
if (ev.sender === this.pluginId && !ev.topic.startsWith('self.')) {
|
|
103
114
|
this.port?.postMessage({ event: ev });
|
|
104
115
|
}
|
|
105
116
|
});
|
|
@@ -108,27 +119,27 @@ export class PluginController {
|
|
|
108
119
|
this.isMessageChannelReady = true;
|
|
109
120
|
|
|
110
121
|
// Process any pending requests
|
|
111
|
-
this.pendingRequests.forEach(request => request());
|
|
122
|
+
this.pendingRequests.forEach((request) => request());
|
|
112
123
|
this.pendingRequests = [];
|
|
113
124
|
};
|
|
114
125
|
if (worker) {
|
|
115
126
|
self.onmessage = listener;
|
|
116
127
|
} else {
|
|
117
|
-
window.addEventListener(
|
|
128
|
+
window.addEventListener('message', listener);
|
|
118
129
|
}
|
|
119
130
|
this.sendHello(worker);
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
private sendHello(isWorker: boolean = false) {
|
|
123
134
|
try {
|
|
124
|
-
const payload = { type:
|
|
135
|
+
const payload = { type: 'rimori:hello', pluginId: this.pluginId };
|
|
125
136
|
if (isWorker) {
|
|
126
137
|
self.postMessage(payload);
|
|
127
138
|
} else {
|
|
128
|
-
window.parent.postMessage(payload,
|
|
139
|
+
window.parent.postMessage(payload, '*');
|
|
129
140
|
}
|
|
130
141
|
} catch (e) {
|
|
131
|
-
console.error(
|
|
142
|
+
console.error('[PluginController] Error sending hello:', e);
|
|
132
143
|
}
|
|
133
144
|
}
|
|
134
145
|
|
|
@@ -141,7 +152,7 @@ export class PluginController {
|
|
|
141
152
|
PluginController.client = await RimoriClient.getInstance(PluginController.instance);
|
|
142
153
|
|
|
143
154
|
//only init logger in workers and on main plugin pages
|
|
144
|
-
if (PluginController.instance.getQueryParam(
|
|
155
|
+
if (PluginController.instance.getQueryParam('applicationMode') !== 'sidebar') {
|
|
145
156
|
Logger.getInstance(PluginController.client);
|
|
146
157
|
}
|
|
147
158
|
}
|
|
@@ -152,7 +163,7 @@ export class PluginController {
|
|
|
152
163
|
return this.queryParams[key] || null;
|
|
153
164
|
}
|
|
154
165
|
|
|
155
|
-
public async getClient(): Promise<{ supabase: SupabaseClient
|
|
166
|
+
public async getClient(): Promise<{ supabase: SupabaseClient; info: RimoriInfo }> {
|
|
156
167
|
// Return cached client if valid
|
|
157
168
|
if (this.supabase && this.rimoriInfo && this.rimoriInfo.expiration > new Date()) {
|
|
158
169
|
return { supabase: this.supabase, info: this.rimoriInfo };
|
|
@@ -160,7 +171,7 @@ export class PluginController {
|
|
|
160
171
|
|
|
161
172
|
// If MessageChannel is not ready yet, queue the request
|
|
162
173
|
if (!this.isMessageChannelReady) {
|
|
163
|
-
return new Promise<{ supabase: SupabaseClient
|
|
174
|
+
return new Promise<{ supabase: SupabaseClient; info: RimoriInfo }>((resolve) => {
|
|
164
175
|
this.pendingRequests.push(async () => {
|
|
165
176
|
const result = await this.getClient();
|
|
166
177
|
resolve(result);
|
|
@@ -185,18 +196,18 @@ export class PluginController {
|
|
|
185
196
|
sender: this.pluginId,
|
|
186
197
|
topic: 'global.supabase.requestAccess',
|
|
187
198
|
data: {},
|
|
188
|
-
debug: false
|
|
189
|
-
}
|
|
199
|
+
debug: false,
|
|
200
|
+
},
|
|
190
201
|
};
|
|
191
202
|
|
|
192
|
-
return new Promise<{ supabase: SupabaseClient
|
|
203
|
+
return new Promise<{ supabase: SupabaseClient; info: RimoriInfo }>((resolve) => {
|
|
193
204
|
// Listen for the response
|
|
194
205
|
const originalOnMessage = self.onmessage;
|
|
195
206
|
self.onmessage = (event) => {
|
|
196
207
|
if (event.data?.topic === 'global.supabase.requestAccess' && event.data?.eventId === eventId) {
|
|
197
208
|
this.rimoriInfo = event.data.data;
|
|
198
209
|
this.supabase = createClient(this.rimoriInfo!.url, this.rimoriInfo!.key, {
|
|
199
|
-
accessToken: () => Promise.resolve(this.getToken())
|
|
210
|
+
accessToken: () => Promise.resolve(this.getToken()),
|
|
200
211
|
});
|
|
201
212
|
self.onmessage = originalOnMessage; // Restore original handler
|
|
202
213
|
resolve({ supabase: this.supabase, info: this.rimoriInfo! });
|
|
@@ -210,10 +221,11 @@ export class PluginController {
|
|
|
210
221
|
});
|
|
211
222
|
} else {
|
|
212
223
|
// In main thread context, use EventBus
|
|
213
|
-
const { data } = await EventBus.request<RimoriInfo>(this.pluginId,
|
|
224
|
+
const { data } = await EventBus.request<RimoriInfo>(this.pluginId, 'global.supabase.requestAccess');
|
|
225
|
+
console.log({ data });
|
|
214
226
|
this.rimoriInfo = data;
|
|
215
227
|
this.supabase = createClient(this.rimoriInfo.url, this.rimoriInfo.key, {
|
|
216
|
-
accessToken: () => Promise.resolve(this.getToken())
|
|
228
|
+
accessToken: () => Promise.resolve(this.getToken()),
|
|
217
229
|
});
|
|
218
230
|
}
|
|
219
231
|
}
|
|
@@ -228,13 +240,16 @@ export class PluginController {
|
|
|
228
240
|
|
|
229
241
|
// If we don't have rimoriInfo, request it
|
|
230
242
|
if (!this.rimoriInfo) {
|
|
231
|
-
const { data } = await EventBus.request<RimoriInfo>(this.pluginId,
|
|
243
|
+
const { data } = await EventBus.request<RimoriInfo>(this.pluginId, 'global.supabase.requestAccess');
|
|
232
244
|
this.rimoriInfo = data;
|
|
233
245
|
return this.rimoriInfo.token;
|
|
234
246
|
}
|
|
235
247
|
|
|
236
248
|
// If token is expired, request fresh access
|
|
237
|
-
const { data } = await EventBus.request<{ token: string
|
|
249
|
+
const { data } = await EventBus.request<{ token: string; expiration: Date }>(
|
|
250
|
+
this.pluginId,
|
|
251
|
+
'global.supabase.requestAccess',
|
|
252
|
+
);
|
|
238
253
|
this.rimoriInfo.token = data.token;
|
|
239
254
|
this.rimoriInfo.expiration = data.expiration;
|
|
240
255
|
|
|
@@ -248,7 +263,7 @@ export class PluginController {
|
|
|
248
263
|
*/
|
|
249
264
|
public getSupabaseUrl() {
|
|
250
265
|
if (!this.rimoriInfo) {
|
|
251
|
-
throw new Error(
|
|
266
|
+
throw new Error('Supabase info not found');
|
|
252
267
|
}
|
|
253
268
|
|
|
254
269
|
return this.rimoriInfo.url;
|
|
@@ -256,30 +271,31 @@ export class PluginController {
|
|
|
256
271
|
|
|
257
272
|
public getBackendUrl() {
|
|
258
273
|
if (!this.rimoriInfo) {
|
|
259
|
-
throw new Error(
|
|
274
|
+
throw new Error('Rimori info not found');
|
|
260
275
|
}
|
|
261
276
|
return this.rimoriInfo.backendUrl;
|
|
262
277
|
}
|
|
263
278
|
|
|
264
279
|
public getGlobalEventTopic(preliminaryTopic: string) {
|
|
265
|
-
if (preliminaryTopic.startsWith(
|
|
280
|
+
if (preliminaryTopic.startsWith('global.')) {
|
|
266
281
|
return preliminaryTopic;
|
|
267
282
|
}
|
|
268
|
-
if (preliminaryTopic.startsWith(
|
|
283
|
+
if (preliminaryTopic.startsWith('self.')) {
|
|
269
284
|
return preliminaryTopic;
|
|
270
285
|
}
|
|
271
|
-
const topicParts = preliminaryTopic.split(
|
|
286
|
+
const topicParts = preliminaryTopic.split('.');
|
|
272
287
|
if (topicParts.length === 3) {
|
|
273
|
-
if (!topicParts[0].startsWith(
|
|
288
|
+
if (!topicParts[0].startsWith('pl') && topicParts[0] !== 'global') {
|
|
274
289
|
throw new Error("The event topic must start with the plugin id or 'global'.");
|
|
275
290
|
}
|
|
276
291
|
return preliminaryTopic;
|
|
277
292
|
} else if (topicParts.length > 3) {
|
|
278
|
-
throw new Error(
|
|
293
|
+
throw new Error(
|
|
294
|
+
`The event topic must consist of 3 parts. <pluginId>.<topic area>.<action>. Received: ${preliminaryTopic}`,
|
|
295
|
+
);
|
|
279
296
|
}
|
|
280
297
|
|
|
281
|
-
const topicRoot = this.rimoriInfo?.pluginId ??
|
|
298
|
+
const topicRoot = this.rimoriInfo?.pluginId ?? 'global';
|
|
282
299
|
return `${topicRoot}.${preliminaryTopic}`;
|
|
283
300
|
}
|
|
284
|
-
|
|
285
|
-
}
|
|
301
|
+
}
|