@rimori/client 1.3.1 → 1.4.3

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 (148) hide show
  1. package/.prettierignore +35 -0
  2. package/README.md +77 -71
  3. package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
  4. package/dist/cli/scripts/init/dev-registration.js +4 -4
  5. package/dist/cli/scripts/init/main.js +1 -1
  6. package/dist/cli/scripts/init/package-setup.d.ts +1 -1
  7. package/dist/cli/scripts/init/package-setup.js +3 -3
  8. package/dist/cli/scripts/init/router-transformer.js +19 -12
  9. package/dist/cli/scripts/init/vite-config.d.ts +2 -2
  10. package/dist/cli/scripts/init/vite-config.js +2 -2
  11. package/dist/cli/scripts/release/release-config-upload.js +9 -9
  12. package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
  13. package/dist/cli/scripts/release/release-db-update.js +9 -9
  14. package/dist/cli/scripts/release/release-file-upload.js +2 -2
  15. package/dist/cli/scripts/release/release.js +2 -2
  16. package/dist/cli/types/DatabaseTypes.d.ts +2 -2
  17. package/dist/components/CRUDModal.d.ts +1 -1
  18. package/dist/components/CRUDModal.js +3 -3
  19. package/dist/components/MarkdownEditor.js +16 -16
  20. package/dist/components/Spinner.js +2 -2
  21. package/dist/components/ai/Assistant.js +7 -8
  22. package/dist/components/ai/Avatar.d.ts +2 -2
  23. package/dist/components/ai/Avatar.js +14 -7
  24. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
  25. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
  26. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
  27. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
  28. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
  29. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
  30. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
  31. package/dist/components/audio/Playbutton.js +10 -7
  32. package/dist/components/components/ContextMenu.d.ts +1 -1
  33. package/dist/components/components/ContextMenu.js +19 -16
  34. package/dist/components.d.ts +10 -10
  35. package/dist/components.js +10 -10
  36. package/dist/core/controller/AIController.d.ts +2 -2
  37. package/dist/core/controller/AIController.js +20 -18
  38. package/dist/core/controller/ExerciseController.d.ts +52 -0
  39. package/dist/core/controller/ExerciseController.js +73 -0
  40. package/dist/core/controller/ObjectController.js +5 -5
  41. package/dist/core/controller/SettingsController.d.ts +22 -7
  42. package/dist/core/controller/SettingsController.js +73 -8
  43. package/dist/core/controller/SharedContentController.d.ts +3 -3
  44. package/dist/core/controller/SharedContentController.js +38 -20
  45. package/dist/core/controller/VoiceController.js +6 -4
  46. package/dist/core/core.d.ts +15 -14
  47. package/dist/core/core.js +7 -7
  48. package/dist/fromRimori/EventBus.js +23 -23
  49. package/dist/fromRimori/PluginTypes.d.ts +4 -4
  50. package/dist/hooks/UseChatHook.d.ts +3 -3
  51. package/dist/hooks/UseChatHook.js +9 -3
  52. package/dist/index.d.ts +10 -10
  53. package/dist/index.js +9 -9
  54. package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
  55. package/dist/plugin/AccomplishmentHandler.js +31 -27
  56. package/dist/plugin/AudioController.d.ts +1 -1
  57. package/dist/plugin/AudioController.js +6 -6
  58. package/dist/plugin/Logger.d.ts +5 -0
  59. package/dist/plugin/Logger.js +65 -13
  60. package/dist/plugin/PluginController.d.ts +7 -1
  61. package/dist/plugin/PluginController.js +32 -27
  62. package/dist/plugin/RimoriClient.d.ts +39 -14
  63. package/dist/plugin/RimoriClient.js +60 -31
  64. package/dist/plugin/StandaloneClient.d.ts +1 -1
  65. package/dist/plugin/StandaloneClient.js +35 -16
  66. package/dist/plugin/ThemeSetter.js +4 -4
  67. package/dist/providers/PluginProvider.js +44 -14
  68. package/dist/utils/Language.js +57 -57
  69. package/dist/utils/PluginUtils.js +3 -3
  70. package/dist/utils/difficultyConverter.d.ts +1 -1
  71. package/dist/utils/difficultyConverter.js +1 -1
  72. package/dist/utils/endpoint.js +2 -2
  73. package/dist/worker/WorkerSetup.d.ts +1 -1
  74. package/dist/worker/WorkerSetup.js +6 -6
  75. package/eslint.config.js +53 -0
  76. package/example/docs/devdocs.md +50 -40
  77. package/example/docs/overview.md +1 -1
  78. package/example/docs/userdocs.md +4 -1
  79. package/example/rimori.config.ts +51 -49
  80. package/example/worker/vite.config.ts +3 -3
  81. package/example/worker/worker.ts +2 -2
  82. package/package.json +17 -4
  83. package/prettier.config.js +8 -0
  84. package/src/cli/scripts/init/dev-registration.ts +5 -8
  85. package/src/cli/scripts/init/env-setup.ts +1 -1
  86. package/src/cli/scripts/init/file-operations.ts +1 -1
  87. package/src/cli/scripts/init/html-cleaner.ts +2 -5
  88. package/src/cli/scripts/init/main.ts +16 -13
  89. package/src/cli/scripts/init/package-setup.ts +11 -15
  90. package/src/cli/scripts/init/router-transformer.ts +40 -37
  91. package/src/cli/scripts/init/tailwind-config.ts +17 -26
  92. package/src/cli/scripts/init/vite-config.ts +3 -3
  93. package/src/cli/scripts/release/release-config-upload.ts +11 -11
  94. package/src/cli/scripts/release/release-db-update.ts +12 -12
  95. package/src/cli/scripts/release/release-file-upload.ts +3 -3
  96. package/src/cli/scripts/release/release.ts +4 -4
  97. package/src/cli/types/DatabaseTypes.ts +7 -8
  98. package/src/components/CRUDModal.tsx +64 -48
  99. package/src/components/MarkdownEditor.tsx +58 -27
  100. package/src/components/Spinner.tsx +24 -17
  101. package/src/components/ai/Assistant.tsx +70 -70
  102. package/src/components/ai/Avatar.tsx +20 -16
  103. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
  104. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
  105. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
  106. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
  107. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
  108. package/src/components/ai/utils.ts +4 -4
  109. package/src/components/audio/Playbutton.tsx +101 -93
  110. package/src/components/components/ContextMenu.tsx +47 -35
  111. package/src/components.ts +10 -10
  112. package/src/core/controller/AIController.ts +62 -50
  113. package/src/core/controller/ExerciseController.ts +98 -0
  114. package/src/core/controller/ObjectController.ts +15 -10
  115. package/src/core/controller/SettingsController.ts +89 -16
  116. package/src/core/controller/SharedContentController.ts +80 -44
  117. package/src/core/controller/VoiceController.ts +10 -8
  118. package/src/core/core.ts +15 -15
  119. package/src/fromRimori/EventBus.ts +76 -47
  120. package/src/fromRimori/PluginTypes.ts +26 -17
  121. package/src/fromRimori/readme.md +2 -2
  122. package/src/hooks/UseChatHook.ts +25 -15
  123. package/src/index.ts +10 -10
  124. package/src/plugin/AccomplishmentHandler.ts +53 -35
  125. package/src/plugin/AudioController.ts +18 -12
  126. package/src/plugin/Logger.ts +77 -19
  127. package/src/plugin/PluginController.ts +60 -44
  128. package/src/plugin/RimoriClient.ts +133 -69
  129. package/src/plugin/StandaloneClient.ts +51 -24
  130. package/src/plugin/ThemeSetter.ts +5 -5
  131. package/src/providers/PluginProvider.tsx +90 -36
  132. package/src/style.scss +3 -3
  133. package/src/utils/Language.ts +58 -58
  134. package/src/utils/PluginUtils.ts +16 -20
  135. package/src/utils/difficultyConverter.ts +2 -2
  136. package/src/utils/endpoint.ts +3 -2
  137. package/src/worker/WorkerSetup.ts +8 -9
  138. package/tsconfig.json +2 -4
  139. package/dist/components/LoggerExample.d.ts +0 -6
  140. package/dist/components/LoggerExample.js +0 -79
  141. package/dist/core/controller/AudioController.d.ts +0 -0
  142. package/dist/core/controller/AudioController.js +0 -1
  143. package/dist/hooks/UseLogger.d.ts +0 -30
  144. package/dist/hooks/UseLogger.js +0 -122
  145. package/dist/plugin/LoggerExample.d.ts +0 -16
  146. package/dist/plugin/LoggerExample.js +0 -140
  147. package/dist/utils/audioFormats.d.ts +0 -26
  148. package/dist/utils/audioFormats.js +0 -67
