@rimori/client 2.4.0 → 2.5.0-next.2

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 (70) hide show
  1. package/dist/cli/scripts/init/dev-registration.js +4 -2
  2. package/dist/cli/scripts/init/main.js +1 -0
  3. package/dist/cli/scripts/release/release.js +0 -0
  4. package/dist/controller/SettingsController.d.ts +1 -1
  5. package/dist/controller/SharedContentController.d.ts +1 -1
  6. package/dist/fromRimori/EventBus.js +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/plugin/CommunicationHandler.d.ts +13 -8
  9. package/dist/plugin/CommunicationHandler.js +44 -59
  10. package/dist/plugin/RimoriClient.d.ts +11 -195
  11. package/dist/plugin/RimoriClient.js +17 -298
  12. package/dist/plugin/StandaloneClient.d.ts +1 -1
  13. package/dist/plugin/StandaloneClient.js +3 -2
  14. package/dist/plugin/module/AIModule.d.ts +49 -0
  15. package/dist/plugin/module/AIModule.js +81 -0
  16. package/dist/plugin/module/DbModule.d.ts +30 -0
  17. package/dist/plugin/module/DbModule.js +51 -0
  18. package/dist/plugin/module/EventModule.d.ts +99 -0
  19. package/dist/plugin/module/EventModule.js +162 -0
  20. package/dist/{controller/ExerciseController.d.ts → plugin/module/ExerciseModule.d.ts} +20 -16
  21. package/dist/{controller/ExerciseController.js → plugin/module/ExerciseModule.js} +27 -20
  22. package/dist/plugin/module/PluginModule.d.ts +76 -0
  23. package/dist/plugin/module/PluginModule.js +88 -0
  24. package/package.json +8 -3
  25. package/.github/workflows/pre-release.yml +0 -126
  26. package/.prettierignore +0 -35
  27. package/eslint.config.js +0 -53
  28. package/example/docs/devdocs.md +0 -241
  29. package/example/docs/overview.md +0 -29
  30. package/example/docs/userdocs.md +0 -126
  31. package/example/rimori.config.ts +0 -91
  32. package/example/worker/vite.config.ts +0 -26
  33. package/example/worker/worker.ts +0 -11
  34. package/prettier.config.js +0 -8
  35. package/src/cli/scripts/init/dev-registration.ts +0 -189
  36. package/src/cli/scripts/init/env-setup.ts +0 -44
  37. package/src/cli/scripts/init/file-operations.ts +0 -58
  38. package/src/cli/scripts/init/html-cleaner.ts +0 -45
  39. package/src/cli/scripts/init/main.ts +0 -175
  40. package/src/cli/scripts/init/package-setup.ts +0 -113
  41. package/src/cli/scripts/init/router-transformer.ts +0 -332
  42. package/src/cli/scripts/init/tailwind-config.ts +0 -66
  43. package/src/cli/scripts/init/vite-config.ts +0 -73
  44. package/src/cli/scripts/release/detect-translation-languages.ts +0 -37
  45. package/src/cli/scripts/release/release-config-upload.ts +0 -119
  46. package/src/cli/scripts/release/release-db-update.ts +0 -97
  47. package/src/cli/scripts/release/release-file-upload.ts +0 -138
  48. package/src/cli/scripts/release/release.ts +0 -85
  49. package/src/cli/types/DatabaseTypes.ts +0 -125
  50. package/src/controller/AIController.ts +0 -295
  51. package/src/controller/AccomplishmentController.ts +0 -188
  52. package/src/controller/AudioController.ts +0 -64
  53. package/src/controller/ExerciseController.ts +0 -117
  54. package/src/controller/ObjectController.ts +0 -120
  55. package/src/controller/SettingsController.ts +0 -186
  56. package/src/controller/SharedContentController.ts +0 -365
  57. package/src/controller/TranslationController.ts +0 -136
  58. package/src/controller/VoiceController.ts +0 -33
  59. package/src/fromRimori/EventBus.ts +0 -382
  60. package/src/fromRimori/PluginTypes.ts +0 -214
  61. package/src/fromRimori/readme.md +0 -2
  62. package/src/index.ts +0 -19
  63. package/src/plugin/CommunicationHandler.ts +0 -310
  64. package/src/plugin/Logger.ts +0 -394
  65. package/src/plugin/RimoriClient.ts +0 -530
  66. package/src/plugin/StandaloneClient.ts +0 -125
  67. package/src/utils/difficultyConverter.ts +0 -15
  68. package/src/utils/endpoint.ts +0 -3
  69. package/src/worker/WorkerSetup.ts +0 -35
  70. package/tsconfig.json +0 -17
