mirror of
https://dev.azure.com/tstanciu94/PhantomMind/_git/Bitip
synced 2025-10-13 01:52:19 +03:00
feat: create centralized path utilities for improved path resolution and environment awareness
This commit is contained in:
parent
dca221384c
commit
ee20b85c9e
@ -29,6 +29,9 @@
|
|||||||
"Removed all `.js` extensions from backend imports (handlers, middleware, routes, services)",
|
"Removed all `.js` extensions from backend imports (handlers, middleware, routes, services)",
|
||||||
"Added `tsup.config.ts` with optimized ESM output configuration",
|
"Added `tsup.config.ts` with optimized ESM output configuration",
|
||||||
"Updated build script from `tsc` to `tsup` in package.json",
|
"Updated build script from `tsc` to `tsup` in package.json",
|
||||||
|
"Created centralized path utilities in `src/backend/utils/paths.ts`",
|
||||||
|
"Replaced duplicated `__dirname` logic with `resolveFromRoot()` function",
|
||||||
|
"Path resolution now environment-aware (dev vs production)",
|
||||||
"Maintained development mode with nodemon for hot-reload support"
|
"Maintained development mode with nodemon for hot-reload support"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -3,8 +3,6 @@ import cors from 'cors';
|
|||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import compression from 'compression';
|
import compression from 'compression';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { dirname } from 'path';
|
|
||||||
import { setTimeout } from 'timers';
|
import { setTimeout } from 'timers';
|
||||||
import apiRoutes from './routes/api';
|
import apiRoutes from './routes/api';
|
||||||
import apiKeyAuth from './middleware/auth';
|
import apiKeyAuth from './middleware/auth';
|
||||||
@ -13,9 +11,7 @@ import config from './services/config';
|
|||||||
import logger from './services/logger';
|
import logger from './services/logger';
|
||||||
import { generateRuntimeConfig } from './services/runtimeConfig';
|
import { generateRuntimeConfig } from './services/runtimeConfig';
|
||||||
import { healthCheckHandler } from './handlers/healthHandler';
|
import { healthCheckHandler } from './handlers/healthHandler';
|
||||||
|
import { paths } from './utils/paths';
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = dirname(__filename);
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@ -72,7 +68,7 @@ const basePath = config.basePath.endsWith('/')
|
|||||||
: config.basePath;
|
: config.basePath;
|
||||||
|
|
||||||
// Serve static frontend files
|
// Serve static frontend files
|
||||||
const frontendPath = path.join(__dirname, '../frontend');
|
const frontendPath = paths.frontendDir;
|
||||||
|
|
||||||
// Generate runtime configuration (env.js) at startup
|
// Generate runtime configuration (env.js) at startup
|
||||||
generateRuntimeConfig(frontendPath, basePath);
|
generateRuntimeConfig(frontendPath, basePath);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response } from 'express';
|
||||||
import Joi from 'joi';
|
import Joi from 'joi';
|
||||||
import { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
import { fileURLToPath } from 'url';
|
import paths from '../utils/paths';
|
||||||
import { dirname, join } from 'path';
|
|
||||||
import geoIPService from '../services/geoip';
|
import geoIPService from '../services/geoip';
|
||||||
import logger from '../services/logger';
|
import logger from '../services/logger';
|
||||||
import config from '../services/config';
|
import config from '../services/config';
|
||||||
@ -13,9 +12,6 @@ import {
|
|||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
} from '../types/index';
|
} from '../types/index';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = dirname(__filename);
|
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
// Validation schemas
|
// Validation schemas
|
||||||
@ -276,10 +272,8 @@ router.get('/version', (_req: Request, res: Response): void => {
|
|||||||
// Get release notes
|
// Get release notes
|
||||||
router.get('/release-notes', (_req: Request, res: Response): void => {
|
router.get('/release-notes', (_req: Request, res: Response): void => {
|
||||||
try {
|
try {
|
||||||
const releaseNotesPath = join(__dirname, '../../../ReleaseNotes.json');
|
const releaseNotesContent = readFileSync(paths.releaseNotesFile, 'utf-8');
|
||||||
const releaseNotesContent = readFileSync(releaseNotesPath, 'utf-8');
|
|
||||||
const releaseNotes = JSON.parse(releaseNotesContent);
|
const releaseNotes = JSON.parse(releaseNotesContent);
|
||||||
|
|
||||||
logger.debug('Release notes retrieved successfully');
|
logger.debug('Release notes retrieved successfully');
|
||||||
res.json(releaseNotes);
|
res.json(releaseNotes);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -294,10 +288,8 @@ router.get('/release-notes', (_req: Request, res: Response): void => {
|
|||||||
// Get overview
|
// Get overview
|
||||||
router.get('/overview', (_req: Request, res: Response): void => {
|
router.get('/overview', (_req: Request, res: Response): void => {
|
||||||
try {
|
try {
|
||||||
const overviewPath = join(__dirname, '../../../Overview.json');
|
const overviewContent = readFileSync(paths.overviewFile, 'utf-8');
|
||||||
const overviewContent = readFileSync(overviewPath, 'utf-8');
|
|
||||||
const overview = JSON.parse(overviewContent);
|
const overview = JSON.parse(overviewContent);
|
||||||
|
|
||||||
logger.debug('Overview retrieved successfully');
|
logger.debug('Overview retrieved successfully');
|
||||||
res.json(overview);
|
res.json(overview);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
import { Config, LogLevel, LOG_LEVELS } from '../types/index';
|
import { Config, LogLevel, LOG_LEVELS } from '../types/index';
|
||||||
import path from 'path';
|
|
||||||
import { config as dotenvConfig } from 'dotenv';
|
import { config as dotenvConfig } from 'dotenv';
|
||||||
import { fileURLToPath } from 'url';
|
import { paths } from '../utils/paths';
|
||||||
import { dirname } from 'path';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
dotenvConfig({ path: paths.envFile });
|
||||||
const __dirname = dirname(__filename);
|
|
||||||
|
|
||||||
// Load .env file from root directory
|
|
||||||
dotenvConfig({ path: path.join(__dirname, '../../../.env') });
|
|
||||||
|
|
||||||
// Parse log level from environment variable
|
// Parse log level from environment variable
|
||||||
const parseLogLevel = (level?: string): LogLevel => {
|
const parseLogLevel = (level?: string): LogLevel => {
|
||||||
|
48
src/backend/utils/paths.ts
Normal file
48
src/backend/utils/paths.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
|
const findProjectRoot = (): string => {
|
||||||
|
// In production (Docker), process.cwd() is /app (project root)
|
||||||
|
if (isProduction) {
|
||||||
|
return process.cwd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import.meta.url) {
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const rootPath = path.resolve(__dirname, '../../..');
|
||||||
|
return rootPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
'import.meta.url is required in development to resolve project root'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const projectRootPath = findProjectRoot();
|
||||||
|
console.log('[paths] Project root resolved:', projectRootPath);
|
||||||
|
|
||||||
|
const resolveFilePath = (...relativePath: string[]): string => {
|
||||||
|
return path.join(projectRootPath, ...relativePath);
|
||||||
|
};
|
||||||
|
|
||||||
|
const envPath = resolveFilePath('.env');
|
||||||
|
const releaseNotesPath = resolveFilePath('ReleaseNotes.json');
|
||||||
|
const overviewPath = resolveFilePath('Overview.json');
|
||||||
|
const frontendPrefix = isProduction ? 'dist' : 'src';
|
||||||
|
const frontendPath = resolveFilePath(frontendPrefix, 'frontend');
|
||||||
|
|
||||||
|
const paths = {
|
||||||
|
projectRoot: projectRootPath,
|
||||||
|
envFile: envPath,
|
||||||
|
releaseNotesFile: releaseNotesPath,
|
||||||
|
overviewFile: overviewPath,
|
||||||
|
frontendDir: frontendPath,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('[paths] App paths resolved:', paths);
|
||||||
|
|
||||||
|
export { paths };
|
||||||
|
export default paths;
|
Loading…
x
Reference in New Issue
Block a user