@@ -51,11 +51,7 @@ export function getRimoriClientVersion(): string {
51
51
  * @param param.isUpgrade - Whether this is an upgrade operation.
52
52
  * @throws {Error} if plugin directory doesn't exist or package.json is missing.
53
53
  */
54
- export function updatePackageJson({
55
- pluginId,
56
- port,
57
- isUpgrade = false,
58
- }: PackageSetupParams): void {
54
+ export function updatePackageJson({ pluginId, port, isUpgrade = false }: PackageSetupParams): void {
59
55
  // Get the plugin repo name from the current directory
60
56
  const pluginRepoName = path.basename(process.cwd());
61
57
  console.log(`Setting up plugin: ${pluginRepoName}`);
@@ -93,18 +89,18 @@ export function updatePackageJson({
93
89
  }
94
90
  packageJson.scripts = {
95
91
  ...packageJson.scripts,
96
- "dev": `vite --port ${port || 3000}`,
97
- "build": "yarn run check && vite build",
98
- "check": "tsc --project tsconfig.app.json --noEmit --pretty",
99
- "release:alpha": "yarn build && yarn rimori-release alpha",
100
- "release:beta": "yarn build && yarn rimori-release beta",
101
- "release:stable": "yarn build && yarn rimori-release stable",
102
- "dev:worker": "VITE_MINIFY=false vite build --watch --config worker/vite.config.ts",
103
- "build:worker": "vite build --config worker/vite.config.ts",
92
+ dev: `vite --port ${port || 3000}`,
93
+ build: 'yarn run check && vite build',
94
+ check: 'tsc --project tsconfig.app.json --noEmit --pretty',
95
+ 'release:alpha': 'yarn build && yarn rimori-release alpha',
96
+ 'release:beta': 'yarn build && yarn rimori-release beta',
97
+ 'release:stable': 'yarn build && yarn rimori-release stable',
98
+ 'dev:worker': 'VITE_MINIFY=false vite build --watch --config worker/vite.config.ts',
99
+ 'build:worker': 'vite build --config worker/vite.config.ts',
104
100
  };
105
101
  packageJson.dependencies = {
106
102
  ...packageJson.dependencies,
107
- "@rimori/client": rimoriClientVersion,
103
+ '@rimori/client': rimoriClientVersion,
108
104
  };
109
105
 
110
106
  // Write the updated package.json back to file
@@ -114,4 +110,4 @@ export function updatePackageJson({
114
110
  } catch (error) {
115
111
  throw new Error(`Failed to update package.json: ${error}`);
116
112
  }
117
- }
113
+ }
@@ -89,14 +89,14 @@ function detectRouteComponents(content: string): RouteComponent[] {
89
89
  }
90
90
 
91
91
  // For each component, find its corresponding import statement
92
- componentNames.forEach(componentName => {
92
+ componentNames.forEach((componentName) => {
93
93
  const importInfo = findImportForComponent(content, componentName);
94
94
  if (importInfo) {
95
95
  routeComponents.push({
96
96
  componentName,
97
97
  importStatement: importInfo.importStatement,
98
98
  importPath: importInfo.importPath,
99
- isDefaultImport: importInfo.isDefaultImport
99
+ isDefaultImport: importInfo.isDefaultImport,
100
100
  });
101
101
  }
102
102
  });
@@ -111,7 +111,10 @@ function detectRouteComponents(content: string): RouteComponent[] {
111
111
  * @param componentName - The component name to find import for
112
112
  * @returns Import information or null if not found
113
113
  */
114
- function findImportForComponent(content: string, componentName: string): {
114
+ function findImportForComponent(
115
+ content: string,
116
+ componentName: string,
117
+ ): {
115
118
  importStatement: string;
116
119
  importPath: string;
117
120
  isDefaultImport: boolean;
@@ -124,7 +127,7 @@ function findImportForComponent(content: string, componentName: string): {
124
127
  return {
125
128
  importStatement: defaultMatch[0],
126
129
  importPath: defaultMatch[1],
127
- isDefaultImport: true
130
+ isDefaultImport: true,
128
131
  };
129
132
  }
130
133
 
@@ -133,12 +136,12 @@ function findImportForComponent(content: string, componentName: string): {
133
136
  let namedMatch;
134
137
 
135
138
  while ((namedMatch = namedImportRegex.exec(content)) !== null) {
136
- const imports = namedMatch[1].split(',').map(imp => imp.trim());
139
+ const imports = namedMatch[1].split(',').map((imp) => imp.trim());
137
140
  if (imports.includes(componentName)) {
138
141
  return {
139
142
  importStatement: namedMatch[0],
140
143
  importPath: namedMatch[2],
141
- isDefaultImport: false
144
+ isDefaultImport: false,
142
145
  };
143
146
  }
144
147
  }
@@ -191,7 +194,10 @@ function addLazyImport(content: string): string {
191
194
  if (reactImportMatch) {
192
195
  // React import exists, add lazy to it
193
196
  const existingImports = reactImportMatch[1] || '';
194
- const importList = existingImports.split(',').map(imp => imp.trim()).filter(Boolean);
197
+ const importList = existingImports
198
+ .split(',')
199
+ .map((imp) => imp.trim())
200
+ .filter(Boolean);
195
201
 
196
202
  if (!importList.includes('lazy')) {
197
203
  importList.push('lazy');
@@ -200,16 +206,18 @@ function addLazyImport(content: string): string {
200
206
  importList.push('Suspense');
201
207
  }
202
208
 
203
- const newImport = importList.length > 0
204
- ? `import React, { ${importList.join(', ')} } from "react";`
205
- : `import React from "react";`;
209
+ const newImport =
210
+ importList.length > 0 ? `import React, { ${importList.join(', ')} } from "react";` : `import React from "react";`;
206
211
 
207
212
  return content.replace(reactImportMatch[0], newImport);
208
213
  } else {
209
214
  // No React import found, add it
210
215
  const firstImportMatch = content.match(/^import.*$/m);
211
216
  if (firstImportMatch) {
212
- return content.replace(firstImportMatch[0], `import React, { lazy, Suspense } from "react";\n${firstImportMatch[0]}`);
217
+ return content.replace(
218
+ firstImportMatch[0],
219
+ `import React, { lazy, Suspense } from "react";\n${firstImportMatch[0]}`,
220
+ );
213
221
  } else {
214
222
  // No imports found, add at the beginning
215
223
  return `import React, { lazy, Suspense } from "react";\n${content}`;
@@ -266,39 +274,34 @@ function transformImports(content: string): string {
266
274
  // Add new import line for PluginProvider
267
275
  const importMatch = content.match(/^(import.*from\s+["']react["'];?\s*\n)/m);
268
276
  if (importMatch) {
269
- content = content.replace(
270
- importMatch[0],
271
- `${importMatch[0]}import { PluginProvider } from "@rimori/client";\n`
272
- );
277
+ content = content.replace(importMatch[0], `${importMatch[0]}import { PluginProvider } from "@rimori/client";\n`);
273
278
  } else {
274
279
  // If no React import found, add at the beginning
275
280
  content = `import { PluginProvider } from "@rimori/client";\n${content}`;
276
281
  }
277
282
  } else {
278
283
  // Update existing @rimori/client import to include PluginProvider
279
- content = content.replace(
280
- /import\s*{\s*([^}]*)\s*}\s*from\s*["']@rimori\/client["'];?/,
281
- (match, imports) => {
282
- const importList = imports.split(',').map((imp: string) => imp.trim()).filter(Boolean);
283
- if (!importList.includes('PluginProvider')) {
284
- importList.push('PluginProvider');
285
- }
286
- return `import { ${importList.join(', ')} } from "@rimori/client";`;
284
+ content = content.replace(/import\s*{\s*([^}]*)\s*}\s*from\s*["']@rimori\/client["'];?/, (match, imports) => {
285
+ const importList = imports
286
+ .split(',')
287
+ .map((imp: string) => imp.trim())
288
+ .filter(Boolean);
289
+ if (!importList.includes('PluginProvider')) {
290
+ importList.push('PluginProvider');
287
291
  }
288
- );
292
+ return `import { ${importList.join(', ')} } from "@rimori/client";`;
293
+ });
289
294
  }
290
295
 
291
296
  // Transform react-router-dom import: replace BrowserRouter with HashRouter
292
- content = content.replace(
293
- /import\s*{\s*([^}]*)\s*}\s*from\s*["']react-router-dom["'];?/,
294
- (match, imports) => {
295
- const importList = imports.split(',').map((imp: string) => imp.trim()).filter(Boolean);
296
- const updatedImports = importList.map((imp: string) =>
297
- imp === 'BrowserRouter' ? 'HashRouter' : imp
298
- );
299
- return `import { ${updatedImports.join(', ')} } from "react-router-dom";`;
300
- }
301
- );
297
+ content = content.replace(/import\s*{\s*([^}]*)\s*}\s*from\s*["']react-router-dom["'];?/, (match, imports) => {
298
+ const importList = imports
299
+ .split(',')
300
+ .map((imp: string) => imp.trim())
301
+ .filter(Boolean);
302
+ const updatedImports = importList.map((imp: string) => (imp === 'BrowserRouter' ? 'HashRouter' : imp));
303
+ return `import { ${updatedImports.join(', ')} } from "react-router-dom";`;
304
+ });
302
305
 
303
306
  return content;
304
307
  }
@@ -315,15 +318,15 @@ function transformJSX(content: string, pluginId: string): string {
315
318
  content = content.replace(
316
319
  /<BrowserRouter(\s[^>]*)?>/,
317
320
  `<PluginProvider pluginId="${pluginId}">
318
- <HashRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>`
321
+ <HashRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>`,
319
322
  );
320
323
 
321
324
  // Replace closing BrowserRouter tag
322
325
  content = content.replace(
323
326
  /<\/BrowserRouter>/,
324
327
  `</HashRouter>
325
- </PluginProvider>`
328
+ </PluginProvider>`,
326
329
  );
327
330
 
328
331
  return content;
329
- }
332
+ }
@@ -21,16 +21,10 @@ export function updateTailwindConfig(): void {
21
21
 
22
22
  // Set darkMode to "class" if it exists, otherwise add it
23
23
  if (updatedContent.includes('darkMode:')) {
24
- updatedContent = updatedContent.replace(
25
- /darkMode:\s*\[?"[^"]*"?\]?,?/g,
26
- 'darkMode: ["class"],'
27
- );
24
+ updatedContent = updatedContent.replace(/darkMode:\s*\[?"[^"]*"?\]?,?/g, 'darkMode: ["class"],');
28
25
  } else {
29
26
  // Add darkMode after the opening brace
30
- updatedContent = updatedContent.replace(
31
- /export default \{/,
32
- 'export default {\n darkMode: ["class"],'
33
- );
27
+ updatedContent = updatedContent.replace(/export default \{/, 'export default {\n darkMode: ["class"],');
34
28
  }
35
29
 
36
30
  // Add Rimori client package to content array if not already present
@@ -38,31 +32,28 @@ export function updateTailwindConfig(): void {
38
32
  // Find the content array and add the Rimori client path
39
33
  if (updatedContent.includes('content:')) {
40
34
  // More precise regex to handle the content array properly
41
- updatedContent = updatedContent.replace(
42
- /(content:\s*\[)([\s\S]*?)(\])/,
43
- (match, start, content, end) => {
44
- // Clean up any existing double commas first
45
- let cleanContent = content.replace(/,\s*,/g, ',');
35
+ updatedContent = updatedContent.replace(/(content:\s*\[)([\s\S]*?)(\])/, (match, start, content, end) => {
36
+ // Clean up any existing double commas first
37
+ let cleanContent = content.replace(/,\s*,/g, ',');
46
38
 
47
- // Remove trailing comma and whitespace
48
- cleanContent = cleanContent.replace(/,\s*$/, '');
39
+ // Remove trailing comma and whitespace
40
+ cleanContent = cleanContent.replace(/,\s*$/, '');
49
41
 
50
- // Add the new path with proper formatting
51
- const newPath = '"node_modules/@rimori/client/dist/components/**/*.{js,jsx}"';
42
+ // Add the new path with proper formatting
43
+ const newPath = '"node_modules/@rimori/client/dist/components/**/*.{js,jsx}"';
52
44
 
53
- // If content is not empty, add comma before new entry
54
- if (cleanContent.trim()) {
55
- return `${start}${cleanContent},\n ${newPath}\n ${end}`;
56
- } else {
57
- return `${start}\n ${newPath}\n ${end}`;
58
- }
45
+ // If content is not empty, add comma before new entry
46
+ if (cleanContent.trim()) {
47
+ return `${start}${cleanContent},\n ${newPath}\n ${end}`;
48
+ } else {
49
+ return `${start}\n ${newPath}\n ${end}`;
59
50
  }
60
- );
51
+ });
61
52
  } else {
62
53
  // Add content array if it doesn't exist
63
54
  updatedContent = updatedContent.replace(
64
55
  /darkMode: \["class"\],/,
65
- 'darkMode: ["class"],\n content: [\n "./src/**/*.{js,jsx,ts,tsx}",\n "node_modules/@rimori/client/dist/components/**/*.{js,jsx}"\n ],'
56
+ 'darkMode: ["class"],\n content: [\n "./src/**/*.{js,jsx,ts,tsx}",\n "node_modules/@rimori/client/dist/components/**/*.{js,jsx}"\n ],',
66
57
  );
67
58
  }
68
59
  }
@@ -72,4 +63,4 @@ export function updateTailwindConfig(): void {
72
63
  } catch (error) {
73
64
  console.warn(`Warning: Could not update tailwind.config.ts: ${error instanceof Error ? error.message : error}`);
74
65
  }
75
- }
66
+ }
@@ -10,7 +10,7 @@ import * as path from 'path';
10
10
  */
11
11
  export function updateViteConfigBase({
12
12
  basePath = './',
13
- configPath = './vite.config.ts'
13
+ configPath = './vite.config.ts',
14
14
  }: {
15
15
  basePath?: string;
16
16
  configPath?: string;
@@ -56,7 +56,7 @@ export function updateViteConfigBase({
56
56
  * @returns The current base value or null if not found.
57
57
  */
58
58
  export function getCurrentViteBase({
59
- configPath = './vite.config.ts'
59
+ configPath = './vite.config.ts',
60
60
  }: {
61
61
  configPath?: string;
62
62
  } = {}): string | null {
@@ -70,4 +70,4 @@ export function getCurrentViteBase({
70
70
  const baseMatch = configContent.match(/base:\s*['"]([^'"]*)['"]/);
71
71
 
72
72
  return baseMatch ? baseMatch[1] : null;
73
- }
73
+ }
@@ -26,7 +26,7 @@ export async function sendConfiguration(config: Config): Promise<string> {
26
26
  // Transpile TypeScript to JavaScript
27
27
  const result = ts.transpile(configContent, {
28
28
  target: ts.ScriptTarget.ES2020,
29
- module: ts.ModuleKind.ES2020
29
+ module: ts.ModuleKind.ES2020,
30
30
  });
31
31
 
32
32
  // Create a temporary file to import the transpiled code
@@ -44,7 +44,7 @@ export async function sendConfiguration(config: Config): Promise<string> {
44
44
  // Clean up temp file even on error
45
45
  try {
46
46
  await fs.promises.unlink(tempFile);
47
- } catch (e) { }
47
+ } catch (e) {}
48
48
  throw error;
49
49
  }
50
50
 
@@ -67,7 +67,7 @@ export async function sendConfiguration(config: Config): Promise<string> {
67
67
  method: 'POST',
68
68
  headers: {
69
69
  'Content-Type': 'application/json',
70
- 'Authorization': `Bearer ${config.token}`
70
+ Authorization: `Bearer ${config.token}`,
71
71
  },
72
72
  body: JSON.stringify(requestBody),
73
73
  });
@@ -87,8 +87,8 @@ export async function sendConfiguration(config: Config): Promise<string> {
87
87
  throw new Error('Configuration upload failed');
88
88
  }
89
89
  } catch (e) {
90
- console.log("error", e);
91
- throw new Error("Error sending configuration");
90
+ console.log('error', e);
91
+ throw new Error('Error sending configuration');
92
92
  }
93
93
  } catch (error: any) {
94
94
  console.error('❌ Error sending configuration:', error.message);
@@ -101,14 +101,14 @@ export async function releasePlugin(config: Config, release_id: string): Promise
101
101
  method: 'POST',
102
102
  headers: {
103
103
  'Content-Type': 'application/json',
104
- 'Authorization': `Bearer ${config.token}`
104
+ Authorization: `Bearer ${config.token}`,
105
105
  },
106
- body: JSON.stringify({ plugin_id: config.plugin_id })
106
+ body: JSON.stringify({ plugin_id: config.plugin_id }),
107
107
  });
108
108
 
109
109
  if (!response.ok) {
110
- console.log("Response:", await response.text());
111
- throw new Error("Failed to release plugin");
110
+ console.log('Response:', await response.text());
111
+ throw new Error('Failed to release plugin');
112
112
  }
113
- console.log("✅ Plugin released successfully");
114
- }
113
+ console.log('✅ Plugin released successfully');
114
+ }
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import ts from 'typescript';
4
- import { Config } from "./release";
4
+ import { Config } from './release';
5
5
 
6
6
  /**
7
7
  * Read and send the database configuration to the release endpoint
@@ -27,7 +27,7 @@ export default async function dbUpdate(config: Config, release_id: string): Prom
27
27
  // Transpile TypeScript to JavaScript
28
28
  const result = ts.transpile(dbConfigContent, {
29
29
  target: ts.ScriptTarget.ES2020,
30
- module: ts.ModuleKind.ES2020
30
+ module: ts.ModuleKind.ES2020,
31
31
  });
32
32
 
33
33
  // Create a temporary file to import the transpiled code
@@ -45,7 +45,7 @@ export default async function dbUpdate(config: Config, release_id: string): Prom
45
45
  // Clean up temp file even on error
46
46
  try {
47
47
  await fs.promises.unlink(tempFile);
48
- } catch (e) { }
48
+ } catch (e) {}
49
49
  throw error;
50
50
  }
51
51
 
@@ -66,32 +66,32 @@ export default async function dbUpdate(config: Config, release_id: string): Prom
66
66
  method: 'POST',
67
67
  headers: {
68
68
  'Content-Type': 'application/json',
69
- 'Authorization': `Bearer ${config.token}`
69
+ Authorization: `Bearer ${config.token}`,
70
70
  },
71
71
  body: JSON.stringify(requestBody),
72
72
  }).catch((e) => {
73
- console.log("error", e);
74
- throw new Error("Error sending database configuration");
73
+ console.log('error', e);
74
+ throw new Error('Error sending database configuration');
75
75
  });
76
76
  try {
77
77
  const responseText = await response.text().catch((e) => {
78
- console.log("error", e);
79
- throw new Error("Error sending database configuration");
78
+ console.log('error', e);
79
+ throw new Error('Error sending database configuration');
80
80
  });
81
81
 
82
82
  const responseData = JSON.parse(responseText);
83
83
  if (response.ok) {
84
84
  console.log('✅ Database configuration deployed successfully!');
85
85
  } else {
86
- console.log("responseData", responseData);
86
+ console.log('responseData', responseData);
87
87
  throw new Error(responseData.message);
88
88
  }
89
89
  } catch (e) {
90
- console.log("error", e);
91
- throw new Error("Error sending database configuration");
90
+ console.log('error', e);
91
+ throw new Error('Error sending database configuration');
92
92
  }
93
93
  } catch (error: any) {
94
94
  console.error('❌ Error sending database configuration:', error.message);
95
95
  throw error;
96
96
  }
97
- }
97
+ }
@@ -52,7 +52,7 @@ export async function uploadDirectory(config: Config, release_id: string): Promi
52
52
  pathMapping[fileId] = relativePath;
53
53
 
54
54
  // Create a Blob with the file content and content type
55
- const blob = new Blob([fileContent], { type: contentType });
55
+ const blob = new Blob([new Uint8Array(fileContent)], { type: contentType });
56
56
 
57
57
  // Add file to FormData with ID_filename format
58
58
  const fileName = `${fileId}_${path.basename(filePath)}`;
@@ -69,7 +69,7 @@ export async function uploadDirectory(config: Config, release_id: string): Promi
69
69
  // Upload to the release endpoint
70
70
  const response = await fetch(`${config.domain}/release/${release_id}/files`, {
71
71
  method: 'POST',
72
- headers: { 'Authorization': `Bearer ${config.token}` },
72
+ headers: { Authorization: `Bearer ${config.token}` },
73
73
  body: formData,
74
74
  });
75
75
 
@@ -135,4 +135,4 @@ function getContentType(filePath: string): string {
135
135
  const contentType = contentTypes[ext || ''];
136
136
  if (!contentType) throw new Error(`Unsupported file type: ${ext}`);
137
137
  return contentType;
138
- }
138
+ }
@@ -38,9 +38,9 @@ const config = {
38
38
  release_channel: releaseChannel,
39
39
  plugin_id: pluginId,
40
40
  token: RIMORI_TOKEN,
41
- domain: process.env.RIMORI_BACKEND_URL || "https://api.rimori.se",
41
+ domain: process.env.RIMORI_BACKEND_URL || 'https://api.rimori.se',
42
42
  rimori_client_version: packageJson.dependencies['@rimori/client'].replace('^', ''),
43
- }
43
+ };
44
44
 
45
45
  export type Config = typeof config;
46
46
 
@@ -61,9 +61,9 @@ async function releaseProcess(): Promise<void> {
61
61
  // Then release the plugin
62
62
  await releasePlugin(config, release_id);
63
63
  } catch (error: any) {
64
- console.log("❌ Error:", error.message);
64
+ console.log('❌ Error:', error.message);
65
65
  process.exit(1);
66
66
  }
67
67
  }
68
68
 
69
- releaseProcess();
69
+ releaseProcess();
@@ -1,4 +1,3 @@
1
-
2
1
  // Database table structure definitions
3
2
 
4
3
  /**
@@ -45,15 +44,15 @@ export interface DbColumnDefinition {
45
44
  // primary_key?: boolean;
46
45
  /** Restrictions for the column. If the column is restricted, the permission is further restricted. E.g. if the column is restricted to user, then the user can only read the column if they have the right permission.
47
46
  * Example: Denying users to update the column, but allowing the moderator to update the column.
48
- */
47
+ */
49
48
  restrict?: {
50
49
  /** Restrictions for the user */
51
- user: Partial<Omit<DbPermissionDefinition, 'delete'>>,
50
+ user: Partial<Omit<DbPermissionDefinition, 'delete'>>;
52
51
  /** Restrictions for the moderator */
53
- moderator?: Partial<Omit<DbPermissionDefinition, 'delete'>>,
52
+ moderator?: Partial<Omit<DbPermissionDefinition, 'delete'>>;
54
53
  /** Restrictions for the maintainer */
55
54
  // maintainer?: Partial<DbPermissionDefinition>,
56
- }
55
+ };
57
56
  }
58
57
 
59
58
  /**
@@ -80,8 +79,8 @@ export interface DbTableDefinition {
80
79
  description: string;
81
80
  /** Permissions for the table */
82
81
  permissions: {
83
- user: DbPermissionDefinition,
84
- moderator?: DbPermissionDefinition,
82
+ user: DbPermissionDefinition;
83
+ moderator?: DbPermissionDefinition;
85
84
  // maintainer?: DbPermissionDefinition,
86
85
  };
87
86
  /** Column definitions for the table */
@@ -98,7 +97,7 @@ export interface DbTableDefinition {
98
97
  *
99
98
  * Defines the permissions for a database table.
100
99
  */
101
- export type DbPermission = "NONE" | "OWN" | "ALL";
100
+ export type DbPermission = 'NONE' | 'OWN' | 'ALL';
102
101
 
103
102
  /**
104
103
  * Permission definition for a database table.
@@ -1,59 +1,75 @@
1
- import { useEffect, useRef } from "react";
1
+ import { useEffect, useRef } from 'react';
2
2
 
3
3
  interface Props {
4
- title: string;
5
- show?: boolean;
6
- className?: string;
7
- closeAble?: boolean;
8
- children: React.ReactNode;
9
- actionbuttons: ActionButton[];
10
- buttonText?: string | React.ReactNode;
11
- onClose?: () => void;
4
+ title: string;
5
+ show?: boolean;
6
+ className?: string;
7
+ closeAble?: boolean;
8
+ children: React.ReactNode;
9
+ actionbuttons: ActionButton[];
10
+ buttonText?: string | React.ReactNode;
11
+ onClose?: () => void;
12
12
  }
13
13
 
14
14
  interface ActionButton {
15
- text: string;
16
- onClick: () => void;
17
- closeModal?: boolean;
15
+ text: string;
16
+ onClick: () => void;
17
+ closeModal?: boolean;
18
18
  }
19
19
 
20
- export function CRUDModal({ actionbuttons, children, title, buttonText, className, closeAble = true, show = false, onClose }: Props) {
21
- const dialogRef = useRef<HTMLDialogElement>(null);
20
+ export function CRUDModal({
21
+ actionbuttons,
22
+ children,
23
+ title,
24
+ buttonText,
25
+ className,
26
+ closeAble = true,
27
+ show = false,
28
+ onClose,
29
+ }: Props) {
30
+ const dialogRef = useRef<HTMLDialogElement>(null);
22
31
 
23
- useEffect(() => {
24
- if (show) {
25
- dialogRef.current?.showModal();
26
- } else {
27
- dialogRef.current?.close();
28
- }
29
- }, [show]);
32
+ useEffect(() => {
33
+ if (show) {
34
+ dialogRef.current?.showModal();
35
+ } else {
36
+ dialogRef.current?.close();
37
+ }
38
+ }, [show]);
30
39
 
31
- const handleClose = () => {
32
- dialogRef.current?.close();
33
- onClose?.();
34
- };
40
+ const handleClose = () => {
41
+ dialogRef.current?.close();
42
+ onClose?.();
43
+ };
35
44
 
36
- return (
37
- <>
38
- {!!buttonText && <button className={className} onClick={() => dialogRef.current?.showModal()}>{buttonText}</button>}
39
- <dialog ref={dialogRef} className="bg-gray-400 rounded-lg font-normal" onClose={handleClose}>
40
- <div className="bg-gray-500 text-xl flex flex-row justify-between p-3 items-start font-bold">
41
- <h2>{title}</h2>
42
- {closeAble && <button onClick={handleClose}>&times;</button>}
43
- </div>
44
- <div className="modal-body p-2">
45
- {children}
46
- </div>
47
- <div className="modal-footer px-2 py-2 flex flex-row gap-2 border-t-2">
48
- {actionbuttons.map(({ onClick, text, closeModal = true }, index) => (
49
- <button key={index} className="bg-blue-500 hover:bg-blue-600 dark:border-gray-900 rounded-md py-2 px-4 dark:text-white font-bold"
50
- onClick={() => {
51
- if (closeModal) handleClose();
52
- onClick();
53
- }}>{text}</button>
54
- ))}
55
- </div>
56
- </dialog>
57
- </>
58
- );
45
+ return (
46
+ <>
47
+ {!!buttonText && (
48
+ <button className={className} onClick={() => dialogRef.current?.showModal()}>
49
+ {buttonText}
50
+ </button>
51
+ )}
52
+ <dialog ref={dialogRef} className="bg-gray-400 rounded-lg font-normal" onClose={handleClose}>
53
+ <div className="bg-gray-500 text-xl flex flex-row justify-between p-3 items-start font-bold">
54
+ <h2>{title}</h2>
55
+ {closeAble && <button onClick={handleClose}>&times;</button>}
56
+ </div>
57
+ <div className="modal-body p-2">{children}</div>
58
+ <div className="modal-footer px-2 py-2 flex flex-row gap-2 border-t-2">
59
+ {actionbuttons.map(({ onClick, text, closeModal = true }, index) => (
60
+ <button
61
+ key={index}
62
+ className="bg-blue-500 hover:bg-blue-600 dark:border-gray-900 rounded-md py-2 px-4 dark:text-white font-bold"
63
+ onClick={() => {
64
+ if (closeModal) handleClose();
65
+ onClick();
66
+ }}
67
+ >
68
+ {text}
69
+ </button>
70
+ ))}
71
+ </div>
72
+ </dialog>
73
+ </>
74
+ );
59
75
  }