@rimori/client 1.0.3 → 1.0.5
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 +51 -0
- package/dist/components/CRUDModal.js +0 -1
- package/dist/components/ai/Assistant.d.ts +9 -0
- package/dist/components/ai/Assistant.js +59 -0
- package/dist/components/ai/Avatar.d.ts +11 -0
- package/dist/components/ai/Avatar.js +39 -0
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +38 -0
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +59 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +86 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +25 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +180 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +7 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +45 -0
- package/dist/components/ai/utils.d.ts +6 -0
- package/dist/components/ai/utils.js +14 -0
- package/dist/components/audio/Playbutton.js +4 -5
- package/dist/components/avatar/Assistant.d.ts +9 -0
- package/dist/components/avatar/Assistant.js +59 -0
- package/dist/components/avatar/Avatar.d.ts +12 -0
- package/dist/components/avatar/Avatar.js +42 -0
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.js +38 -0
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.js +59 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.d.ts +19 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.js +84 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.d.ts +25 -0
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.js +180 -0
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.d.ts +7 -0
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.js +45 -0
- package/dist/components/avatar/utils.d.ts +6 -0
- package/dist/components/avatar/utils.js +14 -0
- package/dist/components.d.ts +9 -0
- package/dist/components.js +10 -0
- package/dist/controller/AIController.d.ts +4 -3
- package/dist/controller/AIController.js +32 -8
- package/dist/controller/ObjectController.d.ts +2 -2
- package/dist/controller/ObjectController.js +4 -5
- package/dist/controller/SettingsController.d.ts +19 -10
- package/dist/controller/SettingsController.js +33 -26
- package/dist/controller/SharedContentController.js +6 -6
- package/dist/core.d.ts +9 -0
- package/dist/core.js +10 -0
- package/dist/hooks/UseChatHook.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -2
- package/dist/plugin/PluginController.d.ts +4 -12
- package/dist/plugin/PluginController.js +45 -70
- package/dist/plugin/RimoriClient.d.ts +85 -32
- package/dist/plugin/RimoriClient.js +98 -77
- package/dist/plugin/ThemeSetter.js +3 -3
- package/dist/plugin/fromRimori/EventBus.d.ts +98 -0
- package/dist/plugin/fromRimori/EventBus.js +240 -0
- package/dist/providers/PluginProvider.d.ts +1 -0
- package/dist/providers/PluginProvider.js +10 -12
- package/dist/worker/WorkerSetup.d.ts +6 -0
- package/dist/worker/WorkerSetup.js +80 -0
- package/package.json +17 -3
- package/src/components/CRUDModal.tsx +1 -3
- package/src/components/ai/Assistant.tsx +96 -0
- package/src/components/ai/Avatar.tsx +61 -0
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +64 -0
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +75 -0
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +91 -0
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +192 -0
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +56 -0
- package/src/components/ai/utils.ts +23 -0
- package/src/components/audio/Playbutton.tsx +4 -5
- package/src/components.ts +10 -0
- package/src/controller/AIController.ts +84 -60
- package/src/controller/ObjectController.ts +4 -6
- package/src/controller/SettingsController.ts +49 -35
- package/src/controller/SharedContentController.ts +6 -6
- package/src/core.ts +10 -0
- package/src/hooks/UseChatHook.ts +2 -2
- package/src/index.ts +4 -2
- package/src/plugin/PluginController.ts +51 -76
- package/src/plugin/RimoriClient.ts +147 -85
- package/src/plugin/ThemeSetter.ts +3 -4
- package/src/plugin/fromRimori/EventBus.ts +301 -0
- package/src/plugin/fromRimori/readme.md +2 -0
- package/src/providers/PluginProvider.tsx +12 -14
- package/src/worker/WorkerSetup.ts +81 -0
- package/dist/CRUDModal.d.ts +0 -16
- package/dist/CRUDModal.js +0 -31
- package/dist/MarkdownEditor.d.ts +0 -8
- package/dist/MarkdownEditor.js +0 -46
- package/dist/audio/Playbutton.d.ts +0 -14
- package/dist/audio/Playbutton.js +0 -73
- package/dist/components/hooks/UseChatHook.d.ts +0 -15
- package/dist/components/hooks/UseChatHook.js +0 -21
- package/dist/controller/PluginController.d.ts +0 -14
- package/dist/controller/PluginController.js +0 -30
- package/dist/plugin/AIController copy.d.ts +0 -22
- package/dist/plugin/AIController copy.js +0 -68
- package/dist/plugin/AIController.d.ts +0 -22
- package/dist/plugin/AIController.js +0 -68
- package/dist/plugin/ObjectController.d.ts +0 -34
- package/dist/plugin/ObjectController.js +0 -77
- package/dist/plugin/SettingController.d.ts +0 -13
- package/dist/plugin/SettingController.js +0 -55
- package/dist/plugin/VoiceController.d.ts +0 -2
- package/dist/plugin/VoiceController.js +0 -27
- package/dist/providers/EventEmitter.d.ts +0 -11
- package/dist/providers/EventEmitter.js +0 -41
- package/dist/providers/EventEmitterContext.d.ts +0 -6
- package/dist/providers/EventEmitterContext.js +0 -19
- package/dist/utils/DifficultyConverter.d.ts +0 -3
- package/dist/utils/DifficultyConverter.js +0 -7
- package/dist/utils/constants.d.ts +0 -4
- package/dist/utils/constants.js +0 -12
- package/dist/utils/plugin/Client.d.ts +0 -72
- package/dist/utils/plugin/Client.js +0 -118
- package/dist/utils/plugin/PluginController.d.ts +0 -36
- package/dist/utils/plugin/PluginController.js +0 -119
- package/dist/utils/plugin/PluginUtils.d.ts +0 -2
- package/dist/utils/plugin/PluginUtils.js +0 -23
- package/dist/utils/plugin/RimoriClient.d.ts +0 -72
- package/dist/utils/plugin/RimoriClient.js +0 -118
- package/dist/utils/plugin/ThemeSetter.d.ts +0 -1
- package/dist/utils/plugin/ThemeSetter.js +0 -13
- package/dist/utils/plugin/WhereClauseBuilder.d.ts +0 -24
- package/dist/utils/plugin/WhereClauseBuilder.js +0 -79
- package/dist/utils/plugin/providers/EventEmitter.d.ts +0 -11
- package/dist/utils/plugin/providers/EventEmitter.js +0 -41
- package/dist/utils/plugin/providers/EventEmitterContext.d.ts +0 -6
- package/dist/utils/plugin/providers/EventEmitterContext.js +0 -19
- package/dist/utils/plugin/providers/PluginProvider.d.ts +0 -8
- package/dist/utils/plugin/providers/PluginProvider.js +0 -49
- package/src/providers/EventEmitter.ts +0 -48
- package/src/providers/EventEmitterContext.tsx +0 -27
- package/src/utils/constants.ts +0 -18
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { env } from "../utils/constants";
|
|
2
|
-
|
|
3
1
|
type PrimitiveType = 'string' | 'number' | 'boolean';
|
|
4
2
|
|
|
5
3
|
// This is the type that can appear in the `type` property
|
|
@@ -35,8 +33,8 @@ export interface ObjectRequest {
|
|
|
35
33
|
instructions: string;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
|
-
export async function generateObject(request: ObjectRequest, token: string) {
|
|
39
|
-
return await fetch(`${
|
|
36
|
+
export async function generateObject(supabaseUrl: string, request: ObjectRequest, token: string) {
|
|
37
|
+
return await fetch(`${supabaseUrl}/functions/v1/llm-object`, {
|
|
40
38
|
method: 'POST',
|
|
41
39
|
body: JSON.stringify({
|
|
42
40
|
stream: false,
|
|
@@ -51,9 +49,9 @@ export async function generateObject(request: ObjectRequest, token: string) {
|
|
|
51
49
|
// TODO adjust stream to work with object
|
|
52
50
|
export type OnLLMResponse = (id: string, response: string, finished: boolean, toolInvocations?: any[]) => void;
|
|
53
51
|
|
|
54
|
-
export async function streamObject(request: ObjectRequest, onResponse: OnLLMResponse, token: string) {
|
|
52
|
+
export async function streamObject(supabaseUrl: string, request: ObjectRequest, onResponse: OnLLMResponse, token: string) {
|
|
55
53
|
const messageId = Math.random().toString(36).substring(3);
|
|
56
|
-
const response = await fetch(`${
|
|
54
|
+
const response = await fetch(`${supabaseUrl}/functions/v1/llm-object`, {
|
|
57
55
|
method: 'POST',
|
|
58
56
|
body: JSON.stringify({
|
|
59
57
|
stream: true,
|
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
2
|
import { LanguageLevel } from "../utils/difficultyConverter";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export interface UserSettings {
|
|
4
|
+
export interface UserInfo {
|
|
7
5
|
motherTongue: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
xp: number;
|
|
7
|
+
listening_level: LanguageLevel;
|
|
8
|
+
reading_level: LanguageLevel;
|
|
9
|
+
speaking_level: LanguageLevel;
|
|
10
|
+
writing_level: LanguageLevel;
|
|
11
|
+
understanding_level: LanguageLevel;
|
|
12
|
+
grammar_level: LanguageLevel;
|
|
13
|
+
longterm_goal: string;
|
|
14
|
+
motivation_type: string;
|
|
15
|
+
study_buddy: string;
|
|
16
|
+
preferred_genre: string;
|
|
17
|
+
milestone: string;
|
|
18
|
+
settings: {
|
|
19
|
+
contextMenuOnSelect: boolean;
|
|
20
|
+
}
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
export class SettingsController {
|
|
@@ -22,13 +29,8 @@ export class SettingsController {
|
|
|
22
29
|
this.pluginId = pluginId;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private async fetchSettings(type: SettingsType): Promise<any | null> {
|
|
30
|
-
const pluginId = type === "plugin" ? this.pluginId : type;
|
|
31
|
-
const { data } = await this.supabase.from("plugin_settings").select("*").eq("plugin_id", pluginId)
|
|
32
|
+
private async fetchSettings(): Promise<any | null> {
|
|
33
|
+
const { data } = await this.supabase.from("plugin_settings").select("*").eq("plugin_id", this.pluginId)
|
|
32
34
|
|
|
33
35
|
if (!data || data.length === 0) {
|
|
34
36
|
return null;
|
|
@@ -37,28 +39,47 @@ export class SettingsController {
|
|
|
37
39
|
return data[0].settings;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
public async setSettings(settings: any): Promise<void> {
|
|
43
|
+
await this.supabase.from("plugin_settings").upsert({ plugin_id: this.pluginId, settings });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async getUserInfo(): Promise<UserInfo> {
|
|
47
|
+
const { data } = await this.supabase.from("profiles").select("*");
|
|
48
|
+
|
|
49
|
+
if (!data || data.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
motherTongue: "en",
|
|
52
|
+
xp: 0,
|
|
53
|
+
listening_level: "Pre-A1",
|
|
54
|
+
reading_level: "Pre-A1",
|
|
55
|
+
speaking_level: "Pre-A1",
|
|
56
|
+
writing_level: "Pre-A1",
|
|
57
|
+
understanding_level: "Pre-A1",
|
|
58
|
+
grammar_level: "Pre-A1",
|
|
59
|
+
longterm_goal: "",
|
|
60
|
+
motivation_type: "self-motivated",
|
|
61
|
+
study_buddy: "clarence",
|
|
62
|
+
preferred_genre: "adventure",
|
|
63
|
+
milestone: "",
|
|
64
|
+
settings: {
|
|
65
|
+
contextMenuOnSelect: false,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
43
68
|
}
|
|
44
69
|
|
|
45
|
-
|
|
70
|
+
return data[0];
|
|
46
71
|
}
|
|
47
72
|
|
|
48
73
|
/**
|
|
49
74
|
* Get the settings for the plugin. T can be any type of settings, UserSettings or SystemSettings.
|
|
50
75
|
* @param defaultSettings The default settings to use if no settings are found.
|
|
51
|
-
* @param genericSettings The type of settings to get.
|
|
52
76
|
* @returns The settings for the plugin.
|
|
53
77
|
*/
|
|
54
|
-
public async getSettings<T extends object>(defaultSettings: T
|
|
55
|
-
const
|
|
56
|
-
const storedSettings = await this.fetchSettings(type) as T | null;
|
|
78
|
+
public async getSettings<T extends object>(defaultSettings: T): Promise<T> {
|
|
79
|
+
const storedSettings = await this.fetchSettings() as T | null;
|
|
57
80
|
|
|
58
81
|
if (!storedSettings) {
|
|
59
|
-
|
|
60
|
-
await this.saveSettings(defaultSettings, type);
|
|
61
|
-
}
|
|
82
|
+
await this.setSettings(defaultSettings);
|
|
62
83
|
return defaultSettings;
|
|
63
84
|
}
|
|
64
85
|
|
|
@@ -72,17 +93,10 @@ export class SettingsController {
|
|
|
72
93
|
);
|
|
73
94
|
const mergedSettings = { ...defaultSettings, ...validStoredSettings } as T;
|
|
74
95
|
|
|
75
|
-
|
|
76
|
-
await this.saveSettings(mergedSettings, type);
|
|
77
|
-
}
|
|
96
|
+
await this.setSettings(mergedSettings);
|
|
78
97
|
return mergedSettings;
|
|
79
98
|
}
|
|
80
99
|
|
|
81
100
|
return storedSettings;
|
|
82
101
|
}
|
|
83
|
-
|
|
84
|
-
public async setSettings(settings: any, genericSettings?: "user" | "system"): Promise<void> {
|
|
85
|
-
const type = this.getSettingsType(genericSettings);
|
|
86
|
-
await this.saveSettings(settings, type);
|
|
87
|
-
}
|
|
88
102
|
}
|
|
@@ -24,14 +24,14 @@ export class SharedContentController {
|
|
|
24
24
|
filter?: { column: string, value: string | number | boolean },
|
|
25
25
|
): Promise<R[]> {
|
|
26
26
|
const queryParameter = { filter_column: filter?.column || null, filter_value: filter?.value || null, unread: true }
|
|
27
|
-
const { data: newAssignments } = await this.rimoriClient.rpc(type + "_entries", queryParameter)
|
|
27
|
+
const { data: newAssignments } = await this.rimoriClient.db.rpc(type + "_entries", queryParameter)
|
|
28
28
|
console.log('newAssignments:', newAssignments);
|
|
29
29
|
|
|
30
30
|
if ((newAssignments as any[]).length > 0) {
|
|
31
31
|
return newAssignments as R[];
|
|
32
32
|
}
|
|
33
33
|
// generate new assignments
|
|
34
|
-
const { data: oldAssignments } = await this.rimoriClient.rpc(type + "_entries", { ...queryParameter, unread: false })
|
|
34
|
+
const { data: oldAssignments } = await this.rimoriClient.db.rpc(type + "_entries", { ...queryParameter, unread: false })
|
|
35
35
|
console.log('oldAssignments:', oldAssignments);
|
|
36
36
|
const reservedTopics = this.getReservedTopics(oldAssignments as BasicAssignment[]);
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ export class SharedContentController {
|
|
|
39
39
|
if (!request.tool.keywords || !request.tool.topic) {
|
|
40
40
|
throw new Error("topic or keywords not found in the request schema");
|
|
41
41
|
}
|
|
42
|
-
const instructions = await this.rimoriClient.
|
|
42
|
+
const instructions = await this.rimoriClient.llm.getObject(request);
|
|
43
43
|
console.log('instructions:', instructions);
|
|
44
44
|
|
|
45
45
|
const preparedData = {
|
|
@@ -47,7 +47,7 @@ export class SharedContentController {
|
|
|
47
47
|
...instructions,
|
|
48
48
|
keywords: this.purifyStringArray(instructions.keywords),
|
|
49
49
|
};
|
|
50
|
-
return await this.rimoriClient.from(type).insert(preparedData).then(() => [preparedData] as R[]);
|
|
50
|
+
return await this.rimoriClient.db.from(type).insert(preparedData).then(() => [preparedData] as R[]);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
private getReservedTopics(oldAssignments: BasicAssignment[]) {
|
|
@@ -62,10 +62,10 @@ export class SharedContentController {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
public async getSharedContent<T extends BasicAssignment>(type: string, id: string): Promise<T> {
|
|
65
|
-
return await this.rimoriClient.from(type).select().eq('id', id).single() as unknown as T;
|
|
65
|
+
return await this.rimoriClient.db.from(type).select().eq('id', id).single() as unknown as T;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
public async completeSharedContent(type: string, assignmentId: string) {
|
|
69
|
-
await this.rimoriClient.from(type + "_result").insert({ assignment_id: assignmentId });
|
|
69
|
+
await this.rimoriClient.db.from(type + "_result").insert({ assignment_id: assignmentId });
|
|
70
70
|
}
|
|
71
71
|
}
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Core functionality exports
|
|
2
|
+
export * from "./controller/AIController";
|
|
3
|
+
export * from "./controller/SharedContentController";
|
|
4
|
+
export * from "./controller/SettingsController";
|
|
5
|
+
export * from "./plugin/RimoriClient";
|
|
6
|
+
export * from "./plugin/PluginController";
|
|
7
|
+
export * from "./utils/difficultyConverter";
|
|
8
|
+
export * from "./utils/PluginUtils";
|
|
9
|
+
export * from "./worker/WorkerSetup";
|
|
10
|
+
export * from "./plugin/fromRimori/EventBus";
|
package/src/hooks/UseChatHook.ts
CHANGED
|
@@ -5,10 +5,10 @@ import { ToolInvocation, Tool, Message } from "../controller/AIController";
|
|
|
5
5
|
export function useChat(tools?: Tool[]) {
|
|
6
6
|
const [messages, setMessages] = React.useState<Message[]>([]);
|
|
7
7
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
8
|
-
const {
|
|
8
|
+
const { llm } = usePlugin();
|
|
9
9
|
|
|
10
10
|
const append = (appendMessages: Message[]) => {
|
|
11
|
-
|
|
11
|
+
llm.getSteamedText([...messages, ...appendMessages], (id, message, finished: boolean, toolInvocations?: ToolInvocation[]) => {
|
|
12
12
|
const lastMessage = messages[messages.length - 1];
|
|
13
13
|
setIsLoading(!finished);
|
|
14
14
|
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Re-export everything
|
|
2
|
+
export * from './core';
|
|
3
|
+
export * from './components';
|
|
1
4
|
export * from "./components/MarkdownEditor";
|
|
2
5
|
export * from "./components/CRUDModal";
|
|
3
6
|
export * from "./components/Spinner";
|
|
@@ -8,8 +11,7 @@ export * from "./controller/SettingsController";
|
|
|
8
11
|
export * from "./hooks/UseChatHook";
|
|
9
12
|
export * from "./plugin/RimoriClient";
|
|
10
13
|
export * from "./plugin/ThemeSetter";
|
|
11
|
-
export * from "./providers/EventEmitter";
|
|
12
|
-
export * from "./providers/EventEmitterContext";
|
|
13
14
|
export * from "./providers/PluginProvider";
|
|
14
15
|
export * from "./utils/difficultyConverter";
|
|
15
16
|
export * from "./utils/PluginUtils";
|
|
17
|
+
export * from "./plugin/PluginController";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { Child } from "ibridge-flex";
|
|
2
1
|
import { createClient, SupabaseClient } from '@supabase/supabase-js'
|
|
3
2
|
import { RimoriClient } from "./RimoriClient";
|
|
3
|
+
import { EventBus, EventBusMessage } from './fromRimori/EventBus';
|
|
4
|
+
import { setTheme } from './ThemeSetter';
|
|
5
|
+
|
|
6
|
+
// Add declaration for WorkerGlobalScope
|
|
7
|
+
declare const WorkerGlobalScope: any;
|
|
4
8
|
|
|
5
9
|
interface SupabaseInfo {
|
|
6
10
|
url: string,
|
|
@@ -12,55 +16,47 @@ interface SupabaseInfo {
|
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export class PluginController {
|
|
15
|
-
private static instance: PluginController;
|
|
16
19
|
private static client: RimoriClient;
|
|
17
|
-
private
|
|
18
|
-
private onceListeners: Map<string, any[]> = new Map();
|
|
19
|
-
private listeners: Map<string, any[]> = new Map();
|
|
20
|
+
private static instance: PluginController;
|
|
20
21
|
private communicationSecret: string | null = null;
|
|
21
|
-
private initialized = false;
|
|
22
22
|
private supabase: SupabaseClient | null = null;
|
|
23
23
|
private supabaseInfo: SupabaseInfo | null = null;
|
|
24
|
+
private pluginId: string;
|
|
24
25
|
|
|
25
|
-
private constructor() {
|
|
26
|
-
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
private constructor(pluginId: string) {
|
|
27
|
+
this.pluginId = pluginId;
|
|
28
|
+
this.getClient = this.getClient.bind(this);
|
|
29
|
+
|
|
30
|
+
if (typeof WorkerGlobalScope === 'undefined') {
|
|
31
|
+
setTheme();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
window.addEventListener("message", (event) => {
|
|
35
|
+
// console.log("client: message received", event);
|
|
36
|
+
const { topic, sender, data, eventId } = event.data.event as EventBusMessage;
|
|
37
|
+
|
|
38
|
+
// skip forwarding messages from own plugin
|
|
39
|
+
if (sender === pluginId) return;
|
|
40
|
+
|
|
41
|
+
EventBus.emit(sender, topic, data, eventId);
|
|
34
42
|
});
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
EventBus.on("*", (event) => {
|
|
45
|
+
// skip messages which are not from the own plugin
|
|
46
|
+
if (event.sender !== this.pluginId) return;
|
|
47
|
+
if (event.topic.startsWith("self.")) return;
|
|
48
|
+
window.parent.postMessage({ event, secret: this.getSecret() }, "*")
|
|
49
|
+
});
|
|
42
50
|
}
|
|
43
51
|
|
|
44
|
-
public static async getInstance(): Promise<RimoriClient> {
|
|
52
|
+
public static async getInstance(sender: string): Promise<RimoriClient> {
|
|
45
53
|
if (!PluginController.instance) {
|
|
46
|
-
PluginController.instance = new PluginController();
|
|
47
|
-
await PluginController.instance
|
|
48
|
-
PluginController.client = await RimoriClient.getInstance(
|
|
49
|
-
PluginController.instance
|
|
50
|
-
);
|
|
54
|
+
PluginController.instance = new PluginController(sender);
|
|
55
|
+
PluginController.client = await RimoriClient.getInstance(PluginController.instance);
|
|
51
56
|
}
|
|
52
57
|
return PluginController.client;
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
async init() {
|
|
56
|
-
if (this.initialized) return;
|
|
57
|
-
|
|
58
|
-
// Wait for the plugin to be ready
|
|
59
|
-
await this.plugin.handshake().then(() => this.initialized = true).catch((error: any) => {
|
|
60
|
-
console.error("Failed to initialize the plugin communication:", error);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
60
|
private getSecret() {
|
|
65
61
|
if (!this.communicationSecret) {
|
|
66
62
|
const secret = new URLSearchParams(window.location.search).get("secret");
|
|
@@ -81,8 +77,8 @@ export class PluginController {
|
|
|
81
77
|
return { supabase: this.supabase, tablePrefix: this.supabaseInfo.tablePrefix, pluginId: this.supabaseInfo.pluginId };
|
|
82
78
|
}
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
const { data } = await EventBus.request<SupabaseInfo>(this.pluginId, "global.supabase.requestAccess");
|
|
81
|
+
this.supabaseInfo = data;
|
|
86
82
|
this.supabase = createClient(this.supabaseInfo.url, this.supabaseInfo.key, {
|
|
87
83
|
accessToken: () => Promise.resolve(this.getToken())
|
|
88
84
|
});
|
|
@@ -95,14 +91,14 @@ export class PluginController {
|
|
|
95
91
|
return this.supabaseInfo.token;
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
const
|
|
94
|
+
const { data } = await EventBus.request<{ token: string, expiration: Date }>(this.pluginId, "global.supabase.requestAccess");
|
|
99
95
|
|
|
100
96
|
if (!this.supabaseInfo) {
|
|
101
97
|
throw new Error("Supabase info not found");
|
|
102
98
|
}
|
|
103
99
|
|
|
104
|
-
this.supabaseInfo.token =
|
|
105
|
-
this.supabaseInfo.expiration =
|
|
100
|
+
this.supabaseInfo.token = data.token;
|
|
101
|
+
this.supabaseInfo.expiration = data.expiration;
|
|
106
102
|
|
|
107
103
|
return this.supabaseInfo.token;
|
|
108
104
|
}
|
|
@@ -115,44 +111,23 @@ export class PluginController {
|
|
|
115
111
|
return this.supabaseInfo.url;
|
|
116
112
|
}
|
|
117
113
|
|
|
118
|
-
public
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// the communication needs to have an id to be able to distinguish between different responses
|
|
123
|
-
private internalEmit(eventName: string, id: number, data?: any) {
|
|
124
|
-
this.init().then(() => this.plugin.emitToParent(eventName, { data, _id: id, secret: this.getSecret() }));
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
public subscribe(eventName: string, callback: (_id: number, data: any) => void) {
|
|
128
|
-
if (!this.listeners.has(eventName)) {
|
|
129
|
-
this.listeners.set(eventName, []);
|
|
114
|
+
public getGlobalEventTopic(preliminaryTopic: string) {
|
|
115
|
+
if (preliminaryTopic.startsWith("global.")) {
|
|
116
|
+
return preliminaryTopic;
|
|
130
117
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
if (preliminaryTopic.startsWith("self.")) {
|
|
119
|
+
return preliminaryTopic;
|
|
120
|
+
}
|
|
121
|
+
const topicParts = preliminaryTopic.split(".");
|
|
122
|
+
if (topicParts.length === 3) {
|
|
123
|
+
if (![this.supabaseInfo?.pluginId, "global"].includes(topicParts[0])) {
|
|
124
|
+
throw new Error("The event topic must start with the plugin id or 'global'.");
|
|
125
|
+
}
|
|
126
|
+
return preliminaryTopic;
|
|
138
127
|
}
|
|
139
128
|
|
|
140
|
-
this.
|
|
129
|
+
const topicRoot = this.supabaseInfo?.pluginId ?? "global";
|
|
130
|
+
return `${topicRoot}.${preliminaryTopic}`;
|
|
141
131
|
}
|
|
142
132
|
|
|
143
|
-
async request<T>(topic: string, data: any = {}): Promise<T> {
|
|
144
|
-
return await new Promise((resolve) => {
|
|
145
|
-
let triggered = false;
|
|
146
|
-
const id = Math.random();
|
|
147
|
-
|
|
148
|
-
this.internalEmit(topic, id, data);
|
|
149
|
-
|
|
150
|
-
this.subscribe(topic, (_id: number, data: any) => {
|
|
151
|
-
if (triggered || (_id !== id && _id !== 0)) return;
|
|
152
|
-
triggered = true;
|
|
153
|
-
|
|
154
|
-
resolve(data)
|
|
155
|
-
})
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
133
|
}
|