@rimori/client 2.5.32 → 2.5.33

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.
Files changed (28) hide show
  1. package/dist/cli/scripts/init/dev-registration.js +118 -136
  2. package/dist/cli/scripts/init/main.js +116 -127
  3. package/dist/cli/scripts/init/package-setup.js +15 -2
  4. package/dist/cli/scripts/release/detect-translation-languages.js +24 -35
  5. package/dist/cli/scripts/release/release-config-upload.js +87 -100
  6. package/dist/cli/scripts/release/release-db-update.js +70 -81
  7. package/dist/cli/scripts/release/release-file-upload.js +75 -91
  8. package/dist/cli/scripts/release/release-prompts-upload.js +60 -72
  9. package/dist/cli/scripts/release/release.js +20 -31
  10. package/dist/controller/AccomplishmentController.js +12 -12
  11. package/dist/controller/AudioController.js +15 -33
  12. package/dist/controller/TranslationController.js +108 -118
  13. package/dist/fromRimori/EventBus.js +20 -31
  14. package/dist/plugin/CommunicationHandler.js +73 -81
  15. package/dist/plugin/Logger.js +71 -83
  16. package/dist/plugin/RimoriClient.js +31 -31
  17. package/dist/plugin/StandaloneClient.js +81 -98
  18. package/dist/plugin/TTS/ChunkedAudioPlayer.js +31 -41
  19. package/dist/plugin/TTS/MessageSender.js +28 -37
  20. package/dist/plugin/module/AIModule.js +215 -237
  21. package/dist/plugin/module/DbModule.js +22 -31
  22. package/dist/plugin/module/EventModule.js +23 -32
  23. package/dist/plugin/module/ExerciseModule.js +42 -56
  24. package/dist/plugin/module/PluginModule.js +97 -106
  25. package/dist/plugin/module/SharedContentController.js +170 -207
  26. package/dist/plugin/module/StorageModule.js +18 -29
  27. package/dist/worker/WorkerSetup.js +23 -34
  28. 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) => __awaiter(this, void 0, void 0, function* () {
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' ? yield handler(data) : handler;
191
+ const response = typeof handler === 'function' ? await handler(data) : handler;
200
192
  this.emit(sender, topic, response, data.eventId);
201
- }), finalIgnoreSender);
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 === null || listener === void 0 ? void 0 : listener.off();
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
- return __awaiter(this, void 0, void 0, function* () {
260
- if (!this.validateTopic(topic)) {
261
- this.logAndThrowError(true, `Invalid topic: ` + topic);
262
- }
263
- const event = this.createEvent(sender, topic, data || {}, undefined, aiSessionToken);
264
- this.logIfDebug(`Requesting data from ` + topic, { event });
265
- return new Promise((resolve) => {
266
- this.responseResolvers.set(event.eventId, (value) => resolve(value));
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
- (_a = this.port) === null || _a === void 0 ? void 0 : _a.postMessage({ event: ev });
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: (_a = this.rimoriInfo) === null || _a === void 0 ? void 0 : _a.dbSchema,
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
- return __awaiter(this, void 0, void 0, function* () {
144
- // Return cached client if valid
145
- if (this.supabase && this.rimoriInfo && this.rimoriInfo.expiration > new Date()) {
146
- return { supabase: this.supabase, info: this.rimoriInfo };
147
- }
148
- // If MessageChannel is not ready yet, queue the request
149
- if (!this.isMessageChannelReady) {
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
- this.pendingRequests.push(() => __awaiter(this, void 0, void 0, function* () {
152
- const result = yield this.getClient();
153
- resolve(result);
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
- // If we have rimoriInfo from MessageChannel init, use it directly
158
- if (this.rimoriInfo && this.supabase) {
159
- return { supabase: this.supabase, info: this.rimoriInfo };
160
- }
161
- // Fallback: request from parent
162
- if (!this.rimoriInfo) {
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
- return { supabase: this.supabase, info: this.rimoriInfo };
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 = Object.assign(Object.assign(Object.assign({}, defaultContentType), options.headers), { Authorization: `Bearer ${token}`, 'plugin-id': this.pluginId });
261
- return fetch(backendUrl + url, Object.assign(Object.assign({}, options), { headers }));
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
  }
@@ -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', () => __awaiter(this, void 0, void 0, function* () {
38
- this.addLogEntry(yield this.createLogEntry('info', 'Screenshot capture', undefined, true));
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
- return __awaiter(this, void 0, void 0, function* () {
205
- // Skip if this is a production log that shouldn't be stored
206
- if (this.isProduction && (level === 'debug' || level === 'info')) {
207
- return;
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
- // Convert console arguments to message and data
210
- const message = args
211
- .map((arg) => {
212
- if (typeof arg !== 'object')
213
- return arg;
214
- try {
215
- return JSON.stringify(arg);
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
- return __awaiter(this, void 0, void 0, function* () {
249
- // Only attempt to capture screenshot in browser environments
250
- if (typeof window === 'undefined' || typeof document === 'undefined') {
251
- return null;
252
- }
253
- try {
254
- // Dynamically import html2canvas only when window is available
255
- // html2canvas is an optional peer dependency - provided by @rimori/react-client
256
- // In worker builds, this import should be marked as external to prevent bundling
257
- const html2canvas = (yield import('html2canvas')).default;
258
- const canvas = yield html2canvas(document.body);
259
- const screenshot = canvas.toDataURL('image/png');
260
- // this.originalConsole.log("screenshot captured", screenshot)
261
- return screenshot;
262
- }
263
- catch (error) {
264
- // html2canvas may not be available (e.g., in workers or when not installed)
265
- // Silently fail to avoid breaking logging functionality
266
- return null;
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
- return __awaiter(this, void 0, void 0, function* () {
279
- const context = {};
280
- // Add URL if available
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 !== null && eventBus !== void 0 ? 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
- var _a;
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
- return __awaiter(this, void 0, void 0, function* () {
78
- if (!RimoriClient.instance) {
79
- if (!pluginId)
80
- throw new Error('Plugin ID is required');
81
- const controller = new RimoriCommunicationHandler(pluginId, false);
82
- const client = yield controller.getClient();
83
- RimoriClient.instance = new RimoriClient(controller, client.supabase, client.info);
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
  }