Fix: Add TypeScript backend compilation for deployment
This commit is contained in:
parent
3592df6a5d
commit
7956762b7e
4 changed files with 194 additions and 5 deletions
156
backend/api/pages.js
Normal file
156
backend/api/pages.js
Normal 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;
|
||||||
|
};
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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
18
tsconfig.backend.json
Normal 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"]
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in a new issue