@infodb/revx 0.1.0

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.
@@ -0,0 +1,160 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import morgan from 'morgan';
4
+ import { createServer } from 'http';
5
+ import { createServer as createHttpsServer } from 'https';
6
+ import { readFileSync } from 'fs';
7
+ import { ConfigLoader } from '../utils/config.js';
8
+ import { ProxyManager } from '../utils/proxy.js';
9
+ import { Logger } from '../utils/logger.js';
10
+ import { randomUUID } from 'crypto';
11
+ export async function startCommand(configFile = 'revx.yaml', options) {
12
+ const logger = new Logger(options.verbose);
13
+ const configLoader = new ConfigLoader(logger);
14
+ try {
15
+ logger.info(`Loading configuration from: ${configFile}`);
16
+ const config = configLoader.load(configFile);
17
+ const app = express();
18
+ const proxyManager = new ProxyManager(logger);
19
+ setupMiddleware(app, config, logger);
20
+ setupRoutes(app, config, proxyManager, logger);
21
+ await startServer(app, config, logger);
22
+ }
23
+ catch (error) {
24
+ if (error instanceof Error) {
25
+ logger.error(`Failed to start server: ${error.message}`);
26
+ }
27
+ process.exit(1);
28
+ }
29
+ }
30
+ function setupMiddleware(app, config, logger) {
31
+ if (config.global?.cors?.enabled !== false) {
32
+ const corsOptions = {
33
+ origin: config.global?.cors?.origin || '*',
34
+ methods: config.global?.cors?.methods || ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
35
+ credentials: config.global?.cors?.credentials ?? true
36
+ };
37
+ app.use(cors(corsOptions));
38
+ logger.verbose('CORS enabled', corsOptions);
39
+ }
40
+ const requestIdMiddleware = config.middleware?.find(m => m.type === 'requestId');
41
+ if (requestIdMiddleware?.enabled !== false) {
42
+ const headerName = requestIdMiddleware?.headerName || 'X-Request-ID';
43
+ app.use((req, res, next) => {
44
+ const requestId = randomUUID();
45
+ req.headers[headerName.toLowerCase()] = requestId;
46
+ res.setHeader(headerName, requestId);
47
+ next();
48
+ });
49
+ logger.verbose('Request ID middleware enabled');
50
+ }
51
+ if (config.global?.logging?.enabled !== false) {
52
+ const format = config.global?.logging?.format || 'combined';
53
+ app.use(morgan(format));
54
+ logger.verbose(`Logging middleware enabled: ${format}`);
55
+ }
56
+ const compressionMiddleware = config.middleware?.find(m => m.type === 'compression');
57
+ if (compressionMiddleware?.enabled) {
58
+ logger.verbose('Compression middleware enabled');
59
+ }
60
+ app.use(express.json());
61
+ app.use(express.urlencoded({ extended: true }));
62
+ }
63
+ function setupRoutes(app, config, proxyManager, logger) {
64
+ config.routes.forEach((route) => {
65
+ if (route.cors) {
66
+ const routeCorsOptions = {
67
+ origin: route.cors.origin || '*',
68
+ methods: route.cors.methods || ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
69
+ credentials: route.cors.credentials ?? true
70
+ };
71
+ app.use(route.path, cors(routeCorsOptions));
72
+ logger.verbose(`Route-specific CORS for ${route.path}`, routeCorsOptions);
73
+ }
74
+ const proxyMiddleware = proxyManager.createProxyMiddleware(route);
75
+ app.use(route.path, proxyMiddleware);
76
+ });
77
+ app.get('/health', (req, res) => {
78
+ res.json({ status: 'ok', timestamp: new Date().toISOString() });
79
+ });
80
+ app.use((req, res) => {
81
+ res.status(404).json({
82
+ error: 'Not Found',
83
+ message: `No route matches ${req.method} ${req.path}`
84
+ });
85
+ });
86
+ app.use((err, req, res, next) => {
87
+ logger.error(`Server error: ${err.message}`);
88
+ if (!res.headersSent) {
89
+ res.status(500).json({
90
+ error: 'Internal Server Error',
91
+ message: err.message
92
+ });
93
+ }
94
+ });
95
+ }
96
+ async function startServer(app, config, logger) {
97
+ return new Promise((resolve, reject) => {
98
+ const port = config.server.port;
99
+ const host = config.server.host || '0.0.0.0';
100
+ let server;
101
+ if (config.ssl?.enabled) {
102
+ try {
103
+ const httpsOptions = {
104
+ key: readFileSync(config.ssl.key, 'utf-8'),
105
+ cert: readFileSync(config.ssl.cert, 'utf-8'),
106
+ ca: config.ssl.ca ? readFileSync(config.ssl.ca, 'utf-8') : undefined
107
+ };
108
+ server = createHttpsServer(httpsOptions, app);
109
+ logger.info('SSL/TLS enabled');
110
+ }
111
+ catch (error) {
112
+ if (error instanceof Error) {
113
+ reject(new Error(`Failed to load SSL certificates: ${error.message}`));
114
+ }
115
+ return;
116
+ }
117
+ }
118
+ else {
119
+ server = createServer(app);
120
+ }
121
+ server.listen(port, host, () => {
122
+ const protocol = config.ssl?.enabled ? 'https' : 'http';
123
+ logger.server(`${config.server.name || 'Reverse Proxy'} started`);
124
+ logger.success(`Listening on ${protocol}://${host}:${port}`);
125
+ logger.info('');
126
+ logger.info('Configured routes:');
127
+ config.routes.forEach((route) => {
128
+ const target = route.target || `${route.targets?.length} targets`;
129
+ logger.info(` ${route.path} -> ${target}`);
130
+ });
131
+ logger.info('');
132
+ logger.info('Press Ctrl+C to stop the server');
133
+ resolve();
134
+ });
135
+ server.on('error', (error) => {
136
+ if (error.code === 'EADDRINUSE') {
137
+ reject(new Error(`Port ${port} is already in use`));
138
+ }
139
+ else {
140
+ reject(error);
141
+ }
142
+ });
143
+ process.on('SIGINT', () => {
144
+ logger.info('');
145
+ logger.info('Shutting down server...');
146
+ server.close(() => {
147
+ logger.success('Server stopped');
148
+ process.exit(0);
149
+ });
150
+ });
151
+ process.on('SIGTERM', () => {
152
+ logger.info('Received SIGTERM signal');
153
+ server.close(() => {
154
+ logger.success('Server stopped');
155
+ process.exit(0);
156
+ });
157
+ });
158
+ });
159
+ }
160
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function validateCommand(configFile: string, options: {
2
+ verbose?: boolean;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAGA,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,iBAkDvF"}
@@ -0,0 +1,50 @@
1
+ import { ConfigLoader } from '../utils/config.js';
2
+ import { Logger } from '../utils/logger.js';
3
+ export async function validateCommand(configFile, options) {
4
+ const logger = new Logger(options.verbose);
5
+ const configLoader = new ConfigLoader(logger);
6
+ try {
7
+ logger.info(`Validating configuration file: ${configFile}`);
8
+ const config = configLoader.load(configFile);
9
+ logger.success('Configuration is valid');
10
+ logger.info('');
11
+ logger.info('Configuration summary:');
12
+ logger.info(` Server: ${config.server.host || '0.0.0.0'}:${config.server.port}`);
13
+ logger.info(` Routes: ${config.routes.length}`);
14
+ if (options.verbose) {
15
+ logger.info('');
16
+ logger.info('Route details:');
17
+ config.routes.forEach((route, index) => {
18
+ logger.info(` ${index + 1}. ${route.path}`);
19
+ if (route.target) {
20
+ logger.info(` Target: ${route.target}`);
21
+ }
22
+ else if (route.targets) {
23
+ logger.info(` Targets: ${route.targets.length} (${route.strategy || 'round-robin'})`);
24
+ route.targets.forEach((target, i) => {
25
+ logger.info(` ${i + 1}. ${target}`);
26
+ });
27
+ }
28
+ });
29
+ if (config.middleware && config.middleware.length > 0) {
30
+ logger.info('');
31
+ logger.info('Middleware:');
32
+ config.middleware.forEach((mw, index) => {
33
+ const status = mw.enabled === false ? 'disabled' : 'enabled';
34
+ logger.info(` ${index + 1}. ${mw.type} (${status})`);
35
+ });
36
+ }
37
+ if (config.ssl?.enabled) {
38
+ logger.info('');
39
+ logger.info('SSL: enabled');
40
+ }
41
+ }
42
+ }
43
+ catch (error) {
44
+ if (error instanceof Error) {
45
+ logger.error(`Validation failed: ${error.message}`);
46
+ }
47
+ process.exit(1);
48
+ }
49
+ }
50
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { startCommand } from './commands/start.js';
4
+ import { validateCommand } from './commands/validate.js';
5
+ import { initCommand } from './commands/init.js';
6
+ const program = new Command();
7
+ program
8
+ .name('revx')
9
+ .description('Reverse proxy CLI tool with YAML configuration')
10
+ .version('0.1.0');
11
+ program
12
+ .command('start')
13
+ .description('Start the reverse proxy server')
14
+ .argument('[config-file]', 'Configuration file path', 'revx.yaml')
15
+ .option('--verbose', 'Verbose output')
16
+ .action(startCommand);
17
+ program
18
+ .command('validate')
19
+ .description('Validate configuration file')
20
+ .argument('<config-file>', 'Configuration file path')
21
+ .option('--verbose', 'Verbose output')
22
+ .action(validateCommand);
23
+ program
24
+ .command('init')
25
+ .description('Create a sample configuration file')
26
+ .option('--simple', 'Create a simple configuration file')
27
+ .option('--output <file>', 'Output file path', 'revx.yaml')
28
+ .option('--verbose', 'Verbose output')
29
+ .action(initCommand);
30
+ program.parse();
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,gCAAgC,CAAC;KAC7C,QAAQ,CAAC,eAAe,EAAE,yBAAyB,EAAE,WAAW,CAAC;KACjE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACrC,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,6BAA6B,CAAC;KAC1C,QAAQ,CAAC,eAAe,EAAE,yBAAyB,CAAC;KACpD,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACrC,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,UAAU,EAAE,oCAAoC,CAAC;KACxD,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,WAAW,CAAC;KAC1D,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC;KACrC,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { Logger } from './logger.js';
2
+ export interface CorsConfig {
3
+ enabled?: boolean;
4
+ origin?: string | string[];
5
+ methods?: string[];
6
+ credentials?: boolean;
7
+ }
8
+ export interface RateLimitConfig {
9
+ enabled?: boolean;
10
+ windowMs?: number;
11
+ max?: number;
12
+ }
13
+ export interface LoggingConfig {
14
+ enabled?: boolean;
15
+ format?: 'combined' | 'dev' | 'common' | 'short' | 'tiny';
16
+ level?: 'error' | 'warn' | 'info' | 'debug';
17
+ }
18
+ export interface GlobalConfig {
19
+ timeout?: number;
20
+ cors?: CorsConfig;
21
+ logging?: LoggingConfig;
22
+ rateLimit?: RateLimitConfig;
23
+ }
24
+ export interface ServerConfig {
25
+ port: number;
26
+ host?: string;
27
+ name?: string;
28
+ }
29
+ export interface RouteOptions {
30
+ timeout?: number;
31
+ followRedirects?: boolean;
32
+ headers?: Record<string, string>;
33
+ }
34
+ export interface CacheConfig {
35
+ enabled?: boolean;
36
+ ttl?: number;
37
+ }
38
+ export interface AuthConfig {
39
+ type?: 'bearer' | 'basic' | 'apikey';
40
+ headerName?: string;
41
+ }
42
+ export interface HealthCheckConfig {
43
+ enabled?: boolean;
44
+ interval?: number;
45
+ path?: string;
46
+ timeout?: number;
47
+ }
48
+ export interface TransformConfig {
49
+ request?: {
50
+ headers?: {
51
+ add?: Record<string, string>;
52
+ remove?: string[];
53
+ };
54
+ };
55
+ response?: {
56
+ headers?: {
57
+ add?: Record<string, string>;
58
+ remove?: string[];
59
+ };
60
+ };
61
+ }
62
+ export interface RouteConfig {
63
+ path: string;
64
+ target?: string;
65
+ targets?: string[];
66
+ changeOrigin?: boolean;
67
+ pathRewrite?: Record<string, string>;
68
+ ws?: boolean;
69
+ strategy?: 'round-robin' | 'random' | 'ip-hash';
70
+ options?: RouteOptions;
71
+ cors?: CorsConfig;
72
+ cache?: CacheConfig;
73
+ auth?: AuthConfig;
74
+ healthCheck?: HealthCheckConfig;
75
+ transform?: TransformConfig;
76
+ }
77
+ export interface MiddlewareConfig {
78
+ type: string;
79
+ enabled?: boolean;
80
+ paths?: string[];
81
+ config?: Record<string, any>;
82
+ headerName?: string;
83
+ threshold?: number;
84
+ }
85
+ export interface SslConfig {
86
+ enabled?: boolean;
87
+ key?: string;
88
+ cert?: string;
89
+ ca?: string;
90
+ }
91
+ export interface RevxConfig {
92
+ server: ServerConfig;
93
+ global?: GlobalConfig;
94
+ routes: RouteConfig[];
95
+ middleware?: MiddlewareConfig[];
96
+ ssl?: SslConfig;
97
+ }
98
+ export declare class ConfigLoader {
99
+ private logger;
100
+ constructor(logger: Logger);
101
+ load(configPath: string): RevxConfig;
102
+ private expandEnvironmentVariables;
103
+ private sortRoutesBySpecificity;
104
+ private validateConfig;
105
+ private validateRoute;
106
+ }
107
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import { readFileSync, existsSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import YAML from 'yaml';
4
+ export class ConfigLoader {
5
+ constructor(logger) {
6
+ this.logger = logger;
7
+ }
8
+ load(configPath) {
9
+ const fullPath = resolve(process.cwd(), configPath);
10
+ this.logger.verbose('Loading configuration file', { path: fullPath });
11
+ if (!existsSync(fullPath)) {
12
+ throw new Error(`Configuration file not found: ${fullPath}`);
13
+ }
14
+ try {
15
+ const fileContent = readFileSync(fullPath, 'utf-8');
16
+ const expandedContent = this.expandEnvironmentVariables(fileContent);
17
+ const config = YAML.parse(expandedContent);
18
+ this.sortRoutesBySpecificity(config);
19
+ this.validateConfig(config);
20
+ return config;
21
+ }
22
+ catch (error) {
23
+ if (error instanceof Error) {
24
+ throw new Error(`Failed to load configuration: ${error.message}`);
25
+ }
26
+ throw error;
27
+ }
28
+ }
29
+ expandEnvironmentVariables(content) {
30
+ return content.replace(/\$\{([^}]+)\}/g, (match, varName) => {
31
+ const value = process.env[varName];
32
+ if (value === undefined) {
33
+ this.logger.warning(`Environment variable not found: ${varName}, using empty string`);
34
+ return '';
35
+ }
36
+ return value;
37
+ });
38
+ }
39
+ sortRoutesBySpecificity(config) {
40
+ if (!config.routes || config.routes.length === 0) {
41
+ return;
42
+ }
43
+ config.routes.sort((a, b) => {
44
+ const pathA = a.path;
45
+ const pathB = b.path;
46
+ // 1. パスの長さで降順ソート(長いパスが先)
47
+ const lengthDiff = pathB.length - pathA.length;
48
+ if (lengthDiff !== 0) {
49
+ return lengthDiff;
50
+ }
51
+ // 2. ワイルドカードの数で昇順ソート(ワイルドカードが少ない方が具体的)
52
+ const wildcardCountA = (pathA.match(/\*/g) || []).length;
53
+ const wildcardCountB = (pathB.match(/\*/g) || []).length;
54
+ const wildcardDiff = wildcardCountA - wildcardCountB;
55
+ if (wildcardDiff !== 0) {
56
+ return wildcardDiff;
57
+ }
58
+ // 3. 辞書順でソート
59
+ return pathA.localeCompare(pathB);
60
+ });
61
+ this.logger.verbose('Routes sorted by specificity', {
62
+ routes: config.routes.map(r => r.path)
63
+ });
64
+ }
65
+ validateConfig(config) {
66
+ if (!config.server) {
67
+ throw new Error('Server configuration is required');
68
+ }
69
+ if (!config.server.port) {
70
+ throw new Error('Server port is required');
71
+ }
72
+ if (!config.routes || !Array.isArray(config.routes)) {
73
+ throw new Error('Routes configuration is required and must be an array');
74
+ }
75
+ if (config.routes.length === 0) {
76
+ throw new Error('At least one route must be configured');
77
+ }
78
+ for (const route of config.routes) {
79
+ this.validateRoute(route);
80
+ }
81
+ }
82
+ validateRoute(route) {
83
+ if (!route.path) {
84
+ throw new Error('Route path is required');
85
+ }
86
+ if (!route.target && !route.targets) {
87
+ throw new Error(`Route ${route.path} must have either target or targets`);
88
+ }
89
+ if (route.target && route.targets) {
90
+ throw new Error(`Route ${route.path} cannot have both target and targets`);
91
+ }
92
+ if (route.targets) {
93
+ if (!Array.isArray(route.targets) || route.targets.length === 0) {
94
+ throw new Error(`Route ${route.path} targets must be a non-empty array`);
95
+ }
96
+ if (route.strategy && !['round-robin', 'random', 'ip-hash'].includes(route.strategy)) {
97
+ throw new Error(`Route ${route.path} has invalid strategy: ${route.strategy}`);
98
+ }
99
+ }
100
+ }
101
+ }
102
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,IAAI,MAAM,MAAM,CAAC;AAiHxB,MAAM,OAAO,YAAY;IACvB,YAAoB,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;IAAG,CAAC;IAEtC,IAAI,CAAC,UAAkB;QACrB,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACpD,MAAM,eAAe,GAAG,IAAI,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAe,CAAC;YAEzD,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,0BAA0B,CAAC,OAAe;QAChD,OAAO,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,mCAAmC,OAAO,sBAAsB,CAAC,CAAC;gBACtF,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,uBAAuB,CAAC,MAAkB;QAChD,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;YACrB,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;YAErB,yBAAyB;YACzB,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC/C,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gBACrB,OAAO,UAAU,CAAC;YACpB,CAAC;YAED,uCAAuC;YACvC,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACzD,MAAM,cAAc,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACzD,MAAM,YAAY,GAAG,cAAc,GAAG,cAAc,CAAC;YACrD,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;gBACvB,OAAO,YAAY,CAAC;YACtB,CAAC;YAED,aAAa;YACb,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,8BAA8B,EAAE;YAClD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACvC,CAAC,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,MAAkB;QACvC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,KAAkB;QACtC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,qCAAqC,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,sCAAsC,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,oCAAoC,CAAC,CAAC;YAC3E,CAAC;YAED,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,aAAa,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrF,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,IAAI,0BAA0B,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ export declare class Logger {
2
+ private isVerbose;
3
+ constructor(isVerbose?: boolean);
4
+ info(message: string): void;
5
+ success(message: string): void;
6
+ error(message: string): void;
7
+ warning(message: string): void;
8
+ verbose(message: string, data?: any): void;
9
+ debug(message: string, data?: any): void;
10
+ server(message: string): void;
11
+ request(method: string, path: string): void;
12
+ private getMethodColor;
13
+ }
14
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,qBAAa,MAAM;IACL,OAAO,CAAC,SAAS;gBAAT,SAAS,GAAE,OAAe;IAE9C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI3B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI5B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAS1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IASxC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAK3C,OAAO,CAAC,cAAc;CAgBvB"}
@@ -0,0 +1,58 @@
1
+ import chalk from 'chalk';
2
+ export class Logger {
3
+ constructor(isVerbose = false) {
4
+ this.isVerbose = isVerbose;
5
+ }
6
+ info(message) {
7
+ console.log(chalk.blue('ℹ'), message);
8
+ }
9
+ success(message) {
10
+ console.log(chalk.green('✓'), message);
11
+ }
12
+ error(message) {
13
+ console.error(chalk.red('✗'), message);
14
+ }
15
+ warning(message) {
16
+ console.warn(chalk.yellow('⚠'), message);
17
+ }
18
+ verbose(message, data) {
19
+ if (this.isVerbose) {
20
+ console.log(chalk.gray('🔍'), chalk.gray(message));
21
+ if (data) {
22
+ console.log(chalk.gray(JSON.stringify(data, null, 2)));
23
+ }
24
+ }
25
+ }
26
+ debug(message, data) {
27
+ if (this.isVerbose) {
28
+ console.log(chalk.magenta('🐛'), chalk.magenta(message));
29
+ if (data) {
30
+ console.log(chalk.magenta(JSON.stringify(data, null, 2)));
31
+ }
32
+ }
33
+ }
34
+ server(message) {
35
+ console.log(chalk.cyan('🚀'), message);
36
+ }
37
+ request(method, path) {
38
+ const methodColor = this.getMethodColor(method);
39
+ console.log(chalk.gray('→'), methodColor(method.padEnd(7)), chalk.white(path));
40
+ }
41
+ getMethodColor(method) {
42
+ switch (method.toUpperCase()) {
43
+ case 'GET':
44
+ return chalk.green;
45
+ case 'POST':
46
+ return chalk.blue;
47
+ case 'PUT':
48
+ return chalk.yellow;
49
+ case 'DELETE':
50
+ return chalk.red;
51
+ case 'PATCH':
52
+ return chalk.magenta;
53
+ default:
54
+ return chalk.white;
55
+ }
56
+ }
57
+ }
58
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,MAAM;IACjB,YAAoB,YAAqB,KAAK;QAA1B,cAAS,GAAT,SAAS,CAAiB;IAAG,CAAC;IAElD,IAAI,CAAC,OAAe;QAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,OAAe;QACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,OAAe;QACnB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,OAAe;QACrB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,OAAe,EAAE,IAAU;QACjC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YACnD,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAU;QAC/B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACzD,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,MAAc,EAAE,IAAY;QAClC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;IAEO,cAAc,CAAC,MAAc;QACnC,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YAC7B,KAAK,KAAK;gBACR,OAAO,KAAK,CAAC,KAAK,CAAC;YACrB,KAAK,MAAM;gBACT,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,KAAK,KAAK;gBACR,OAAO,KAAK,CAAC,MAAM,CAAC;YACtB,KAAK,QAAQ;gBACX,OAAO,KAAK,CAAC,GAAG,CAAC;YACnB,KAAK,OAAO;gBACV,OAAO,KAAK,CAAC,OAAO,CAAC;YACvB;gBACE,OAAO,KAAK,CAAC,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import { RouteConfig } from './config.js';
2
+ import { Logger } from './logger.js';
3
+ import { Request } from 'express';
4
+ import { IncomingMessage, ServerResponse } from 'http';
5
+ export declare class LoadBalancer {
6
+ private targets;
7
+ private strategy;
8
+ private logger;
9
+ private currentIndex;
10
+ private targetHealth;
11
+ constructor(targets: string[], strategy: "round-robin" | "random" | "ip-hash" | undefined, logger: Logger);
12
+ getTarget(req?: Request): string;
13
+ markUnhealthy(target: string): void;
14
+ markHealthy(target: string): void;
15
+ private hashCode;
16
+ }
17
+ export declare class ProxyManager {
18
+ private logger;
19
+ private loadBalancers;
20
+ constructor(logger: Logger);
21
+ createProxyMiddleware(route: RouteConfig): import("http-proxy-middleware").RequestHandler<IncomingMessage, ServerResponse<IncomingMessage>, (err?: any) => void>;
22
+ getLoadBalancer(path: string): LoadBalancer | undefined;
23
+ }
24
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/utils/proxy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAY,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAEvD,qBAAa,YAAY;IAKrB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAmC;gBAG7C,OAAO,EAAE,MAAM,EAAE,EACjB,QAAQ,EAAE,aAAa,GAAG,QAAQ,GAAG,SAAS,YAAgB,EAC9D,MAAM,EAAE,MAAM;IAKxB,SAAS,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM;IA4BhC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKnC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAKjC,OAAO,CAAC,QAAQ;CASjB;AAED,qBAAa,YAAY;IAGX,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,aAAa,CAAwC;gBAEzC,MAAM,EAAE,MAAM;IAElC,qBAAqB,CAAC,KAAK,EAAE,WAAW;IAyFxC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;CAGxD"}