@manojkmfsi/monodog 1.1.7 → 1.1.8

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 (53) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/package.json +1 -1
  4. package/src/config/swagger-config.ts +0 -344
  5. package/src/config-loader.ts +0 -97
  6. package/src/constants/index.ts +0 -13
  7. package/src/constants/middleware.ts +0 -83
  8. package/src/constants/port.ts +0 -20
  9. package/src/constants/security.ts +0 -78
  10. package/src/controllers/commit-controller.ts +0 -31
  11. package/src/controllers/config-controller.ts +0 -42
  12. package/src/controllers/health-controller.ts +0 -24
  13. package/src/controllers/package-controller.ts +0 -67
  14. package/src/get-db-url.ts +0 -9
  15. package/src/index.ts +0 -9
  16. package/src/middleware/dashboard-startup.ts +0 -161
  17. package/src/middleware/error-handler.ts +0 -50
  18. package/src/middleware/index.ts +0 -20
  19. package/src/middleware/logger.ts +0 -65
  20. package/src/middleware/security.ts +0 -90
  21. package/src/middleware/server-startup.ts +0 -153
  22. package/src/middleware/swagger-middleware.ts +0 -58
  23. package/src/repositories/commit-repository.ts +0 -108
  24. package/src/repositories/dependency-repository.ts +0 -110
  25. package/src/repositories/index.ts +0 -10
  26. package/src/repositories/package-health-repository.ts +0 -75
  27. package/src/repositories/package-repository.ts +0 -142
  28. package/src/repositories/prisma-client.ts +0 -25
  29. package/src/routes/commit-routes.ts +0 -10
  30. package/src/routes/config-routes.ts +0 -14
  31. package/src/routes/health-routes.ts +0 -14
  32. package/src/routes/package-routes.ts +0 -22
  33. package/src/serve.ts +0 -41
  34. package/src/services/commit-service.ts +0 -44
  35. package/src/services/config-service.ts +0 -391
  36. package/src/services/git-service.ts +0 -140
  37. package/src/services/health-service.ts +0 -162
  38. package/src/services/package-service.ts +0 -228
  39. package/src/setup.ts +0 -78
  40. package/src/types/ci.ts +0 -122
  41. package/src/types/config.ts +0 -22
  42. package/src/types/database.ts +0 -67
  43. package/src/types/git.ts +0 -33
  44. package/src/types/health.ts +0 -11
  45. package/src/types/index.ts +0 -23
  46. package/src/types/package.ts +0 -39
  47. package/src/types/scanner.ts +0 -31
  48. package/src/types/swagger-jsdoc.d.ts +0 -15
  49. package/src/utils/ci-status.ts +0 -535
  50. package/src/utils/db-utils.ts +0 -92
  51. package/src/utils/health-utils.ts +0 -67
  52. package/src/utils/monorepo-scanner.ts +0 -576
  53. package/src/utils/utilities.ts +0 -427
