yxorp 0.1.5 → 0.2.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.
Files changed (63) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +369 -81
  3. package/bin/yxorp.js +13 -22
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +59 -0
  6. package/dist/middleware/bootstrap.middleware.d.ts +15 -0
  7. package/dist/middleware/bootstrap.middleware.js +63 -0
  8. package/dist/middleware/mock.middleware.d.ts +9 -0
  9. package/dist/middleware/mock.middleware.js +54 -0
  10. package/dist/middleware/proxy.middleware.d.ts +15 -0
  11. package/dist/middleware/proxy.middleware.js +26 -0
  12. package/dist/middleware/proxyRes.middleware.d.ts +9 -0
  13. package/dist/middleware/proxyRes.middleware.js +28 -0
  14. package/dist/middleware/rawBody.middleware.d.ts +6 -0
  15. package/dist/middleware/rawBody.middleware.js +24 -0
  16. package/dist/middleware/rewrite.middleware.d.ts +9 -0
  17. package/dist/middleware/rewrite.middleware.js +54 -0
  18. package/dist/middleware/static.middleware.d.ts +12 -0
  19. package/dist/middleware/static.middleware.js +85 -0
  20. package/dist/services/config-resolver.d.ts +6 -0
  21. package/dist/services/config-resolver.js +45 -0
  22. package/dist/services/config.service.d.ts +6 -0
  23. package/dist/services/config.service.js +12 -0
  24. package/dist/services/http-proxy.service.d.ts +14 -0
  25. package/dist/services/http-proxy.service.js +19 -0
  26. package/dist/services/http-server.service.d.ts +15 -0
  27. package/dist/services/http-server.service.js +23 -0
  28. package/dist/services/logger.service.d.ts +7 -0
  29. package/dist/services/logger.service.js +17 -0
  30. package/dist/services/pipeline.service.d.ts +8 -0
  31. package/dist/services/pipeline.service.js +29 -0
  32. package/dist/services/rules-matchers/mock-rules-matcher.service.d.ts +8 -0
  33. package/dist/services/rules-matchers/mock-rules-matcher.service.js +35 -0
  34. package/dist/services/rules-matchers/remote-rules-matcher.service.d.ts +8 -0
  35. package/dist/services/rules-matchers/remote-rules-matcher.service.js +51 -0
  36. package/dist/services/rules-matchers/rewrite-rules-matcher.service.d.ts +8 -0
  37. package/dist/services/rules-matchers/rewrite-rules-matcher.service.js +35 -0
  38. package/dist/services/yxorp-server.service.d.ts +10 -0
  39. package/dist/services/yxorp-server.service.js +49 -0
  40. package/dist/types/yxorp-config.d.ts +54 -0
  41. package/dist/types/yxorp-config.js +2 -0
  42. package/package.json +45 -38
  43. package/.editorconfig +0 -16
  44. package/src/index.ts +0 -48
  45. package/src/middleware/bootstrap.middleware.ts +0 -87
  46. package/src/middleware/mock.middleware.ts +0 -61
  47. package/src/middleware/proxy.middleware.ts +0 -42
  48. package/src/middleware/proxyRes.middleware.ts +0 -34
  49. package/src/middleware/rawBody.middleware.ts +0 -22
  50. package/src/middleware/rewrite.middleware.ts +0 -64
  51. package/src/middleware/static.middleware.ts +0 -113
  52. package/src/services/config.service.ts +0 -26
  53. package/src/services/http-proxy.service.ts +0 -25
  54. package/src/services/http-server.service.ts +0 -24
  55. package/src/services/logger.service.ts +0 -21
  56. package/src/services/pipeline.service.ts +0 -44
  57. package/src/services/rules-matchers/mock-rules-matcher.service.ts +0 -48
  58. package/src/services/rules-matchers/remote-rules-matcher.service.ts +0 -49
  59. package/src/services/rules-matchers/rewrite-rules-matcher.service.ts +0 -48
  60. package/src/services/yxorp-server.service.ts +0 -73
  61. package/src/types/http.d.ts +0 -10
  62. package/src/types/yxorp-config.ts +0 -67
  63. package/tsconfig.json +0 -21
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MockMiddleware = void 0;
7
+ const mime_1 = __importDefault(require("mime"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const path_1 = __importDefault(require("path"));
10
+ class MockMiddleware {
11
+ constructor(logger) {
12
+ this.logger = logger;
13
+ }
14
+ async use(req, res, next) {
15
+ try {
16
+ const mockRule = req === null || req === void 0 ? void 0 : req.mockRule;
17
+ if (!mockRule) {
18
+ next();
19
+ return;
20
+ }
21
+ if ('script' in mockRule) {
22
+ const fullPath = path_1.default.resolve(mockRule.script);
23
+ delete require.cache[require.resolve(fullPath)];
24
+ const handler = require(fullPath);
25
+ if (typeof handler === 'function') {
26
+ await handler(req, res);
27
+ if (!res.headersSent) {
28
+ res.setHeader('content-type', 'application/json');
29
+ }
30
+ }
31
+ this.logger.info(`mock ${res.statusCode || 200} ${req.method} ${req.url}`);
32
+ return;
33
+ }
34
+ if ('file' in mockRule) {
35
+ const file = await promises_1.default.readFile(path_1.default.resolve(mockRule.file));
36
+ const mimeType = mime_1.default.getType(path_1.default.resolve(mockRule.file));
37
+ res.statusCode = mockRule.statusCode || res.statusCode;
38
+ if (mimeType) {
39
+ res.setHeader('content-type', mimeType);
40
+ }
41
+ res.setHeader('content-length', file.length);
42
+ res.end(file);
43
+ this.logger.info(`mock ${res.statusCode} ${req.method} ${req.url}`);
44
+ return;
45
+ }
46
+ next();
47
+ }
48
+ catch (e) {
49
+ this.logger.error(e);
50
+ next();
51
+ }
52
+ }
53
+ }
54
+ exports.MockMiddleware = MockMiddleware;
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ import { HttpProxy } from '../services/http-proxy.service';
4
+ import { RemoteRulesMatcher } from '../services/rules-matchers/remote-rules-matcher.service';
5
+ import { Config } from '../services/config.service';
6
+ import { Middleware } from '../services/pipeline.service';
7
+ import { LoggerService } from '../services/logger.service';
8
+ export declare class ProxyMiddleware implements Middleware<[req: IncomingMessage, res: ServerResponse]> {
9
+ private httpProxy;
10
+ private remoteRulesMatcher;
11
+ private config;
12
+ private logger;
13
+ constructor(httpProxy: HttpProxy, remoteRulesMatcher: RemoteRulesMatcher, config: Config, logger: LoggerService);
14
+ use(req: IncomingMessage, res: ServerResponse): void;
15
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProxyMiddleware = void 0;
4
+ class ProxyMiddleware {
5
+ constructor(httpProxy, remoteRulesMatcher, config, logger) {
6
+ this.httpProxy = httpProxy;
7
+ this.remoteRulesMatcher = remoteRulesMatcher;
8
+ this.config = config;
9
+ this.logger = logger;
10
+ }
11
+ use(req, res) {
12
+ const url = req.url || '';
13
+ const proxyOptions = this.config.get().proxyOptions;
14
+ const remoteRule = this.remoteRulesMatcher.match(url);
15
+ const target = remoteRule
16
+ ? this.remoteRulesMatcher.toPath(url, remoteRule)
17
+ : undefined;
18
+ const options = {
19
+ ...proxyOptions,
20
+ prependPath: !target,
21
+ target: target || proxyOptions.target,
22
+ };
23
+ this.httpProxy.web(req, res, options).catch((error) => this.logger.error(error));
24
+ }
25
+ }
26
+ exports.ProxyMiddleware = ProxyMiddleware;
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ import { Middleware } from '../services/pipeline.service';
4
+ import { LoggerService } from '../services/logger.service';
5
+ export declare class ProxyResMiddleware implements Middleware<[proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse]> {
6
+ private logger;
7
+ constructor(logger: LoggerService);
8
+ use(proxyRes: IncomingMessage, _req: IncomingMessage, res: ServerResponse): void;
9
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProxyResMiddleware = void 0;
4
+ class ProxyResMiddleware {
5
+ constructor(logger) {
6
+ this.logger = logger;
7
+ }
8
+ use(proxyRes, _req, res) {
9
+ try {
10
+ // Skip transfer-encoding since we reconstruct the body with known length
11
+ for (let key in proxyRes.headers) {
12
+ if (key === 'transfer-encoding')
13
+ continue;
14
+ res.setHeader(key, proxyRes.headers[key]);
15
+ }
16
+ res.statusCode = proxyRes.statusCode;
17
+ res.statusMessage = proxyRes.statusMessage;
18
+ const response = proxyRes.rawBody || Buffer.from('');
19
+ res.removeHeader('content-length');
20
+ res.setHeader('content-length', response.length);
21
+ res.end(response);
22
+ }
23
+ catch (e) {
24
+ this.logger.error(e);
25
+ }
26
+ }
27
+ }
28
+ exports.ProxyResMiddleware = ProxyResMiddleware;
@@ -0,0 +1,6 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ import { Middleware } from '../services/pipeline.service';
4
+ export declare class RawBodyMiddleware implements Middleware<[proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse]> {
5
+ use(proxyRes: IncomingMessage, _req: IncomingMessage, _res: ServerResponse, next: () => void): Promise<void>;
6
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RawBodyMiddleware = void 0;
4
+ class RawBodyMiddleware {
5
+ use(proxyRes, _req, _res, next) {
6
+ return new Promise((resolve, reject) => {
7
+ const body = [];
8
+ proxyRes.on('data', (chunk) => {
9
+ body.push(chunk);
10
+ });
11
+ proxyRes.on('end', () => {
12
+ proxyRes.rawBody = Buffer.concat(body);
13
+ next();
14
+ resolve();
15
+ });
16
+ proxyRes.on('error', (err) => {
17
+ proxyRes.rawBody = Buffer.concat(body);
18
+ next();
19
+ reject(err);
20
+ });
21
+ });
22
+ }
23
+ }
24
+ exports.RawBodyMiddleware = RawBodyMiddleware;
@@ -0,0 +1,9 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage, ServerResponse } from 'http';
3
+ import { Middleware } from '../services/pipeline.service';
4
+ import { LoggerService } from '../services/logger.service';
5
+ export declare class RewriteMiddleware implements Middleware<[proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse]> {
6
+ private logger;
7
+ constructor(logger: LoggerService);
8
+ use(proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse, next: () => void): Promise<void>;
9
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RewriteMiddleware = void 0;
7
+ const http_encoding_1 = require("http-encoding");
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const path_1 = __importDefault(require("path"));
10
+ class RewriteMiddleware {
11
+ constructor(logger) {
12
+ this.logger = logger;
13
+ }
14
+ async use(proxyRes, req, res, next) {
15
+ const rewriteRule = req === null || req === void 0 ? void 0 : req.rewriteRule;
16
+ try {
17
+ if (!rewriteRule) {
18
+ next();
19
+ return;
20
+ }
21
+ const encoding = proxyRes.headers['content-encoding'];
22
+ const response = proxyRes.rawBody || Buffer.from('');
23
+ if ('script' in rewriteRule) {
24
+ const fullPath = path_1.default.resolve(rewriteRule.script);
25
+ delete require.cache[require.resolve(fullPath)];
26
+ const handler = require(fullPath);
27
+ if (typeof handler === 'function') {
28
+ const encodedResponse = await (0, http_encoding_1.decodeBuffer)(response, encoding);
29
+ const rewritedResponse = await handler(encodedResponse, proxyRes, req, res);
30
+ proxyRes.rawBody = await (0, http_encoding_1.encodeBuffer)(rewritedResponse, encoding);
31
+ }
32
+ this.logger.info(`rewrite ${proxyRes.statusCode} ${req.method} ${req.url}`);
33
+ next();
34
+ return;
35
+ }
36
+ if ('file' in rewriteRule) {
37
+ const file = await promises_1.default.readFile(path_1.default.resolve(rewriteRule.file));
38
+ proxyRes.rawBody = await (0, http_encoding_1.encodeBuffer)(file, encoding);
39
+ if (rewriteRule.statusCode) {
40
+ proxyRes.statusCode = rewriteRule.statusCode;
41
+ }
42
+ this.logger.info(`rewrite ${proxyRes.statusCode} ${req.method} ${req.url}`);
43
+ next();
44
+ return;
45
+ }
46
+ next();
47
+ }
48
+ catch (e) {
49
+ this.logger.error(e);
50
+ next();
51
+ }
52
+ }
53
+ }
54
+ exports.RewriteMiddleware = RewriteMiddleware;
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" />
2
+ import { ServerResponse, IncomingMessage } from 'http';
3
+ import { Config } from '../services/config.service';
4
+ import { Middleware } from '../services/pipeline.service';
5
+ import { LoggerService } from '../services/logger.service';
6
+ export declare class StaticMiddleware implements Middleware<[req: IncomingMessage, res: ServerResponse]> {
7
+ private config;
8
+ private logger;
9
+ constructor(config: Config, logger: LoggerService);
10
+ use(req: IncomingMessage, res: ServerResponse, next: () => void): Promise<void>;
11
+ private readdir;
12
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StaticMiddleware = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const mime_1 = __importDefault(require("mime"));
10
+ class StaticMiddleware {
11
+ constructor(config, logger) {
12
+ this.config = config;
13
+ this.logger = logger;
14
+ }
15
+ async use(req, res, next) {
16
+ try {
17
+ const staticRules = this.config.get().staticRules || [];
18
+ const url = new URL(req.url || '', 'http://fake.com');
19
+ const urlPath = url.pathname;
20
+ if (!staticRules) {
21
+ next();
22
+ return;
23
+ }
24
+ const currentStaticRule = staticRules.filter((staticRule) => {
25
+ return urlPath.startsWith(staticRule.path);
26
+ })[0];
27
+ if (!currentStaticRule) {
28
+ next();
29
+ return;
30
+ }
31
+ const pathToDirectory = path_1.default.resolve(currentStaticRule.directory);
32
+ const dirents = await this.readdir(pathToDirectory);
33
+ const filePath = dirents
34
+ .filter(dirent => !dirent.isDirectory())
35
+ .map(dirent => ({
36
+ urlPath: path_1.default.join(currentStaticRule.path, path_1.default.join(dirent.path, dirent.name).replace(pathToDirectory, '')).replace(/\\/g, '/'),
37
+ path: path_1.default.join(dirent.path, dirent.name).replace(/\\/g, '/'),
38
+ }))
39
+ .filter(dirent => {
40
+ const pathname = path_1.default.extname(urlPath)
41
+ ? urlPath
42
+ : path_1.default.join(urlPath, currentStaticRule.directoryIndex || '').replace(/\\/g, '/');
43
+ if (currentStaticRule.caseInsensitive) {
44
+ return dirent.urlPath.toLocaleLowerCase() === pathname.toLowerCase();
45
+ }
46
+ else {
47
+ return dirent.urlPath === pathname;
48
+ }
49
+ })
50
+ .map(dirent => dirent.path)[0];
51
+ if (!filePath) {
52
+ next();
53
+ return;
54
+ }
55
+ const file = await promises_1.default.readFile(path_1.default.resolve(filePath));
56
+ const mimeType = mime_1.default.getType(path_1.default.resolve(filePath));
57
+ if (mimeType) {
58
+ res.setHeader('content-type', mimeType);
59
+ }
60
+ res.setHeader('content-length', file.length);
61
+ res.end(file);
62
+ this.logger.info(`static ${res.statusCode} ${req.method} ${req.url}`);
63
+ }
64
+ catch (e) {
65
+ this.logger.error(e);
66
+ next();
67
+ }
68
+ }
69
+ async readdir(pathname, subpathname) {
70
+ const files = [];
71
+ const fullpath = path_1.default.join(pathname, subpathname || '');
72
+ const dirents = await promises_1.default.readdir(fullpath, {
73
+ withFileTypes: true,
74
+ });
75
+ for (let dirent of dirents) {
76
+ dirent.path = fullpath;
77
+ files.push(dirent);
78
+ if (dirent.isDirectory()) {
79
+ files.push(...await this.readdir(fullpath, dirent.name));
80
+ }
81
+ }
82
+ return files;
83
+ }
84
+ }
85
+ exports.StaticMiddleware = StaticMiddleware;
@@ -0,0 +1,6 @@
1
+ import { ConfigFile } from '../types/yxorp-config';
2
+ export interface ResolvedConfig {
3
+ configDir: string;
4
+ config: ConfigFile;
5
+ }
6
+ export declare function resolveConfig(cwd: string, argv: string[]): ResolvedConfig;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveConfig = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ function resolveConfig(cwd, argv) {
10
+ // Parse --config CLI argument
11
+ const configArgIndex = argv.indexOf('--config');
12
+ let configFile;
13
+ if (configArgIndex !== -1 && configArgIndex + 1 < argv.length) {
14
+ configFile = argv[configArgIndex + 1];
15
+ }
16
+ if (configFile) {
17
+ const resolved = path_1.default.resolve(cwd, configFile);
18
+ if (!fs_1.default.existsSync(resolved)) {
19
+ throw new Error(`Config file not found: ${configFile}`);
20
+ }
21
+ return {
22
+ configDir: path_1.default.dirname(resolved),
23
+ config: JSON.parse(fs_1.default.readFileSync(resolved, 'utf-8')),
24
+ };
25
+ }
26
+ // Default: look for config in order of preference
27
+ const rootConfig = path_1.default.join(cwd, 'yxorp.json');
28
+ if (fs_1.default.existsSync(rootConfig)) {
29
+ return {
30
+ configDir: cwd,
31
+ config: JSON.parse(fs_1.default.readFileSync(rootConfig, 'utf-8')),
32
+ };
33
+ }
34
+ const dotDir = path_1.default.join(cwd, '.yxorp');
35
+ const dotConfig = path_1.default.join(dotDir, 'settings.json');
36
+ if (fs_1.default.existsSync(dotConfig)) {
37
+ return {
38
+ configDir: dotDir,
39
+ config: JSON.parse(fs_1.default.readFileSync(dotConfig, 'utf-8')),
40
+ };
41
+ }
42
+ throw new Error('Config file not found. Create yxorp.json or .yxorp/settings.json in the current directory, ' +
43
+ 'or use --config <path> to specify a config file.');
44
+ }
45
+ exports.resolveConfig = resolveConfig;
@@ -0,0 +1,6 @@
1
+ import { YxorpConfig } from '../types/yxorp-config';
2
+ export declare class Config {
3
+ private config;
4
+ set(config: YxorpConfig): void;
5
+ get(): YxorpConfig;
6
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Config = void 0;
4
+ class Config {
5
+ set(config) {
6
+ this.config = config;
7
+ }
8
+ get() {
9
+ return this.config;
10
+ }
11
+ }
12
+ exports.Config = Config;
@@ -0,0 +1,14 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ /// <reference types="node" />
4
+ import { IncomingMessage, ServerResponse } from 'http';
5
+ import { Pipeline } from './pipeline.service';
6
+ export declare class HttpProxy {
7
+ private pipeline;
8
+ readonly on: (...args: any[]) => any;
9
+ private proxy;
10
+ constructor(pipeline: Pipeline<[proxyRes: IncomingMessage, req: IncomingMessage, res: ServerResponse]>);
11
+ execute: (args_0: IncomingMessage, args_1: IncomingMessage, args_2: ServerResponse<IncomingMessage>) => Promise<void>;
12
+ web(req: IncomingMessage, res: ServerResponse, options?: Record<string, any>): any;
13
+ ws(req: IncomingMessage, socket: any, options: Record<string, any>, head?: Buffer): any;
14
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpProxy = void 0;
4
+ const httpxy_1 = require("httpxy");
5
+ class HttpProxy {
6
+ constructor(pipeline) {
7
+ this.pipeline = pipeline;
8
+ this.execute = (...args) => this.pipeline.execute(...args);
9
+ this.proxy = (0, httpxy_1.createProxyServer)({});
10
+ this.on = this.proxy.on.bind(this.proxy);
11
+ }
12
+ web(req, res, options) {
13
+ return this.proxy.web(req, res, options);
14
+ }
15
+ ws(req, socket, options, head) {
16
+ return this.proxy.ws(req, socket, options, head);
17
+ }
18
+ }
19
+ exports.HttpProxy = HttpProxy;
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage, Server, ServerResponse } from 'http';
3
+ import { Pipeline } from './pipeline.service';
4
+ export declare class HttpServer {
5
+ private pipeline;
6
+ readonly use: Pipeline<[IncomingMessage, ServerResponse]>['use'];
7
+ readonly on: Server['on'];
8
+ readonly addListener: Server['addListener'];
9
+ readonly removeListener: Server['removeListener'];
10
+ readonly listen: Server['listen'];
11
+ readonly close: Server['close'];
12
+ readonly address: Server['address'];
13
+ private readonly server;
14
+ constructor(pipeline: Pipeline<[req: IncomingMessage, res: ServerResponse]>);
15
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HttpServer = void 0;
7
+ const http_1 = __importDefault(require("http"));
8
+ class HttpServer {
9
+ constructor(pipeline) {
10
+ this.pipeline = pipeline;
11
+ this.server = http_1.default.createServer((req, res) => {
12
+ this.pipeline.execute(req, res);
13
+ });
14
+ this.use = this.pipeline.use.bind(this.pipeline);
15
+ this.on = this.server.on.bind(this.server);
16
+ this.addListener = this.server.addListener.bind(this.server);
17
+ this.removeListener = this.server.removeListener.bind(this.server);
18
+ this.listen = this.server.listen.bind(this.server);
19
+ this.close = this.server.close.bind(this.server);
20
+ this.address = this.server.address.bind(this.server);
21
+ }
22
+ }
23
+ exports.HttpServer = HttpServer;
@@ -0,0 +1,7 @@
1
+ export declare class LoggerService {
2
+ private logger;
3
+ info: import("winston").LeveledLogMethod;
4
+ error: import("winston").LeveledLogMethod;
5
+ warn: import("winston").LeveledLogMethod;
6
+ debug: import("winston").LeveledLogMethod;
7
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoggerService = void 0;
4
+ const winston_1 = require("winston");
5
+ class LoggerService {
6
+ constructor() {
7
+ this.logger = (0, winston_1.createLogger)({
8
+ format: winston_1.format.combine(winston_1.format.colorize(), winston_1.format.simple()),
9
+ transports: [new winston_1.transports.Console],
10
+ });
11
+ this.info = this.logger.info.bind(this.logger);
12
+ this.error = this.logger.error.bind(this.logger);
13
+ this.warn = this.logger.warn.bind(this.logger);
14
+ this.debug = this.logger.debug.bind(this.logger);
15
+ }
16
+ }
17
+ exports.LoggerService = LoggerService;
@@ -0,0 +1,8 @@
1
+ export interface Middleware<T extends any[]> {
2
+ use(...args: [...T, () => void]): void | Promise<void>;
3
+ }
4
+ export declare class Pipeline<T extends any[]> {
5
+ private stack;
6
+ use(...middlewares: Middleware<T>[]): void;
7
+ execute(...args: [...T]): Promise<void>;
8
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Pipeline = void 0;
4
+ class Pipeline {
5
+ constructor() {
6
+ this.stack = [];
7
+ }
8
+ use(...middlewares) {
9
+ this.stack.push(...middlewares);
10
+ }
11
+ async execute(...args) {
12
+ let prevIndex = -1;
13
+ const runner = async (index) => {
14
+ if (index === prevIndex) {
15
+ throw new Error('next() called multiple times');
16
+ }
17
+ prevIndex = index;
18
+ const middleware = this.stack[index];
19
+ if (!middleware) {
20
+ return;
21
+ }
22
+ await middleware.use(...args, () => {
23
+ return runner(index + 1);
24
+ });
25
+ };
26
+ await runner(0);
27
+ }
28
+ }
29
+ exports.Pipeline = Pipeline;
@@ -0,0 +1,8 @@
1
+ import { Config } from '../config.service';
2
+ import { MockRule } from '../../types/yxorp-config';
3
+ export declare class MockRulesMatcher {
4
+ private config;
5
+ constructor(config: Config);
6
+ match(url: string, method: string): MockRule | undefined;
7
+ params(url: string, mockRule: MockRule): Object | undefined;
8
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MockRulesMatcher = void 0;
4
+ const path_to_regexp_1 = require("path-to-regexp");
5
+ class MockRulesMatcher {
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ match(url, method) {
10
+ const mockRules = this.config.get().mockRules || [];
11
+ for (let mockRule of mockRules) {
12
+ if (mockRule.disable) {
13
+ continue;
14
+ }
15
+ if (mockRule.method.toLowerCase() !== method.toLowerCase()) {
16
+ continue;
17
+ }
18
+ const matchResult = (0, path_to_regexp_1.match)(mockRule.path, {
19
+ decode: decodeURIComponent,
20
+ })(url);
21
+ if (matchResult) {
22
+ return mockRule;
23
+ }
24
+ }
25
+ }
26
+ params(url, mockRule) {
27
+ const matchResult = (0, path_to_regexp_1.match)(mockRule.path, {
28
+ decode: decodeURIComponent,
29
+ })(url);
30
+ if (matchResult) {
31
+ return matchResult.params;
32
+ }
33
+ }
34
+ }
35
+ exports.MockRulesMatcher = MockRulesMatcher;
@@ -0,0 +1,8 @@
1
+ import { Config } from '../config.service';
2
+ import { RemoteRule } from '../../types/yxorp-config';
3
+ export declare class RemoteRulesMatcher {
4
+ private config;
5
+ constructor(config: Config);
6
+ match(url: string, ws?: boolean): RemoteRule | undefined;
7
+ toPath(url: string, remoteRule: RemoteRule): string | undefined;
8
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RemoteRulesMatcher = void 0;
4
+ const path_to_regexp_1 = require("path-to-regexp");
5
+ class RemoteRulesMatcher {
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ match(url, ws = false) {
10
+ const rules = this.config.get().remoteRules || [];
11
+ for (let rule of rules) {
12
+ if (rule.disable) {
13
+ continue;
14
+ }
15
+ if (!!rule.ws !== ws) {
16
+ continue;
17
+ }
18
+ const matchResult = (0, path_to_regexp_1.match)(rule.path, {
19
+ decode: decodeURIComponent
20
+ })(url);
21
+ if (matchResult) {
22
+ return rule;
23
+ }
24
+ }
25
+ }
26
+ toPath(url, remoteRule) {
27
+ const matchResult = (0, path_to_regexp_1.match)(remoteRule.path, {
28
+ decode: decodeURIComponent
29
+ })(url);
30
+ if (matchResult) {
31
+ const params = matchResult.params;
32
+ // remoteRule.target may be a full URL (http://host:port/:param/path)
33
+ // Parse it and only compile the path portion
34
+ let baseUrl;
35
+ let pathPattern;
36
+ try {
37
+ const urlObj = new URL(remoteRule.target);
38
+ baseUrl = urlObj.origin;
39
+ pathPattern = urlObj.pathname;
40
+ }
41
+ catch {
42
+ // Not a valid URL — treat as a path pattern
43
+ const toPath = (0, path_to_regexp_1.compile)(remoteRule.target);
44
+ return toPath(matchResult.params);
45
+ }
46
+ const toPath = (0, path_to_regexp_1.compile)(pathPattern);
47
+ return baseUrl + toPath(params);
48
+ }
49
+ }
50
+ }
51
+ exports.RemoteRulesMatcher = RemoteRulesMatcher;