Files
Krow-workspace/scripts/prepare-export.js
bwnyasse 554dc9f9e3 feat: Initialize monorepo structure and comprehensive documentation
This commit establishes the new monorepo architecture for the KROW Workforce platform.

Key changes include:
- Reorganized project into `frontend-web`, `mobile-apps`, `firebase`, `scripts`, and `secrets` directories.
- Updated `Makefile` to support the new monorepo layout and automate Base44 export integration.
- Fixed `scripts/prepare-export.js` for ES module compatibility and global component import resolution.
- Created and updated `CONTRIBUTING.md` for developer onboarding.
- Restructured, renamed, and translated all `docs/` files for clarity and consistency.
- Implemented an interactive internal launchpad with diagram viewing capabilities.
- Configured base Firebase project files (`firebase.json`, security rules).
- Updated `README.md` to reflect the new project structure and documentation overview.
2025-11-12 12:50:55 -05:00

202 lines
6.5 KiB
JavaScript

import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// Replicate __dirname functionality in ES modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.join(__dirname, '..', 'frontend-web');
// --- Fonctions de Patch ---
function applyPatch(filePath, patchInfo) {
const fullPath = path.join(projectRoot, filePath);
if (!fs.existsSync(fullPath)) {
console.warn(`🟡 Fichier non trouvé, patch ignoré : ${filePath}`);
return;
}
let content = fs.readFileSync(fullPath, 'utf8');
if (content.includes(patchInfo.new_string)) {
console.log(`✅ Patch déjà appliqué dans ${filePath} (recherche de '${patchInfo.search_string}').`);
return;
}
if (content.includes(patchInfo.old_string)) {
content = content.replace(patchInfo.old_string, patchInfo.new_string);
fs.writeFileSync(fullPath, content, 'utf8');
console.log(`🟢 Patch appliqué dans ${filePath} (remplacement de '${patchInfo.search_string}').`);
} else {
console.error(`🔴 Impossible d'appliquer le patch dans ${filePath}. Chaîne non trouvée : '${patchInfo.search_string}'.`);
}
}
// --- Définition des Patches ---
const patches = [
{
file: 'src/api/base44Client.js',
search_string: 'createClient',
old_string: `import { createClient } from '@base44/sdk';
// import { getAccessToken } from '@base44/sdk/utils/auth-utils';
// Create a client with authentication required
export const base44 = createClient({
appId: "68fc6cf01386035c266e7a5d",
requiresAuth: true // Ensure authentication is required for all operations
});`,
new_string: `// import { createClient } from '@base44/sdk';
// --- MIGRATION MOCK ---
// This mock completely disables the Base44 SDK to allow for local development.
export const base44 = {
auth: {
me: () => Promise.resolve(null),
logout: () => {},
},
entities: {
ActivityLog: {
filter: () => Promise.resolve([]),
},
},
};
`
},
{
file: 'src/main.jsx',
search_string:
`ReactDOM.createRoot(document.getElementById('root')).render(`,
old_string: `import React from 'react'
import ReactDOM from 'react-dom/client'
import App from '@/App.jsx'
import '@/index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<App />
)`,
new_string: `import React from 'react'
import ReactDOM from 'react-dom/client'
import App from '@/App.jsx'
import '@/index.css'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</React.StrictMode>,
)
`
},
{
file: 'src/pages/Layout.jsx',
search_string: `const { data: user } = useQuery`,
old_string: ` const { data: user } = useQuery({
queryKey: ['current-user-layout'],
queryFn: () => base44.auth.me(),
});`,
new_string: ` // const { data: user } = useQuery({
// queryKey: ['current-user-layout'],
// queryFn: () => base44.auth.me(),
// });
// Mock user data to prevent redirection and allow local development
const user = {
full_name: "Dev User",
email: "dev@example.com",
user_role: "admin", // You can change this to 'procurement', 'operator', 'client', etc. to test different navigation menus
profile_picture: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
};
`
},
{
file: 'src/pages/Layout.jsx',
search_string: `const { data: unreadCount = 0 } = useQuery`,
old_string: ` const { data: unreadCount = 0 } = useQuery({
queryKey: ['unread-notifications', user?.id],
queryFn: async () => {
if (!user?.id) return 0;
const notifications = await base44.entities.ActivityLog.filter({
user_id: user?.id,
is_read: false
});
return notifications.length;
},
enabled: !!user?.id,
initialData: 0,
refetchInterval: 10000,
});`,
new_string: ` // Get unread notification count
// const { data: unreadCount = 0 } = useQuery({
const unreadCount = 0; // Mocked value`
},
{
file: 'src/pages/Layout.jsx',
search_string: 'import { Badge } from \"./components/ui/badge\"',
old_string: 'import { Badge } from \"./components/ui/badge\"',
new_string: 'import { Badge } from \"@/components/ui/badge\"',
},
{
file: 'src/pages/Layout.jsx',
search_string: 'import ChatBubble from \"./components/chat/ChatBubble\"',
old_string: 'import ChatBubble from \"./components/chat/ChatBubble\"',
new_string: 'import ChatBubble from \"@/components/chat/ChatBubble\"',
}
];
// --- Global Import Fix ---
function fixComponentImports(directory) {
const entries = fs.readdirSync(directory, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
fixComponentImports(fullPath);
} else if (entry.isFile() && entry.name.endsWith('.jsx')) {
let content = fs.readFileSync(fullPath, 'utf8');
const originalContent = content;
// Regex to find all imports from "./components/" (with single or double quotes)
const importRegex = /from\s+(['"])\.\/components\//g;
content = content.replace(importRegex, 'from $1@/components/');
// This specifically handles the badge import which might be different
content = content.replace('from "./components/ui/badge"', 'from "@/components/ui/badge"');
content = content.replace('from "./components/chat/ChatBubble"', 'from "@/components/chat/ChatBubble"');
content = content.replace('from "./components/dev/RoleSwitcher"', 'from "@/components/dev/RoleSwitcher"');
content = content.replace('from "./components/notifications/NotificationPanel"', 'from "@/components/notifications/NotificationPanel"');
content = content.replace('from "./components/ui/toaster"', 'from "@/components/ui/toaster"');
if (content !== originalContent) {
console.log(` Glogal import fix appliqué dans ${fullPath}`);
fs.writeFileSync(fullPath, content, 'utf8');
}
}
}
}
// --- Exécution ---
function main() {
console.log('--- Application des patchs pour l\'environnement local ---');
patches.forEach(patchInfo => {
applyPatch(patchInfo.file, patchInfo);
});
console.log('--- Correction globale des imports de composants ---');
fixComponentImports(path.join(projectRoot, 'src'));
console.log('--- Fin de l\'application des patchs ---');
}
main();