@@ -1,113 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { dirname } from 'path';
4
- import { fileURLToPath } from 'url';
5
-
6
- // ES module equivalent of __dirname
7
- const __filename = fileURLToPath(import.meta.url);
8
- const __dirname = dirname(__filename);
9
-
10
- export interface PackageJson {
11
- name?: string;
12
- r_id?: string;
13
- scripts: {
14
- dev?: string;
15
- [key: string]: string | undefined;
16
- };
17
- dependencies?: {
18
- [key: string]: string;
19
- };
20
- [key: string]: any;
21
- }
22
-
23
- export interface PackageSetupParams {
24
- pluginId?: string;
25
- port?: number;
26
- isUpgrade?: boolean;
27
- }
28
-
29
- /**
30
- * Gets the current version of @rimori/client from its package.json.
31
- * @returns The current version string with caret prefix.
32
- * @throws {Error} if rimori-client package.json cannot be read.
33
- */
34
- export function getRimoriClientVersion(): string {
35
- try {
36
- // Get the path to rimori-client package.json relative to this script
37
- // From dist/cli/scripts/init/ we need to go up 4 levels to reach the root
38
- const rimoriClientPackageJsonPath = path.resolve(__dirname, '../../../../package.json');
39
- const rimoriClientPackageJson = JSON.parse(fs.readFileSync(rimoriClientPackageJsonPath, 'utf8'));
40
- return `^${rimoriClientPackageJson.version}`;
41
- } catch (error) {
42
- throw new Error(`Failed to read rimori-client version: ${error}`);
43
- }
44
- }
45
-
46
- /**
47
- * Updates the plugin's package.json with necessary configuration.
48
- * @param param
49
- * @param param.pluginId - The unique plugin identifier (optional for upgrade mode).
50
- * @param param.port - The development port for the plugin (optional).
51
- * @param param.isUpgrade - Whether this is an upgrade operation.
52
- * @throws {Error} if plugin directory doesn't exist or package.json is missing.
53
- */
54
- export function updatePackageJson({ pluginId, port, isUpgrade = false }: PackageSetupParams): void {
55
- // Get the plugin repo name from the current directory
56
- const pluginRepoName = path.basename(process.cwd());
57
- console.log(`Setting up plugin: ${pluginRepoName}`);
58
- if (pluginId) {
59
- console.log(`Plugin ID: ${pluginId}`);
60
- }
61
- if (port) {
62
- console.log(`Port: ${port}`);
63
- }
64
-
65
- // Check if package.json exists in plugin directory
66
- const packageJsonPath = path.resolve('./package.json');
67
- if (!fs.existsSync(packageJsonPath)) {
68
- throw new Error(`package.json not found! Are you in the root directory of the plugin?`);
69
- }
70
-
71
- // Read and parse the existing package.json
72
- let packageJson: PackageJson;
73
- try {
74
- packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
75
- } catch (error) {
76
- throw new Error(`Failed to read or parse package.json: ${error}`);
77
- }
78
-
79
- console.log('Updating package.json...');
80
- console.log('pluginId', pluginId);
81
-
82
- // Get the current rimori-client version
83
- const rimoriClientVersion = getRimoriClientVersion();
84
-
85
- // Update the package.json object
86
- packageJson.name = pluginRepoName;
87
- if (pluginId) {
88
- packageJson.r_id = pluginId;
89
- }
90
- packageJson.scripts = {
91
- ...packageJson.scripts,
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',
100
- };
101
- packageJson.dependencies = {
102
- ...packageJson.dependencies,
103
- '@rimori/client': rimoriClientVersion,
104
- };
105
-
106
- // Write the updated package.json back to file
107
- try {
108
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8');
109
- console.log('✅ Successfully updated package.json');
110
- } catch (error) {
111
- throw new Error(`Failed to update package.json: ${error}`);
112
- }
113
- }
@@ -1,332 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
-
4
- /**
5
- * Interface representing a detected route component
6
- */
7
- interface RouteComponent {
8
- /** Component name as used in JSX */
9
- componentName: string;
10
- /** Original import statement */
11
- importStatement: string;
12
- /** Import path */
13
- importPath: string;
14
- /** Whether it's a default import */
15
- isDefaultImport: boolean;
16
- }
17
-
18
- /**
19
- * Transform App.tsx to use PluginProvider with HashRouter instead of BrowserRouter.
20
- * Also converts route components to lazy loading with Suspense.
21
- * @param pluginId - The plugin ID to use in PluginProvider
22
- */
23
- export function transformAppRouter(pluginId: string): void {
24
- const appTsxPath = path.resolve('./src/App.tsx');
25
-
26
- if (!fs.existsSync(appTsxPath)) {
27
- console.warn('Warning: App.tsx not found, skipping router transformation');
28
- return;
29
- }
30
-
31
- let content = fs.readFileSync(appTsxPath, 'utf8');
32
-
33
- // Check if PluginProvider is already applied
34
- if (content.includes('PluginProvider')) {
35
- console.log('✅ PluginProvider already applied, skipping router transformation');
36
- return;
37
- }
38
-
39
- // Check if BrowserRouter exists
40
- if (!content.includes('BrowserRouter')) {
41
- console.log('✅ BrowserRouter not found, skipping router transformation');
42
- return;
43
- }
44
-
45
- console.log('🔄 Transforming App.tsx to use PluginProvider with HashRouter...');
46
-
47
- // Step 1: Detect and extract route components
48
- const routeComponents = detectRouteComponents(content);
49
-
50
- if (routeComponents.length > 0) {
51
- console.log(`🔄 Found ${routeComponents.length} route components, converting to lazy loading...`);
52
-
53
- // Step 2: Transform imports to lazy loading
54
- content = transformToLazyImports(content, routeComponents);
55
-
56
- // Step 3: Add Suspense wrapper around Routes
57
- content = addSuspenseWrapper(content);
58
- }
59
-
60
- // Step 4: Transform router imports and JSX (existing functionality)
61
- content = transformImports(content);
62
- content = transformJSX(content, pluginId);
63
-
64
- // Write the transformed content back
65
- fs.writeFileSync(appTsxPath, content, 'utf8');
66
- console.log('✅ App.tsx transformed successfully with lazy loading');
67
- }
68
-
69
- /**
70
- * Detects route components in the JSX by parsing Route elements.
71
- * Looks for patterns like: <Route path="/" element={<ComponentName />} />
72
- * @param content - The file content to analyze
73
- * @returns Array of detected route components with their import information
74
- */
75
- function detectRouteComponents(content: string): RouteComponent[] {
76
- const routeComponents: RouteComponent[] = [];
77
-
78
- // Regex to match Route elements with component references
79
- // Matches: <Route ... element={<ComponentName .../>} ... />
80
- const routeRegex = /<Route[^>]*element=\{\s*<(\w+)[^}]*\}[^>]*\/?>/g;
81
-
82
- let match;
83
- const componentNames = new Set<string>();
84
-
85
- // Extract all unique component names from routes
86
- while ((match = routeRegex.exec(content)) !== null) {
87
- const componentName = match[1];
88
- componentNames.add(componentName);
89
- }
90
-
91
- // For each component, find its corresponding import statement
92
- componentNames.forEach((componentName) => {
93
- const importInfo = findImportForComponent(content, componentName);
94
- if (importInfo) {
95
- routeComponents.push({
96
- componentName,
97
- importStatement: importInfo.importStatement,
98
- importPath: importInfo.importPath,
99
- isDefaultImport: importInfo.isDefaultImport,
100
- });
101
- }
102
- });
103
-
104
- return routeComponents;
105
- }
106
-
107
- /**
108
- * Finds the import statement for a given component name.
109
- * Handles both default imports and named imports.
110
- * @param content - The file content to search
111
- * @param componentName - The component name to find import for
112
- * @returns Import information or null if not found
113
- */
114
- function findImportForComponent(
115
- content: string,
116
- componentName: string,
117
- ): {
118
- importStatement: string;
119
- importPath: string;
120
- isDefaultImport: boolean;
121
- } | null {
122
- // Check for default import: import ComponentName from "path"
123
- const defaultImportRegex = new RegExp(`import\\s+${componentName}\\s+from\\s+["']([^"']+)["'];?`, 'g');
124
- const defaultMatch = defaultImportRegex.exec(content);
125
-
126
- if (defaultMatch) {
127
- return {
128
- importStatement: defaultMatch[0],
129
- importPath: defaultMatch[1],
130
- isDefaultImport: true,
131
- };
132
- }
133
-
134
- // Check for named import: import { ComponentName } from "path"
135
- const namedImportRegex = /import\s*\{\s*([^}]*)\s*\}\s*from\s*["']([^"']+)["'];?/g;
136
- let namedMatch;
137
-
138
- while ((namedMatch = namedImportRegex.exec(content)) !== null) {
139
- const imports = namedMatch[1].split(',').map((imp) => imp.trim());
140
- if (imports.includes(componentName)) {
141
- return {
142
- importStatement: namedMatch[0],
143
- importPath: namedMatch[2],
144
- isDefaultImport: false,
145
- };
146
- }
147
- }
148
-
149
- return null;
150
- }
151
-
152
- /**
153
- * Transforms regular component imports to lazy imports.
154
- * Converts: import ComponentName from "./path"
155
- * To: const ComponentName = lazy(() => import("./path"))
156
- * @param content - The file content to transform
157
- * @param routeComponents - Array of route components to transform
158
- * @returns Transformed content with lazy imports
159
- */
160
- function transformToLazyImports(content: string, routeComponents: RouteComponent[]): string {
161
- let transformedContent = content;
162
-
163
- // Add lazy import if not already present
164
- if (!content.includes('lazy')) {
165
- transformedContent = addLazyImport(transformedContent);
166
- }
167
-
168
- // Transform each route component import
169
- routeComponents.forEach((component, index) => {
170
- const { componentName, importStatement, importPath, isDefaultImport } = component;
171
-
172
- // Create lazy import statement
173
- const lazyImport = isDefaultImport
174
- ? `const ${componentName} = lazy(() => import("${importPath}"));`
175
- : `const ${componentName} = lazy(() => import("${importPath}").then(module => ({ default: module.${componentName} })));`;
176
-
177
- // Replace the original import with lazy import
178
- transformedContent = transformedContent.replace(importStatement, (index === 0 ? '\n' : '') + lazyImport);
179
- });
180
-
181
- return transformedContent;
182
- }
183
-
184
- /**
185
- * Adds lazy import from React if not already present.
186
- * @param content - The file content to modify
187
- * @returns Content with lazy import added
188
- */
189
- function addLazyImport(content: string): string {
190
- // Check if React import exists and update it
191
- const reactImportRegex = /import\s+(?:\*\s+as\s+)?React(?:\s*,\s*\{\s*([^}]*)\s*\})?\s+from\s+["']react["'];?/;
192
- const reactImportMatch = content.match(reactImportRegex);
193
-
194
- if (reactImportMatch) {
195
- // React import exists, add lazy to it
196
- const existingImports = reactImportMatch[1] || '';
197
- const importList = existingImports
198
- .split(',')
199
- .map((imp) => imp.trim())
200
- .filter(Boolean);
201
-
202
- if (!importList.includes('lazy')) {
203
- importList.push('lazy');
204
- }
205
- if (!importList.includes('Suspense')) {
206
- importList.push('Suspense');
207
- }
208
-
209
- const newImport =
210
- importList.length > 0 ? `import React, { ${importList.join(', ')} } from "react";` : `import React from "react";`;
211
-
212
- return content.replace(reactImportMatch[0], newImport);
213
- } else {
214
- // No React import found, add it
215
- const firstImportMatch = content.match(/^import.*$/m);
216
- if (firstImportMatch) {
217
- return content.replace(
218
- firstImportMatch[0],
219
- `import React, { lazy, Suspense } from "react";\n${firstImportMatch[0]}`,
220
- );
221
- } else {
222
- // No imports found, add at the beginning
223
- return `import React, { lazy, Suspense } from "react";\n${content}`;
224
- }
225
- }
226
- }
227
-
228
- /**
229
- * Wraps the Routes component with Suspense for lazy loading fallback.
230
- * Converts: <Routes>...</Routes>
231
- * To: <Suspense fallback={<div>Loading...</div>}><Routes>...</Routes></Suspense>
232
- * @param content - The file content to modify
233
- * @returns Content with Suspense wrapper added
234
- */
235
- function addSuspenseWrapper(content: string): string {
236
- // Check if Suspense is already wrapping Routes
237
- if (content.includes('<Suspense') && content.match(/<Suspense[^>]*>[\s\S]*<Routes/)) {
238
- console.log('✅ Suspense wrapper already present');
239
- return content;
240
- }
241
-
242
- // Find Routes component and wrap with Suspense
243
- // Handle both self-closing and regular Routes tags
244
- const routesRegex = /(<Routes(?:[^>]*)>)([\s\S]*?)(<\/Routes>)/;
245
- const selfClosingRoutesRegex = /(<Routes[^>]*\/>)/;
246
-
247
- const routesMatch = content.match(routesRegex);
248
- const selfClosingMatch = content.match(selfClosingRoutesRegex);
249
-
250
- if (routesMatch) {
251
- // Regular Routes with children
252
- const [fullMatch, openTag, children, closeTag] = routesMatch;
253
- const suspenseWrapper = `<Suspense fallback={<div className="flex items-center justify-center min-h-screen"><div className="text-lg">Loading...</div></div>}>\n ${openTag}${children}${closeTag}\n </Suspense>`;
254
- return content.replace(fullMatch, suspenseWrapper);
255
- } else if (selfClosingMatch) {
256
- // Self-closing Routes
257
- const suspenseWrapper = `<Suspense fallback={<div className="flex items-center justify-center min-h-screen"><div className="text-lg">Loading...</div></div>}>\n ${selfClosingMatch[1]}\n </Suspense>`;
258
- return content.replace(selfClosingMatch[1], suspenseWrapper);
259
- }
260
-
261
- console.log('✅ Routes component not found, skipping Suspense wrapper');
262
- return content;
263
- }
264
-
265
- /**
266
- * Transform the import statements to include PluginProvider and change BrowserRouter to HashRouter.
267
- * This is the original functionality for router transformation.
268
- * @param content - The file content to transform
269
- * @returns Transformed content with updated imports
270
- */
271
- function transformImports(content: string): string {
272
- // Add PluginProvider import
273
- if (!content.includes('import') || !content.includes('@rimori/client')) {
274
- // Add new import line for PluginProvider
275
- const importMatch = content.match(/^(import.*from\s+["']react["'];?\s*\n)/m);
276
- if (importMatch) {
277
- content = content.replace(importMatch[0], `${importMatch[0]}import { PluginProvider } from "@rimori/client";\n`);
278
- } else {
279
- // If no React import found, add at the beginning
280
- content = `import { PluginProvider } from "@rimori/client";\n${content}`;
281
- }
282
- } else {
283
- // Update existing @rimori/client import to include PluginProvider
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');
291
- }
292
- return `import { ${importList.join(', ')} } from "@rimori/client";`;
293
- });
294
- }
295
-
296
- // Transform react-router-dom import: replace BrowserRouter with HashRouter
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
- });
305
-
306
- return content;
307
- }
308
-
309
- /**
310
- * Transform the JSX to wrap with PluginProvider and change BrowserRouter to HashRouter.
311
- * This is the original functionality for router transformation.
312
- * @param content - The file content to transform
313
- * @param pluginId - The plugin ID to use in PluginProvider
314
- * @returns Transformed content with updated JSX
315
- */
316
- function transformJSX(content: string, pluginId: string): string {
317
- // Replace opening BrowserRouter tag
318
- content = content.replace(
319
- /<BrowserRouter(\s[^>]*)?>/,
320
- `<PluginProvider pluginId="${pluginId}">
321
- <HashRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>`,
322
- );
323
-
324
- // Replace closing BrowserRouter tag
325
- content = content.replace(
326
- /<\/BrowserRouter>/,
327
- `</HashRouter>
328
- </PluginProvider>`,
329
- );
330
-
331
- return content;
332
- }
@@ -1,66 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
-
4
- /**
5
- * Updates the tailwind.config.ts file to set darkMode to "class" and add the Rimori client package to content.
6
- */
7
- export function updateTailwindConfig(): void {
8
- console.log('Updating Tailwind CSS configuration...');
9
-
10
- const tailwindConfigPath = path.resolve('./tailwind.config.ts');
11
-
12
- if (!fs.existsSync(tailwindConfigPath)) {
13
- console.log('Warning: tailwind.config.ts not found, skipping Tailwind CSS update');
14
- return;
15
- }
16
-
17
- try {
18
- const configContent = fs.readFileSync(tailwindConfigPath, 'utf8');
19
-
20
- let updatedContent = configContent;
21
-
22
- // Set darkMode to "class" if it exists, otherwise add it
23
- if (updatedContent.includes('darkMode:')) {
24
- updatedContent = updatedContent.replace(/darkMode:\s*\[?"[^"]*"?\]?,?/g, 'darkMode: ["class"],');
25
- } else {
26
- // Add darkMode after the opening brace
27
- updatedContent = updatedContent.replace(/export default \{/, 'export default {\n darkMode: ["class"],');
28
- }
29
-
30
- // Add Rimori client package to content array if not already present
31
- if (!updatedContent.includes('node_modules/@rimori/client')) {
32
- // Find the content array and add the Rimori client path
33
- if (updatedContent.includes('content:')) {
34
- // More precise regex to handle the content array properly
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, ',');
38
-
39
- // Remove trailing comma and whitespace
40
- cleanContent = cleanContent.replace(/,\s*$/, '');
41
-
42
- // Add the new path with proper formatting
43
- const newPath = '"node_modules/@rimori/client/dist/components/**/*.{js,jsx}"';
44
-
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}`;
50
- }
51
- });
52
- } else {
53
- // Add content array if it doesn't exist
54
- updatedContent = updatedContent.replace(
55
- /darkMode: \["class"\],/,
56
- 'darkMode: ["class"],\n content: [\n "./src/**/*.{js,jsx,ts,tsx}",\n "node_modules/@rimori/client/dist/components/**/*.{js,jsx}"\n ],',
57
- );
58
- }
59
- }
60
-
61
- fs.writeFileSync(tailwindConfigPath, updatedContent, 'utf8');
62
- console.log('✅ Tailwind CSS configuration updated');
63
- } catch (error) {
64
- console.warn(`Warning: Could not update tailwind.config.ts: ${error instanceof Error ? error.message : error}`);
65
- }
66
- }
@@ -1,73 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
-
4
- /**
5
- * Updates the vite.config.ts file to set the base property.
6
- * @param param
7
- * @param param.basePath - The base path to set in vite config (defaults to './')
8
- * @param param.configPath - Path to the vite.config.ts file (defaults to './vite.config.ts')
9
- * @throws {Error} if vite.config.ts file is not found or cannot be modified.
10
- */
11
- export function updateViteConfigBase({
12
- basePath = './',
13
- configPath = './vite.config.ts',
14
- }: {
15
- basePath?: string;
16
- configPath?: string;
17
- } = {}): void {
18
- const viteConfigPath = path.resolve(configPath);
19
-
20
- if (!fs.existsSync(viteConfigPath)) {
21
- throw new Error(`vite.config.ts not found at ${viteConfigPath}`);
22
- }
23
-
24
- let configContent = fs.readFileSync(viteConfigPath, 'utf8');
25
-
26
- // Check if base property already exists
27
- const baseRegex = /base:\s*['"][^'"]*['"],?\s*/;
28
- const hasBase = baseRegex.test(configContent);
29
-
30
- if (hasBase) {
31
- // Update existing base property
32
- configContent = configContent.replace(baseRegex, `base: '${basePath}',`);
33
- console.log(`Updated existing base property in vite.config.ts to '${basePath}'`);
34
- } else {
35
- // Add base property before server config
36
- const serverRegex = /(\s*)(server:\s*\{)/;
37
- const serverMatch = configContent.match(serverRegex);
38
-
39
- if (serverMatch) {
40
- const indentation = serverMatch[1] || ' '; // Use existing indentation or default to 2 spaces
41
- const replacement = `${indentation}base: '${basePath}',${indentation}${serverMatch[2]}`;
42
- configContent = configContent.replace(serverRegex, replacement);
43
- console.log(`Added base property to vite.config.ts with value '${basePath}'`);
44
- } else {
45
- throw new Error('Could not find server config in vite.config.ts to add base property before it');
46
- }
47
- }
48
-
49
- fs.writeFileSync(viteConfigPath, configContent, 'utf8');
50
- }
51
-
52
- /**
53
- * Reads the current base value from vite.config.ts.
54
- * @param param
55
- * @param param.configPath - Path to the vite.config.ts file (defaults to './vite.config.ts')
56
- * @returns The current base value or null if not found.
57
- */
58
- export function getCurrentViteBase({
59
- configPath = './vite.config.ts',
60
- }: {
61
- configPath?: string;
62
- } = {}): string | null {
63
- const viteConfigPath = path.resolve(configPath);
64
-
65
- if (!fs.existsSync(viteConfigPath)) {
66
- return null;
67
- }
68
-
69
- const configContent = fs.readFileSync(viteConfigPath, 'utf8');
70
- const baseMatch = configContent.match(/base:\s*['"]([^'"]*)['"]/);
71
-
72
- return baseMatch ? baseMatch[1] : null;
73
- }
@@ -1,37 +0,0 @@
1
- import fs from 'fs';
2
-
3
- /**
4
- * Detect available translation languages from public/locales directory
5
- * @returns Promise<string[]> Array of language codes found in the locales directory
6
- */
7
- export async function detectTranslationLanguages(): Promise<string[]> {
8
- const localesPath = './public/locales';
9
-
10
- try {
11
- await fs.promises.access(localesPath);
12
- } catch (e) {
13
- console.log('⚠️ No locales directory found, no translations available');
14
- return [];
15
- }
16
-
17
- try {
18
- const files = await fs.promises.readdir(localesPath);
19
-
20
- // Filter out local- files and only include .json files
21
- const translationFiles = files.filter((file) => file.endsWith('.json') && !file.startsWith('local-'));
22
-
23
- if (translationFiles.length === 0) {
24
- console.log('⚠️ No translation files found (excluding local- files)');
25
- return [];
26
- }
27
-
28
- // Extract language codes from filenames (e.g., en.json -> en)
29
- const languages = translationFiles.map((file) => file.replace('.json', ''));
30
-
31
- console.log(`🌐 Found ${languages.length} translation languages: ${languages.join(', ')}`);
32
- return languages;
33
- } catch (error: any) {
34
- console.error(`❌ Error reading locales directory:`, error.message);
35
- return [];
36
- }
37
- }