Fix: Add TypeScript backend compilation for deployment

This commit is contained in:
mmabdalla 2025-12-29 01:31:04 +02:00
parent 3592df6a5d
commit 7956762b7e
4 changed files with 194 additions and 5 deletions

156
backend/api/pages.js Normal file
View file

@ -0,0 +1,156 @@
import express from 'express';
// BOSA SDK instance (initialized in server.js)
let bosa = null;
export const initPagesAPI = (bosaInstance) => {
bosa = bosaInstance;
};
export const createPagesRouter = () => {
const router = express.Router();
router.post('/', async (req, res) => {
try {
const { app_name, route_path, page_config } = req.body;
if (!app_name || !route_path || !page_config) {
bosa?.log?.warn('CreatePage: Missing required fields');
return res.status(400).json({ error: 'Missing required fields' });
}
if (!bosa) {
return res.status(500).json({ error: 'BOSA SDK not initialized' });
}
// Check if page already exists
const existing = await bosa.db
.query('wb_pages')
.where('app_name', '=', app_name)
.where('route_path', '=', route_path)
.first();
if (existing) {
bosa.log?.warn(`CreatePage: Page already exists | App: ${app_name} | Route: ${route_path}`);
return res.status(409).json({ error: 'Page already exists' });
}
// Insert using BOSA SDK
const id = await bosa.db.query('wb_pages').insert({
app_name,
route_path,
page_config: JSON.stringify(page_config),
version: 1,
});
bosa.log?.info(`CreatePage: Page created | ID: ${id} | App: ${app_name}`);
res.status(201).json({
id,
app_name,
route_path,
page_config,
version: 1,
});
}
catch (error) {
bosa?.log?.error(`CreatePage: Failed | Error: ${error.message} | App: ${req.body.app_name}`);
res.status(500).json({ error: error.message });
}
});
router.get('/:id', async (req, res) => {
try {
if (!bosa) {
return res.status(500).json({ error: 'BOSA SDK not initialized' });
}
const page = await bosa.db
.query('wb_pages')
.where('id', '=', Number(req.params.id))
.first();
if (!page) {
bosa.log?.warn(`GetPage: Page not found | ID: ${req.params.id}`);
return res.status(404).json({ error: 'Page not found' });
}
const result = page;
res.json({
...result,
page_config: JSON.parse(result.page_config),
});
}
catch (error) {
bosa?.log?.error(`GetPage: Failed | ID: ${req.params.id} | Error: ${error.message}`);
res.status(500).json({ error: error.message });
}
});
router.put('/:id', async (req, res) => {
try {
if (!bosa) {
return res.status(500).json({ error: 'BOSA SDK not initialized' });
}
const { page_config } = req.body;
if (!page_config) {
bosa.log?.warn(`UpdatePage: Missing page_config | ID: ${req.params.id}`);
return res.status(400).json({ error: 'Missing page_config' });
}
const existing = await bosa.db
.query('wb_pages')
.where('id', '=', Number(req.params.id))
.first();
if (!existing) {
bosa.log?.warn(`UpdatePage: Page not found | ID: ${req.params.id}`);
return res.status(404).json({ error: 'Page not found' });
}
const newVersion = (existing.version || 1) + 1;
await bosa.db
.query('wb_pages')
.where('id', '=', Number(req.params.id))
.update({
page_config: JSON.stringify(page_config),
version: newVersion,
});
bosa.log?.info(`UpdatePage: Page updated | ID: ${req.params.id} | Version: ${newVersion}`);
res.json({
id: Number(req.params.id),
page_config,
version: newVersion,
});
}
catch (error) {
bosa?.log?.error(`UpdatePage: Failed | ID: ${req.params.id} | Error: ${error.message}`);
res.status(500).json({ error: error.message });
}
});
router.delete('/:id', async (req, res) => {
try {
if (!bosa) {
return res.status(500).json({ error: 'BOSA SDK not initialized' });
}
const deleted = await bosa.db
.query('wb_pages')
.where('id', '=', Number(req.params.id))
.delete();
if (deleted === 0) {
bosa.log?.warn(`DeletePage: Page not found | ID: ${req.params.id}`);
return res.status(404).json({ error: 'Page not found' });
}
bosa.log?.info(`DeletePage: Page deleted | ID: ${req.params.id}`);
res.status(204).send();
}
catch (error) {
bosa?.log?.error(`DeletePage: Failed | ID: ${req.params.id} | Error: ${error.message}`);
res.status(500).json({ error: error.message });
}
});
router.get('/', async (req, res) => {
try {
if (!bosa) {
return res.status(500).json({ error: 'BOSA SDK not initialized' });
}
const appName = req.query.app_name;
let query = bosa.db.query('wb_pages');
if (appName) {
query = query.where('app_name', '=', appName);
}
const pages = await query.get();
const results = pages.map((page) => ({
...page,
page_config: JSON.parse(page.page_config),
}));
res.json(results);
}
catch (error) {
bosa?.log?.error(`ListPages: Failed | App: ${req.query.app_name} | Error: ${error.message}`);
res.status(500).json({ error: error.message });
}
});
return router;
};

