@rimori/client 2.5.32 → 2.5.33-next.0
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/dist/cli/scripts/init/dev-registration.js +118 -136
- package/dist/cli/scripts/init/main.js +116 -127
- package/dist/cli/scripts/init/package-setup.js +15 -2
- package/dist/cli/scripts/release/detect-translation-languages.js +24 -35
- package/dist/cli/scripts/release/release-config-upload.js +87 -100
- package/dist/cli/scripts/release/release-db-update.js +70 -81
- package/dist/cli/scripts/release/release-file-upload.js +75 -91
- package/dist/cli/scripts/release/release-prompts-upload.js +60 -72
- package/dist/cli/scripts/release/release.js +20 -31
- package/dist/controller/AccomplishmentController.js +12 -12
- package/dist/controller/AudioController.js +15 -33
- package/dist/controller/TranslationController.js +108 -118
- package/dist/fromRimori/EventBus.js +20 -31
- package/dist/plugin/CommunicationHandler.js +73 -81
- package/dist/plugin/Logger.js +71 -83
- package/dist/plugin/RimoriClient.js +31 -31
- package/dist/plugin/StandaloneClient.js +81 -98
- package/dist/plugin/TTS/ChunkedAudioPlayer.js +31 -41
- package/dist/plugin/TTS/MessageSender.js +28 -37
- package/dist/plugin/module/AIModule.js +215 -237
- package/dist/plugin/module/DbModule.js +22 -31
- package/dist/plugin/module/EventModule.js +23 -32
- package/dist/plugin/module/ExerciseModule.js +42 -56
- package/dist/plugin/module/PluginModule.js +97 -106
- package/dist/plugin/module/SharedContentController.js +170 -207
- package/dist/plugin/module/StorageModule.js +18 -29
- package/dist/worker/WorkerSetup.js +23 -34
- package/package.json +1 -1
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
export class EventBusHandler {
|
|
2
|
+
listeners = new Map();
|
|
3
|
+
responseResolvers = new Map();
|
|
4
|
+
static instance = null;
|
|
5
|
+
debugEnabled = false;
|
|
6
|
+
evName = '';
|
|
7
|
+
generatedIds = new Map(); // Map<id, timestamp>
|
|
8
|
+
cleanupInterval = null;
|
|
11
9
|
constructor() {
|
|
12
|
-
this.listeners = new Map();
|
|
13
|
-
this.responseResolvers = new Map();
|
|
14
|
-
this.debugEnabled = false;
|
|
15
|
-
this.evName = '';
|
|
16
|
-
this.generatedIds = new Map(); // Map<id, timestamp>
|
|
17
|
-
this.cleanupInterval = null;
|
|
18
10
|
this.startIdCleanup();
|
|
19
11
|
}
|
|
20
12
|
/**
|
|
@@ -187,7 +179,7 @@ export class EventBusHandler {
|
|
|
187
179
|
const blackListedEventIds = [];
|
|
188
180
|
//To allow event communication inside the same plugin the sender needs to be ignored but the events still need to be checked for the same event just reaching the subscriber to prevent infinite loops
|
|
189
181
|
const finalIgnoreSender = !topic.startsWith('self.') ? [sender] : [];
|
|
190
|
-
const listener = this.on(topic, (data) =>
|
|
182
|
+
const listener = this.on(topic, async (data) => {
|
|
191
183
|
if (blackListedEventIds.includes(data.eventId)) {
|
|
192
184
|
// console.log("BLACKLISTED EVENT ID", data.eventId);
|
|
193
185
|
return;
|
|
@@ -196,9 +188,9 @@ export class EventBusHandler {
|
|
|
196
188
|
if (blackListedEventIds.length > 100) {
|
|
197
189
|
blackListedEventIds.shift();
|
|
198
190
|
}
|
|
199
|
-
const response = typeof handler === 'function' ?
|
|
191
|
+
const response = typeof handler === 'function' ? await handler(data) : handler;
|
|
200
192
|
this.emit(sender, topic, response, data.eventId);
|
|
201
|
-
}
|
|
193
|
+
}, finalIgnoreSender);
|
|
202
194
|
this.logIfDebug(`Added respond listener ` + sender + ' to topic ' + topic, { listener, sender });
|
|
203
195
|
return {
|
|
204
196
|
off: () => listener.off(),
|
|
@@ -221,7 +213,7 @@ export class EventBusHandler {
|
|
|
221
213
|
let listener = undefined;
|
|
222
214
|
const wrapper = (event) => {
|
|
223
215
|
handler(event);
|
|
224
|
-
listener
|
|
216
|
+
listener?.off();
|
|
225
217
|
};
|
|
226
218
|
listener = this.on(topic, wrapper);
|
|
227
219
|
this.logIfDebug(`Added once listener ` + topic, { listener, topic });
|
|
@@ -255,17 +247,15 @@ export class EventBusHandler {
|
|
|
255
247
|
* @param data - The data of the event.
|
|
256
248
|
* @returns A promise that resolves to the event.
|
|
257
249
|
*/
|
|
258
|
-
request(sender, topic, data, aiSessionToken) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.emitInternal(sender, topic, data || {}, event.eventId, true, aiSessionToken);
|
|
268
|
-
});
|
|
250
|
+
async request(sender, topic, data, aiSessionToken) {
|
|
251
|
+
if (!this.validateTopic(topic)) {
|
|
252
|
+
this.logAndThrowError(true, `Invalid topic: ` + topic);
|
|
253
|
+
}
|
|
254
|
+
const event = this.createEvent(sender, topic, data || {}, undefined, aiSessionToken);
|
|
255
|
+
this.logIfDebug(`Requesting data from ` + topic, { event });
|
|
256
|
+
return new Promise((resolve) => {
|
|
257
|
+
this.responseResolvers.set(event.eventId, (value) => resolve(value));
|
|
258
|
+
this.emitInternal(sender, topic, data || {}, event.eventId, true, aiSessionToken);
|
|
269
259
|
});
|
|
270
260
|
}
|
|
271
261
|
/**
|
|
@@ -336,5 +326,4 @@ export class EventBusHandler {
|
|
|
336
326
|
}
|
|
337
327
|
}
|
|
338
328
|
}
|
|
339
|
-
EventBusHandler.instance = null;
|
|
340
329
|
export const EventBus = EventBusHandler.getInstance();
|
|
@@ -1,24 +1,16 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
11
2
|
import { EventBus } from '../fromRimori/EventBus';
|
|
12
3
|
export class RimoriCommunicationHandler {
|
|
4
|
+
pluginId;
|
|
5
|
+
port = null;
|
|
6
|
+
queryParams = {};
|
|
7
|
+
supabase = null;
|
|
8
|
+
rimoriInfo = null;
|
|
9
|
+
isMessageChannelReady = false;
|
|
10
|
+
pendingRequests = [];
|
|
11
|
+
updateCallbacks = new Set();
|
|
13
12
|
constructor(pluginId, standalone) {
|
|
14
13
|
this.pluginId = pluginId;
|
|
15
|
-
this.port = null;
|
|
16
|
-
this.queryParams = {};
|
|
17
|
-
this.supabase = null;
|
|
18
|
-
this.rimoriInfo = null;
|
|
19
|
-
this.isMessageChannelReady = false;
|
|
20
|
-
this.pendingRequests = [];
|
|
21
|
-
this.updateCallbacks = new Set();
|
|
22
14
|
this.getClient = this.getClient.bind(this);
|
|
23
15
|
//no need to forward messages to parent in standalone mode or worker context
|
|
24
16
|
if (standalone)
|
|
@@ -69,9 +61,8 @@ export class RimoriCommunicationHandler {
|
|
|
69
61
|
};
|
|
70
62
|
// Forward plugin events to parent (only after MessageChannel is ready)
|
|
71
63
|
EventBus.on('*', (ev) => {
|
|
72
|
-
var _a;
|
|
73
64
|
if (ev.sender === this.pluginId && !ev.topic.startsWith('self.')) {
|
|
74
|
-
|
|
65
|
+
this.port?.postMessage({ event: ev });
|
|
75
66
|
}
|
|
76
67
|
});
|
|
77
68
|
// Listen for updates from rimori-main (data changes, token refresh, etc.)
|
|
@@ -129,9 +120,8 @@ export class RimoriCommunicationHandler {
|
|
|
129
120
|
return this.queryParams[key] || null;
|
|
130
121
|
}
|
|
131
122
|
getSupabase(url, key, token) {
|
|
132
|
-
var _a;
|
|
133
123
|
return new PostgrestClient(`${url}/rest/v1`, {
|
|
134
|
-
schema:
|
|
124
|
+
schema: this.rimoriInfo?.dbSchema,
|
|
135
125
|
headers: {
|
|
136
126
|
apikey: key,
|
|
137
127
|
Authorization: `Bearer ${token}`,
|
|
@@ -139,69 +129,66 @@ export class RimoriCommunicationHandler {
|
|
|
139
129
|
},
|
|
140
130
|
});
|
|
141
131
|
}
|
|
142
|
-
getClient() {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
132
|
+
async getClient() {
|
|
133
|
+
// Return cached client if valid
|
|
134
|
+
if (this.supabase && this.rimoriInfo && this.rimoriInfo.expiration > new Date()) {
|
|
135
|
+
return { supabase: this.supabase, info: this.rimoriInfo };
|
|
136
|
+
}
|
|
137
|
+
// If MessageChannel is not ready yet, queue the request
|
|
138
|
+
if (!this.isMessageChannelReady) {
|
|
139
|
+
return new Promise((resolve) => {
|
|
140
|
+
this.pendingRequests.push(async () => {
|
|
141
|
+
const result = await this.getClient();
|
|
142
|
+
resolve(result);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// If we have rimoriInfo from MessageChannel init, use it directly
|
|
147
|
+
if (this.rimoriInfo && this.supabase) {
|
|
148
|
+
return { supabase: this.supabase, info: this.rimoriInfo };
|
|
149
|
+
}
|
|
150
|
+
// Fallback: request from parent
|
|
151
|
+
if (!this.rimoriInfo) {
|
|
152
|
+
if (typeof WorkerGlobalScope !== 'undefined') {
|
|
153
|
+
// In worker context, send request via self.postMessage to WorkerHandler
|
|
154
|
+
const eventId = Math.floor(Math.random() * 1000000000);
|
|
155
|
+
const requestEvent = {
|
|
156
|
+
event: {
|
|
157
|
+
timestamp: new Date().toISOString(),
|
|
158
|
+
eventId,
|
|
159
|
+
sender: this.pluginId,
|
|
160
|
+
topic: 'global.supabase.requestAccess',
|
|
161
|
+
data: {},
|
|
162
|
+
debug: false,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
150
165
|
return new Promise((resolve) => {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
// Listen for the response
|
|
167
|
+
const originalOnMessage = self.onmessage;
|
|
168
|
+
self.onmessage = (event) => {
|
|
169
|
+
if (event.data?.topic === 'global.supabase.requestAccess' && event.data?.eventId === eventId) {
|
|
170
|
+
this.rimoriInfo = event.data.data;
|
|
171
|
+
this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
|
|
172
|
+
self.onmessage = originalOnMessage; // Restore original handler
|
|
173
|
+
resolve({ supabase: this.supabase, info: this.rimoriInfo });
|
|
174
|
+
}
|
|
175
|
+
else if (originalOnMessage) {
|
|
176
|
+
originalOnMessage.call(self, event);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
// Send the request
|
|
180
|
+
self.postMessage(requestEvent);
|
|
155
181
|
});
|
|
156
182
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (typeof WorkerGlobalScope !== 'undefined') {
|
|
164
|
-
// In worker context, send request via self.postMessage to WorkerHandler
|
|
165
|
-
const eventId = Math.floor(Math.random() * 1000000000);
|
|
166
|
-
const requestEvent = {
|
|
167
|
-
event: {
|
|
168
|
-
timestamp: new Date().toISOString(),
|
|
169
|
-
eventId,
|
|
170
|
-
sender: this.pluginId,
|
|
171
|
-
topic: 'global.supabase.requestAccess',
|
|
172
|
-
data: {},
|
|
173
|
-
debug: false,
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
return new Promise((resolve) => {
|
|
177
|
-
// Listen for the response
|
|
178
|
-
const originalOnMessage = self.onmessage;
|
|
179
|
-
self.onmessage = (event) => {
|
|
180
|
-
var _a, _b;
|
|
181
|
-
if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.topic) === 'global.supabase.requestAccess' && ((_b = event.data) === null || _b === void 0 ? void 0 : _b.eventId) === eventId) {
|
|
182
|
-
this.rimoriInfo = event.data.data;
|
|
183
|
-
this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
|
|
184
|
-
self.onmessage = originalOnMessage; // Restore original handler
|
|
185
|
-
resolve({ supabase: this.supabase, info: this.rimoriInfo });
|
|
186
|
-
}
|
|
187
|
-
else if (originalOnMessage) {
|
|
188
|
-
originalOnMessage.call(self, event);
|
|
189
|
-
}
|
|
190
|
-
};
|
|
191
|
-
// Send the request
|
|
192
|
-
self.postMessage(requestEvent);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
// In main thread context, use EventBus
|
|
197
|
-
const { data } = yield EventBus.request(this.pluginId, 'global.supabase.requestAccess');
|
|
198
|
-
// console.log({ data });
|
|
199
|
-
this.rimoriInfo = data;
|
|
200
|
-
this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
|
|
201
|
-
}
|
|
183
|
+
else {
|
|
184
|
+
// In main thread context, use EventBus
|
|
185
|
+
const { data } = await EventBus.request(this.pluginId, 'global.supabase.requestAccess');
|
|
186
|
+
// console.log({ data });
|
|
187
|
+
this.rimoriInfo = data;
|
|
188
|
+
this.supabase = this.getSupabase(this.rimoriInfo.url, this.rimoriInfo.key, this.rimoriInfo.token);
|
|
202
189
|
}
|
|
203
|
-
|
|
204
|
-
}
|
|
190
|
+
}
|
|
191
|
+
return { supabase: this.supabase, info: this.rimoriInfo };
|
|
205
192
|
}
|
|
206
193
|
/**
|
|
207
194
|
* Handles updates to RimoriInfo from rimori-main.
|
|
@@ -257,7 +244,12 @@ export class RimoriCommunicationHandler {
|
|
|
257
244
|
if (typeof options.body === 'string') {
|
|
258
245
|
defaultContentType['Content-Type'] = 'application/json';
|
|
259
246
|
}
|
|
260
|
-
const headers =
|
|
261
|
-
|
|
247
|
+
const headers = {
|
|
248
|
+
...defaultContentType,
|
|
249
|
+
...options.headers,
|
|
250
|
+
Authorization: `Bearer ${token}`,
|
|
251
|
+
'plugin-id': this.pluginId,
|
|
252
|
+
};
|
|
253
|
+
return fetch(backendUrl + url, { ...options, headers });
|
|
262
254
|
}
|
|
263
255
|
}
|
package/dist/plugin/Logger.js
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
/**
|
|
11
2
|
* Singleton Logger class for Rimori client plugins.
|
|
12
3
|
* Handles all logging levels, production filtering, and log transmission to Rimori.
|
|
13
4
|
* Overrides console methods globally for seamless integration.
|
|
14
5
|
*/
|
|
15
6
|
export class Logger {
|
|
7
|
+
static instance;
|
|
8
|
+
isProduction;
|
|
9
|
+
logs = [];
|
|
10
|
+
logIdCounter = 0;
|
|
11
|
+
originalConsole;
|
|
12
|
+
mousePosition = null;
|
|
16
13
|
constructor(rimori, isProduction) {
|
|
17
|
-
this.logs = [];
|
|
18
|
-
this.logIdCounter = 0;
|
|
19
|
-
this.mousePosition = null;
|
|
20
14
|
this.isProduction = this.validateIsProduction(isProduction);
|
|
21
15
|
// Store original console methods
|
|
22
16
|
this.originalConsole = {
|
|
@@ -34,8 +28,8 @@ export class Logger {
|
|
|
34
28
|
this.exposeToDevTools();
|
|
35
29
|
// Set up navigation clearing
|
|
36
30
|
this.setupNavigationClearing();
|
|
37
|
-
rimori.event.respond('logging.requestPluginLogs', () =>
|
|
38
|
-
this.addLogEntry(
|
|
31
|
+
rimori.event.respond('logging.requestPluginLogs', async () => {
|
|
32
|
+
this.addLogEntry(await this.createLogEntry('info', 'Screenshot capture', undefined, true));
|
|
39
33
|
const logs = {
|
|
40
34
|
logs: this.logs,
|
|
41
35
|
pluginId: rimori.plugin.pluginId,
|
|
@@ -44,7 +38,7 @@ export class Logger {
|
|
|
44
38
|
this.logs = [];
|
|
45
39
|
this.logIdCounter = 0;
|
|
46
40
|
return logs;
|
|
47
|
-
})
|
|
41
|
+
});
|
|
48
42
|
}
|
|
49
43
|
/**
|
|
50
44
|
* Initialize the Logger singleton and override console methods globally.
|
|
@@ -200,29 +194,27 @@ export class Logger {
|
|
|
200
194
|
* @param level - Log level
|
|
201
195
|
* @param args - Console arguments
|
|
202
196
|
*/
|
|
203
|
-
handleConsoleCall(level, args) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
197
|
+
async handleConsoleCall(level, args) {
|
|
198
|
+
// Skip if this is a production log that shouldn't be stored
|
|
199
|
+
if (this.isProduction && (level === 'debug' || level === 'info')) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Convert console arguments to message and data
|
|
203
|
+
const message = args
|
|
204
|
+
.map((arg) => {
|
|
205
|
+
if (typeof arg !== 'object')
|
|
206
|
+
return arg;
|
|
207
|
+
try {
|
|
208
|
+
return JSON.stringify(arg);
|
|
208
209
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
catch (error) {
|
|
218
|
-
return 'Error adding object to log: ' + error.message + ' ' + String(arg);
|
|
219
|
-
}
|
|
220
|
-
})
|
|
221
|
-
.join(' ');
|
|
222
|
-
const data = args.length > 1 ? args.slice(1) : undefined;
|
|
223
|
-
const entry = yield this.createLogEntry(level, message, data);
|
|
224
|
-
this.addLogEntry(entry);
|
|
225
|
-
});
|
|
210
|
+
catch (error) {
|
|
211
|
+
return 'Error adding object to log: ' + error.message + ' ' + String(arg);
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
.join(' ');
|
|
215
|
+
const data = args.length > 1 ? args.slice(1) : undefined;
|
|
216
|
+
const entry = await this.createLogEntry(level, message, data);
|
|
217
|
+
this.addLogEntry(entry);
|
|
226
218
|
}
|
|
227
219
|
/**
|
|
228
220
|
* Get browser and system information for debugging.
|
|
@@ -244,28 +236,26 @@ export class Logger {
|
|
|
244
236
|
* Dynamically imports html2canvas only in browser environments.
|
|
245
237
|
* @returns Promise resolving to base64 screenshot or null if failed
|
|
246
238
|
*/
|
|
247
|
-
captureScreenshot() {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
});
|
|
239
|
+
async captureScreenshot() {
|
|
240
|
+
// Only attempt to capture screenshot in browser environments
|
|
241
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
try {
|
|
245
|
+
// Dynamically import html2canvas only when window is available
|
|
246
|
+
// html2canvas is an optional peer dependency - provided by @rimori/react-client
|
|
247
|
+
// In worker builds, this import should be marked as external to prevent bundling
|
|
248
|
+
const html2canvas = (await import('html2canvas')).default;
|
|
249
|
+
const canvas = await html2canvas(document.body);
|
|
250
|
+
const screenshot = canvas.toDataURL('image/png');
|
|
251
|
+
// this.originalConsole.log("screenshot captured", screenshot)
|
|
252
|
+
return screenshot;
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
// html2canvas may not be available (e.g., in workers or when not installed)
|
|
256
|
+
// Silently fail to avoid breaking logging functionality
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
269
259
|
}
|
|
270
260
|
/**
|
|
271
261
|
* Create a log entry with context information.
|
|
@@ -274,37 +264,35 @@ export class Logger {
|
|
|
274
264
|
* @param data - Additional data
|
|
275
265
|
* @returns Log entry
|
|
276
266
|
*/
|
|
277
|
-
createLogEntry(level, message, data, forceScreenshot) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
282
|
-
return {
|
|
283
|
-
id: `log_${++this.logIdCounter}_${Date.now()}`,
|
|
284
|
-
timestamp: new Date().toISOString(),
|
|
285
|
-
level,
|
|
286
|
-
message,
|
|
287
|
-
data,
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
context.url = window.location.href;
|
|
291
|
-
// Add browser info (this method now handles worker context internally)
|
|
292
|
-
context.browserInfo = this.getBrowserInfo();
|
|
293
|
-
context.userAgent = context.browserInfo.userAgent;
|
|
294
|
-
// Add screenshot and mouse position if level is error or warn
|
|
295
|
-
if (level === 'error' || level === 'warn' || forceScreenshot) {
|
|
296
|
-
context.screenshot = (yield this.captureScreenshot()) || undefined;
|
|
297
|
-
context.mousePosition = this.mousePosition || undefined;
|
|
298
|
-
}
|
|
267
|
+
async createLogEntry(level, message, data, forceScreenshot) {
|
|
268
|
+
const context = {};
|
|
269
|
+
// Add URL if available
|
|
270
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
299
271
|
return {
|
|
300
272
|
id: `log_${++this.logIdCounter}_${Date.now()}`,
|
|
301
273
|
timestamp: new Date().toISOString(),
|
|
302
274
|
level,
|
|
303
275
|
message,
|
|
304
276
|
data,
|
|
305
|
-
context: context,
|
|
306
277
|
};
|
|
307
|
-
}
|
|
278
|
+
}
|
|
279
|
+
context.url = window.location.href;
|
|
280
|
+
// Add browser info (this method now handles worker context internally)
|
|
281
|
+
context.browserInfo = this.getBrowserInfo();
|
|
282
|
+
context.userAgent = context.browserInfo.userAgent;
|
|
283
|
+
// Add screenshot and mouse position if level is error or warn
|
|
284
|
+
if (level === 'error' || level === 'warn' || forceScreenshot) {
|
|
285
|
+
context.screenshot = (await this.captureScreenshot()) || undefined;
|
|
286
|
+
context.mousePosition = this.mousePosition || undefined;
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
id: `log_${++this.logIdCounter}_${Date.now()}`,
|
|
290
|
+
timestamp: new Date().toISOString(),
|
|
291
|
+
level,
|
|
292
|
+
message,
|
|
293
|
+
data,
|
|
294
|
+
context: context,
|
|
295
|
+
};
|
|
308
296
|
}
|
|
309
297
|
/**
|
|
310
298
|
* Add a log entry to the internal log array.
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { SharedContentController } from './module/SharedContentController';
|
|
11
2
|
import { RimoriCommunicationHandler } from './CommunicationHandler';
|
|
12
3
|
import { Logger } from './Logger';
|
|
@@ -19,17 +10,21 @@ import { StorageModule } from './module/StorageModule';
|
|
|
19
10
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
20
11
|
import { EventBus, EventBusHandler } from '../fromRimori/EventBus';
|
|
21
12
|
export class RimoriClient {
|
|
13
|
+
static instance;
|
|
14
|
+
controller;
|
|
15
|
+
sharedContent;
|
|
16
|
+
db;
|
|
17
|
+
event;
|
|
18
|
+
plugin;
|
|
19
|
+
ai;
|
|
20
|
+
exercise;
|
|
21
|
+
/** Upload and manage images stored in Supabase via the backend. */
|
|
22
|
+
storage;
|
|
23
|
+
/** The EventBus instance used by this client. In federation mode this is a per-plugin instance. */
|
|
24
|
+
eventBus;
|
|
22
25
|
constructor(controller, supabase, info, eventBus) {
|
|
23
|
-
this.navigation = {
|
|
24
|
-
toDashboard: () => {
|
|
25
|
-
this.event.emit('global.navigation.triggerToDashboard');
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
this.runtime = {
|
|
29
|
-
fetchBackend: (url, options = {}) => this.controller.fetchBackend(url, options),
|
|
30
|
-
};
|
|
31
26
|
this.controller = controller;
|
|
32
|
-
this.eventBus = eventBus
|
|
27
|
+
this.eventBus = eventBus ?? EventBus;
|
|
33
28
|
this.sharedContent = new SharedContentController(supabase, this);
|
|
34
29
|
this.ai = new AIModule(controller);
|
|
35
30
|
this.ai.setOnRateLimited((exercisesRemaining) => {
|
|
@@ -67,22 +62,27 @@ export class RimoriClient {
|
|
|
67
62
|
// subscribes to triggerUpdate events. PluginEventBridge forwards host-bus events to
|
|
68
63
|
// this plugin's isolated eventBus, so we listen here and hand off to the controller.
|
|
69
64
|
eventBus.on(`${info.pluginId}.supabase.triggerUpdate`, (ev) => {
|
|
70
|
-
|
|
71
|
-
console.log('[RimoriClient] Federated triggerUpdate received for', info.pluginId, '| ttsEnabled:', (_a = ev.data) === null || _a === void 0 ? void 0 : _a.ttsEnabled);
|
|
65
|
+
console.log('[RimoriClient] Federated triggerUpdate received for', info.pluginId, '| ttsEnabled:', ev.data?.ttsEnabled);
|
|
72
66
|
controller.handleRimoriInfoUpdate(ev.data);
|
|
73
67
|
});
|
|
74
68
|
return client;
|
|
75
69
|
}
|
|
76
|
-
static getInstance(pluginId) {
|
|
77
|
-
|
|
78
|
-
if (!
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return RimoriClient.instance;
|
|
86
|
-
});
|
|
70
|
+
static async getInstance(pluginId) {
|
|
71
|
+
if (!RimoriClient.instance) {
|
|
72
|
+
if (!pluginId)
|
|
73
|
+
throw new Error('Plugin ID is required');
|
|
74
|
+
const controller = new RimoriCommunicationHandler(pluginId, false);
|
|
75
|
+
const client = await controller.getClient();
|
|
76
|
+
RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
|
|
77
|
+
}
|
|
78
|
+
return RimoriClient.instance;
|
|
87
79
|
}
|
|
80
|
+
navigation = {
|
|
81
|
+
toDashboard: () => {
|
|
82
|
+
this.event.emit('global.navigation.triggerToDashboard');
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
runtime = {
|
|
86
|
+
fetchBackend: (url, options = {}) => this.controller.fetchBackend(url, options),
|
|
87
|
+
};
|
|
88
88
|
}
|