@@ -1,42 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import { AppLogger } from '../middleware/logger';
3
- import { getConfigurationFilesService, updateConfigFileService, updatePackageConfigurationService } from '../services/config-service';
4
-
5
- export const getConfigurationFiles = async (_req: Request, res: Response) => {
6
- try {
7
- const rootDir = _req.app.locals.rootPath;
8
- AppLogger.debug('Monorepo root directory: ' + rootDir);
9
-
10
- const configFiles = await getConfigurationFilesService(rootDir);
11
- res.json(configFiles);
12
- } catch (error) {
13
- AppLogger.error('Error fetching configuration files', error as Error);
14
- res.status(500).json({
15
- success: false,
16
- error: 'Failed to fetch configuration files',
17
- });
18
- }
19
- }
20
-
21
- export const updateConfigFile = async (_req: Request, res: Response) => {
22
- try {
23
- const { id } = _req.params;
24
- const { content } = _req.body;
25
-
26
- if (!content) {
27
- return res.status(400).json({
28
- success: false,
29
- error: 'Content is required',
30
- });
31
- }
32
- const rootDir = _req.app.locals.rootPath;
33
- const result = await updateConfigFileService(id, rootDir, content);
34
- res.json(result);
35
- } catch (error) {
36
- AppLogger.error('Error saving configuration file', error as Error);
37
- res.status(500).json({
38
- success: false,
39
- error: 'Failed to save configuration file',
40
- });
41
- }
42
- }
@@ -1,24 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import { AppLogger } from '../middleware/logger';
3
- import { getHealthSummaryService, healthRefreshService } from '../services/health-service';
4
-
5
- export const getPackagesHealth = async (_req: Request, res: Response) => {
6
- try {
7
- const health = await getHealthSummaryService();
8
- res.json(health);
9
- } catch (error) {
10
- AppLogger.error('Error fetching health data from database:', error as Error);
11
- res
12
- .status(500)
13
- .json({ error: 'Failed to fetch health data from database' });
14
- }
15
- }
16
-
17
- export const refreshHealth = async (_req: Request, res: Response) => {
18
- try {
19
- const health = await healthRefreshService(_req.app.locals.rootPath);
20
- res.json(health);
21
- } catch (error) {
22
- res.status(500).json({ error: 'Failed to fetch health metrics' });
23
- }
24
- }
@@ -1,67 +0,0 @@
1
- import { Request, Response } from 'express';
2
- import { AppLogger } from '../middleware/logger';
3
- import { updatePackageConfigurationService } from '../services/config-service';
4
- import { getPackageDetailService, getPackagesService, refreshPackagesService } from '../services/package-service';
5
-
6
- export const getPackages = async (_req: Request, res: Response) => {
7
- try {
8
- const transformedPackages = await getPackagesService(_req.app.locals.rootPath);
9
- res.json(transformedPackages);
10
- } catch (error) {
11
- res.status(500).json({ error: 'Failed to fetch packages, ' + error });
12
- }
13
- }
14
-
15
- export const refreshPackages = async (_req: Request, res: Response) => {
16
- AppLogger.info('Refreshing packages from source: ' + _req.app.locals.rootPath);
17
-
18
- try {
19
- const packages = await refreshPackagesService(_req.app.locals.rootPath);
20
- res.json(packages);
21
- } catch (error) {
22
- res.status(500).json({ error: 'Failed to refresh packages' });
23
- }
24
- }
25
-
26
- export const getPackageDetail = async (_req: Request, res: Response) => {
27
- const { name } = _req.params;
28
- try {
29
- const packageDetail = await getPackageDetailService(name)
30
- res.json(packageDetail);
31
- } catch (error) {
32
- res.status(500).json({ error: 'Failed to fetch package details' });
33
- }
34
- }
35
-
36
- export const updatePackageConfig = async (req: Request, res: Response) => {
37
- try {
38
- const { packageName, config, packagePath } = req.body;
39
-
40
- if (!packageName || !config || !packagePath) {
41
- return res.status(400).json({
42
- success: false,
43
- error: 'Package name, configuration, and package path are required',
44
- });
45
- }
46
-
47
- AppLogger.info('Updating package configuration for: ' + packageName);
48
- AppLogger.debug('Package path: ' + packagePath);
49
-
50
- const updatedPackage = await updatePackageConfigurationService(packagePath, packageName, config);
51
-
52
- return res.json({
53
- success: true,
54
- message: 'Package configuration updated successfully',
55
- package: updatedPackage,
56
- preservedFields: true,
57
- });
58
- } catch (error) {
59
- return res.status(500).json({
60
- success: false,
61
- error: 'Failed to update package configuration',
62
- message:
63
- error instanceof Error ? error.message : 'Unknown error occurred',
64
- });
65
- }
66
- }
67
-
package/src/get-db-url.ts DELETED
@@ -1,9 +0,0 @@
1
- import { appConfig } from './config-loader';
2
-
3
- function generateUrl() {
4
- const DATABASE_URL = `${appConfig.database.path}`;
5
- process.env.DATABASE_URL = DATABASE_URL;
6
- process.stdout.write(DATABASE_URL);
7
- }
8
-
9
- generateUrl();
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * Monodog Application Entry Point
3
- *
4
- * This file exports the main server and dashboard startup functions
5
- * All middleware, security, and error handling logic has been moved to separate files
6
- */
7
-
8
- export { startServer } from './middleware/server-startup';
9
- export { serveDashboard } from './middleware/dashboard-startup';
@@ -1,161 +0,0 @@
1
- /**
2
- * Dashboard server startup logic
3
- */
4
-
5
- import express from 'express';
6
- import path from 'path';
7
- import type { Express } from 'express';
8
- import { httpLogger, AppLogger } from './logger';
9
-
10
- import { appConfig } from '../config-loader';
11
- import {
12
- errorHandler,
13
- } from './error-handler';
14
- import {
15
- createHelmetMiddleware,
16
- createDashboardCorsMiddleware,
17
- createTimeoutMiddleware,
18
- buildApiUrl,
19
- } from './security';
20
- import {
21
- PORT_MIN,
22
- PORT_MAX,
23
- PORT_VALIDATION_ERROR_MESSAGE,
24
- CACHE_CONTROL_NO_CACHE,
25
- EXPIRES_HEADER,
26
- PRAGMA_HEADER,
27
- STATIC_FILE_PATTERN,
28
- CONTENT_TYPE_JAVASCRIPT,
29
- ERROR_SERVING_INDEX_HTML,
30
- MESSAGE_GRACEFUL_SHUTDOWN,
31
- MESSAGE_DASHBOARD_GRACEFUL_SHUTDOWN,
32
- MESSAGE_DASHBOARD_CLOSED,
33
- SUCCESS_DASHBOARD_START,
34
- ERROR_PORT_IN_USE,
35
- ERROR_PERMISSION_DENIED,
36
- } from '../constants';
37
-
38
- /**
39
- * Validate port number
40
- */
41
- function validatePort(port: string | number): number {
42
- const portNum = typeof port === 'string' ? parseInt(port, 10) : port;
43
-
44
- if (isNaN(portNum) || portNum < PORT_MIN || portNum > PORT_MAX) {
45
- throw new Error(PORT_VALIDATION_ERROR_MESSAGE(PORT_MIN, PORT_MAX));
46
- }
47
-
48
- return portNum;
49
- }
50
-
51
- /**
52
- * Create Express app for dashboard with middleware
53
- */
54
- function createDashboardApp(): Express {
55
- const app = express();
56
-
57
- // Timeout middleware
58
- app.use(createTimeoutMiddleware());
59
-
60
- // Security setup
61
- const serverHost = appConfig.server.host === '0.0.0.0'
62
- ? 'localhost'
63
- : appConfig.server.host;
64
- const apiUrl = buildApiUrl(serverHost, appConfig.server.port);
65
-
66
- app.use(createHelmetMiddleware(apiUrl));
67
- app.use(createDashboardCorsMiddleware());
68
-
69
- // Environment config endpoint
70
- app.get('/env-config.js', (_req, res) => {
71
- res.setHeader('Content-Type', CONTENT_TYPE_JAVASCRIPT);
72
- res.setHeader('Cache-Control', CACHE_CONTROL_NO_CACHE);
73
-
74
- res.send(
75
- `window.ENV = { API_URL: "${apiUrl}" };`
76
- );
77
- });
78
-
79
- // Request logging
80
- app.use(httpLogger);
81
-
82
- // SPA routing: serve index.html for non-static routes
83
- app.use((_req, _res, next) => {
84
- if (STATIC_FILE_PATTERN.test(_req.path)) {
85
- next();
86
- } else {
87
- _res.header(
88
- 'Cache-Control',
89
- CACHE_CONTROL_NO_CACHE
90
- );
91
- _res.header('Expires', EXPIRES_HEADER);
92
- _res.header('Pragma', PRAGMA_HEADER);
93
- _res.sendFile('index.html', {
94
- root: path.resolve(__dirname, '..', '..', 'monodog-dashboard', 'dist'),
95
- }, (err: Error | null) => {
96
- if (err) {
97
- AppLogger.error(ERROR_SERVING_INDEX_HTML, err);
98
- _res.status(500).json({ error: 'Internal server error' });
99
- }
100
- });
101
- }
102
- });
103
-
104
- // Static files
105
- const staticPath = path.join(__dirname, '..', '..', 'monodog-dashboard', 'dist');
106
- AppLogger.debug('Serving static files from:', { path: staticPath });
107
- app.use(express.static(staticPath, {
108
- maxAge: '1d',
109
- etag: false,
110
- dotfiles: 'deny',
111
- }));
112
-
113
- // Global error handler (must be last)
114
- app.use(errorHandler);
115
-
116
- return app;
117
- }
118
-
119
- /**
120
- * Start the dashboard server
121
- */
122
- export function serveDashboard(rootPath: string): void {
123
- try {
124
- const port = appConfig.dashboard.port;
125
- const host = appConfig.dashboard.host;
126
- const validatedPort = validatePort(port);
127
-
128
- const app = createDashboardApp();
129
-
130
- const server = app.listen(validatedPort, host, () => {
131
- console.log(SUCCESS_DASHBOARD_START(host, validatedPort));
132
- console.log('Press Ctrl+C to quit.');
133
- });
134
-
135
- server.on('error', (err: NodeJS.ErrnoException) => {
136
- if (err.code === 'EADDRINUSE') {
137
- AppLogger.error(ERROR_PORT_IN_USE(validatedPort), err);
138
- process.exit(1);
139
- } else if (err.code === 'EACCES') {
140
- AppLogger.error(ERROR_PERMISSION_DENIED(validatedPort), err);
141
- process.exit(1);
142
- } else {
143
- AppLogger.error('Server failed to start:', err);
144
- process.exit(1);
145
- }
146
- });
147
-
148
- // Graceful shutdown
149
- process.on('SIGTERM', () => {
150
- AppLogger.info(MESSAGE_DASHBOARD_GRACEFUL_SHUTDOWN);
151
- server.close(() => {
152
- AppLogger.info(MESSAGE_DASHBOARD_CLOSED);
153
- process.exit(0);
154
- });
155
- });
156
- } catch (error: unknown) {
157
- const err = error as Error & { message?: string };
158
- AppLogger.error('Failed to start dashboard:', err);
159
- process.exit(1);
160
- }
161
- }
@@ -1,50 +0,0 @@
1
- /**
2
- * Error handling middleware for Express
3
- */
4
-
5
- import { Request, Response, NextFunction, ErrorRequestHandler } from 'express';
6
- import { AppLogger } from './logger';
7
-
8
- /**
9
- * Custom error interface extending Error
10
- */
11
- export interface CustomError extends Error {
12
- status?: number;
13
- statusCode?: number;
14
- }
15
-
16
- /**
17
- * Global error handler middleware
18
- * Must be registered last in the middleware chain
19
- */
20
- export const errorHandler: ErrorRequestHandler = (
21
- err: CustomError,
22
- req: Request,
23
- res: Response,
24
- _next: NextFunction
25
- ): void => {
26
- const status = err.status || err.statusCode || 500;
27
-
28
- AppLogger.error('Request error occurred', {
29
- status,
30
- method: req.method,
31
- path: req.path,
32
- message: err.message,
33
- timestamp: new Date().toISOString(),
34
- });
35
-
36
- res.status(status).json({
37
- error: 'Internal server error',
38
- timestamp: Date.now(),
39
- });
40
- };
41
-
42
- /**
43
- * 404 Not Found handler
44
- */
45
- export const notFoundHandler = (_req: Request, res: Response): void => {
46
- res.status(404).json({
47
- error: 'Endpoint not found',
48
- timestamp: Date.now(),
49
- });
50
- };
@@ -1,20 +0,0 @@
1
- /**
2
- * Middleware exports
3
- */
4
-
5
- export { errorHandler, notFoundHandler } from './error-handler';
6
- export type { CustomError } from './error-handler';
7
-
8
- export {
9
- createHelmetMiddleware,
10
- createApiCorsMiddleware,
11
- createDashboardCorsMiddleware,
12
- createTimeoutMiddleware,
13
- buildApiUrl,
14
- buildDashboardUrl,
15
- } from './security';
16
-
17
- export { startServer } from './server-startup';
18
- export { serveDashboard } from './dashboard-startup';
19
-
20
- export { httpLogger, AppLogger } from './logger';
@@ -1,65 +0,0 @@
1
- /**
2
- * Logger configuration using Morgan
3
- */
4
-
5
- import morgan from 'morgan';
6
- import fs from 'fs';
7
- import path from 'path';
8
-
9
- const accessLogStream = fs.createWriteStream(path.join(__dirname, '../../','access.log'),{flags : 'a'});
10
-
11
- /**
12
- * HTTP request logger middleware using Morgan, only log error responses
13
- */
14
- export const httpLogger = morgan('combined', {
15
- stream : accessLogStream,
16
- // skip: function (req, res) { return res.statusCode < 400 }
17
- });
18
-
19
- /**
20
- * Application logger for non-HTTP events
21
- */
22
- export class AppLogger {
23
- private static readonly prefix = '[APP]';
24
-
25
- static info(message: string, data?: Record<string, unknown>): void {
26
- if (process.env.LOG_LEVEL == 'info' || process.env.LOG_LEVEL == 'debug') {
27
- if (data) {
28
- console.log(`${this.prefix} [INFO]`, message, JSON.stringify(data, null, 2));
29
- } else {
30
- console.log(`${this.prefix} [INFO]`, message);
31
- }
32
- }
33
- }
34
-
35
- static error(message: string, error?: Error | Record<string, unknown>): void {
36
- if (error instanceof Error) {
37
- console.error(`${this.prefix} [ERROR]`, message, {
38
- message: error.message,
39
- stack: error.stack,
40
- });
41
- } else if (error) {
42
- console.error(`${this.prefix} [ERROR]`, message, error);
43
- } else {
44
- console.error(`${this.prefix} [ERROR]`, message);
45
- }
46
- }
47
-
48
- static warn(message: string, data?: Record<string, unknown>): void {
49
- if (data) {
50
- console.warn(`${this.prefix} [WARN]`, message, JSON.stringify(data, null, 2));
51
- } else {
52
- console.warn(`${this.prefix} [WARN]`, message);
53
- }
54
- }
55
-
56
- static debug(message: string, data?: Record<string, unknown>): void {
57
- if (process.env.LOG_LEVEL == 'debug') {
58
- if (data) {
59
- console.log(`${this.prefix} [DEBUG]`, message, JSON.stringify(data, null, 2));
60
- } else {
61
- console.log(`${this.prefix} [DEBUG]`, message);
62
- }
63
- }
64
- }
65
- }
@@ -1,90 +0,0 @@
1
- /**
2
- * Security middleware and configuration
3
- */
4
-
5
- import { Request, Response, NextFunction } from 'express';
6
- import helmet from 'helmet';
7
- import cors, { CorsOptions } from 'cors';
8
- import type { MonodogConfig } from '../types/config';
9
- import {
10
- REQUEST_TIMEOUT,
11
- RESPONSE_TIMEOUT,
12
- CORS_API_METHODS,
13
- CORS_ALLOWED_HEADERS,
14
- DEFAULT_LOCALHOST,
15
- WILDCARD_ADDRESS,
16
- HTTP_PROTOCOL,
17
- } from '../constants';
18
-
19
- /**
20
- * Create Helmet security middleware with Content Security Policy
21
- */
22
- export function createHelmetMiddleware(apiUrl: string) {
23
- return helmet({
24
- contentSecurityPolicy: {
25
- directives: {
26
- defaultSrc: ["'self'"],
27
- connectSrc: ["'self'", apiUrl, 'http://localhost:*', 'http://127.0.0.1:*'],
28
- scriptSrc: ["'self'"],
29
- imgSrc: ["'self'", 'data:', 'https:'],
30
- },
31
- },
32
- });
33
- }
34
-
35
- /**
36
- * Create CORS middleware for API server
37
- */
38
- export function createApiCorsMiddleware(dashboardUrl: string) {
39
- const corsOptions: CorsOptions = {
40
- origin: dashboardUrl,
41
- credentials: true,
42
- methods: [...CORS_API_METHODS],
43
- allowedHeaders: [...CORS_ALLOWED_HEADERS],
44
- };
45
-
46
- return cors(corsOptions);
47
- }
48
-
49
- /**
50
- * Create CORS middleware for dashboard (no cross-origin)
51
- */
52
- export function createDashboardCorsMiddleware() {
53
- const corsOptions: CorsOptions = {
54
- origin: false, // Don't allow any origin for static assets
55
- };
56
-
57
- return cors(corsOptions);
58
- }
59
-
60
- /**
61
- * Request timeout middleware (30 seconds)
62
- */
63
- export function createTimeoutMiddleware() {
64
- return (req: Request, res: Response, next: NextFunction): void => {
65
- req.setTimeout(REQUEST_TIMEOUT);
66
- res.setTimeout(RESPONSE_TIMEOUT);
67
- next();
68
- };
69
- }
70
-
71
- /**
72
- * Build API URL based on config
73
- */
74
- export function buildApiUrl(
75
- host: string,
76
- port: number
77
- ): string {
78
- const apiHost = host === WILDCARD_ADDRESS ? DEFAULT_LOCALHOST : host;
79
- return `${HTTP_PROTOCOL}${apiHost}:${port}`;
80
- }
81
-
82
- /**
83
- * Build dashboard URL based on config
84
- */
85
- export function buildDashboardUrl(config: MonodogConfig): string {
86
- const dashboardHost = config.dashboard.host === WILDCARD_ADDRESS
87
- ? DEFAULT_LOCALHOST
88
- : config.dashboard.host;
89
- return `${HTTP_PROTOCOL}${dashboardHost}:${config.dashboard.port}`;
90
- }
@@ -1,153 +0,0 @@
1
- /**
2
- * Server startup logic for the API backend
3
- */
4
-
5
- import express from 'express';
6
- import { json } from 'body-parser';
7
- import type { Express } from 'express';
8
- import { httpLogger, AppLogger } from './logger';
9
-
10
- import { appConfig } from '../config-loader';
11
- import {
12
- errorHandler,
13
- notFoundHandler,
14
- } from './error-handler';
15
- import {
16
- createHelmetMiddleware,
17
- createApiCorsMiddleware,
18
- createTimeoutMiddleware,
19
- buildApiUrl,
20
- buildDashboardUrl,
21
- } from './security';
22
- import { setupSwaggerDocs } from './swagger-middleware';
23
-
24
- import packageRouter from '../routes/package-routes';
25
- import commitRouter from '../routes/commit-routes';
26
- import healthRouter from '../routes/health-routes';
27
- import configRouter from '../routes/config-routes';
28
- import {
29
- PORT_MIN,
30
- PORT_MAX,
31
- PORT_VALIDATION_ERROR_MESSAGE,
32
- BODY_PARSER_LIMIT,
33
- SUCCESS_SERVER_START,
34
- ERROR_PORT_IN_USE,
35
- ERROR_PERMISSION_DENIED,
36
- MESSAGE_GRACEFUL_SHUTDOWN,
37
- MESSAGE_SERVER_CLOSED,
38
- } from '../constants';
39
-
40
- /**
41
- * Validate port number
42
- */
43
- function validatePort(port: string | number): number {
44
- const portNum = typeof port === 'string' ? parseInt(port, 10) : port;
45
-
46
- if (isNaN(portNum) || portNum < PORT_MIN || portNum > PORT_MAX) {
47
- throw new Error(PORT_VALIDATION_ERROR_MESSAGE(PORT_MIN, PORT_MAX));
48
- }
49
-
50
- return portNum;
51
- }
52
-
53
- /**
54
- * Create Express app with middleware configuration
55
- */
56
- function createApp(rootPath: string): Express {
57
- const app = express();
58
-
59
- // Timeout middleware
60
- app.use(createTimeoutMiddleware());
61
-
62
- // Store root path for routes
63
- app.locals.rootPath = rootPath;
64
-
65
- // Security and CORS setup
66
- const dashboardUrl = buildDashboardUrl(appConfig);
67
- const apiUrl = buildApiUrl(appConfig.server.host, appConfig.server.port);
68
-
69
- app.use(createHelmetMiddleware(apiUrl));
70
- app.use(createApiCorsMiddleware(dashboardUrl));
71
-
72
- // Body parser
73
- app.use(json({ limit: BODY_PARSER_LIMIT }));
74
-
75
- // HTTP request logging with Morgan
76
- app.use(httpLogger);
77
-
78
- // Setup Swagger documentation
79
- setupSwaggerDocs(app);
80
-
81
- // Routes
82
- app.use('/api/packages', packageRouter);
83
- app.use('/api/commits/', commitRouter);
84
- app.use('/api/health/', healthRouter);
85
- app.use('/api/config/', configRouter);
86
-
87
- // 404 handler
88
- app.use('*', notFoundHandler);
89
-
90
- // Global error handler (must be last)
91
- app.use(errorHandler);
92
-
93
- return app;
94
- }
95
-
96
- /**
97
- * Start the API server
98
- */
99
- export function startServer(rootPath: string): void {
100
- try {
101
- const port = appConfig.server.port;
102
- const host = appConfig.server.host;
103
- const validatedPort = validatePort(port);
104
-
105
- AppLogger.info(`Starting Monodog API server...`);
106
- AppLogger.info(`Analyzing monorepo at root: ${rootPath}`);
107
-
108
- const app = createApp(rootPath);
109
-
110
- const server = app.listen(validatedPort, host, () => {
111
- console.log(SUCCESS_SERVER_START(host, validatedPort));
112
- AppLogger.info('API endpoints available:', {
113
- endpoints: [
114
- 'POST /api/packages/refresh',
115
- 'GET /api/packages',
116
- 'GET /api/packages/:name',
117
- 'PUT /api/packages/update-config',
118
- 'GET /api/commits/:packagePath',
119
- 'GET /api/health/packages',
120
- 'POST /api/health/refresh',
121
- 'PUT /api/config/files/:id',
122
- 'GET /api/config/files',
123
- ],
124
- });
125
- });
126
-
127
- server.on('error', (err: NodeJS.ErrnoException) => {
128
- if (err.code === 'EADDRINUSE') {
129
- AppLogger.error(ERROR_PORT_IN_USE(validatedPort), err);
130
- process.exit(1);
131
- } else if (err.code === 'EACCES') {
132
- AppLogger.error(ERROR_PERMISSION_DENIED(validatedPort), err);
133
- process.exit(1);
134
- } else {
135
- AppLogger.error('Server failed to start:', err);
136
- process.exit(1);
137
- }
138
- });
139
-
140
- // Graceful shutdown
141
- process.on('SIGTERM', () => {
142
- AppLogger.info(MESSAGE_GRACEFUL_SHUTDOWN);
143
- server.close(() => {
144
- AppLogger.info(MESSAGE_SERVER_CLOSED);
145
- process.exit(0);
146
- });
147
- });
148
- } catch (error: unknown) {
149
- const err = error as Error & { message?: string };
150
- AppLogger.error('Failed to start server:', err);
151
- process.exit(1);
152
- }
153
- }