View file

@ -9,7 +9,8 @@
"dev:frontend": "vite", "dev:frontend": "vite",
"dev:all": "concurrently \"npm run dev\" \"npm run dev:frontend\"", "dev:all": "concurrently \"npm run dev\" \"npm run dev:frontend\"",
"start": "node server.js", "start": "node server.js",
"build": "tsc && vite build", "build": "npm run build:backend && npm run build:frontend",
"build:backend": "tsc -p tsconfig.backend.json",
"build:frontend": "vite build", "build:frontend": "vite build",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx", "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix", "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",

View file

@ -48,9 +48,19 @@ echo [INFO] Source: %SOURCE_DIR%
echo [INFO] Target: %TARGET_DIR% echo [INFO] Target: %TARGET_DIR%
echo. echo.
REM Build the frontend first REM Build backend and frontend
echo [INFO] Building frontend... echo [INFO] Building backend (TypeScript)...
cd /d "%SOURCE_DIR%" cd /d "%SOURCE_DIR%"
call npm run build:backend
if errorlevel 1 (
echo [ERROR] Backend build failed!
pause
exit /b 1
)
echo [OK] Backend build completed
echo.
echo [INFO] Building frontend...
call npm run build:frontend call npm run build:frontend
if errorlevel 1 ( if errorlevel 1 (
echo [ERROR] Frontend build failed! echo [ERROR] Frontend build failed!
@ -82,10 +92,14 @@ if exist "%SOURCE_DIR%\package.json" (
echo [OK] Copied package.json echo [OK] Copied package.json
) )
REM Copy backend directory REM Copy backend directory (compiled JS files only, exclude .ts files)
if exist "%SOURCE_DIR%\backend" ( if exist "%SOURCE_DIR%\backend" (
xcopy /E /I /Y "%SOURCE_DIR%\backend" "%TARGET_DIR%\backend" >nul xcopy /E /I /Y "%SOURCE_DIR%\backend" "%TARGET_DIR%\backend" >nul
echo [OK] Copied backend directory REM Remove TypeScript source files from target
for /r "%TARGET_DIR%\backend" %%f in (*.ts) do (
if not "%%~nxf"=="*.test.ts" del "%%f"
)
echo [OK] Copied backend directory (JS files)
) )
REM Copy migrations directory REM Copy migrations directory

18
tsconfig.backend.json Normal file
View file

@ -0,0 +1,18 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"outDir": "./backend",
"rootDir": "./backend",
"module": "ESNext",
"moduleResolution": "node",
"allowImportingTsExtensions": false,
"jsx": "preserve",
"lib": ["ES2020"],
"noUnusedLocals": false,
"noUnusedParameters": false
},
"include": ["backend/**/*"],
"exclude": ["node_modules", "dist", "backend/**/*.test.ts"]
}