yxorp 0.2.0 → 0.2.1

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.
package/README.md CHANGED
@@ -341,7 +341,15 @@ Here's a complete config showing all features in action:
341
341
 
342
342
  ---
343
343
 
344
- ## Script Hot-Reload
344
+ ## Hot-Reload
345
+
346
+ ### Config
347
+
348
+ Yxorp watches its config file at runtime. **Save the file — changes take effect on the next request.** No restart needed.
349
+
350
+ This works for all config fields: mock rules, rewrite rules, remote rules, static rules, and headers. The proxy server keeps running and the new config is applied immediately.
351
+
352
+ ### Scripts
345
353
 
346
354
  Mock and rewrite scripts are reloaded on every request — **just save the file and the next request uses the new code**. No need to restart Yxorp.
347
355
 
package/dist/index.js CHANGED
@@ -12,12 +12,15 @@ const rewrite_rules_matcher_service_1 = require("./services/rules-matchers/rewri
12
12
  const mock_rules_matcher_service_1 = require("./services/rules-matchers/mock-rules-matcher.service");
13
13
  const yxorp_server_service_1 = require("./services/yxorp-server.service");
14
14
  const config_resolver_1 = require("./services/config-resolver");
15
+ const config_watcher_1 = require("./services/config-watcher");
15
16
  // --- Config resolution ---
16
17
  let configDir;
18
+ let configPath;
17
19
  let config;
18
20
  try {
19
21
  const resolved = (0, config_resolver_1.resolveConfig)(process.cwd(), process.argv);
20
22
  configDir = resolved.configDir;
23
+ configPath = resolved.configPath;
21
24
  config = resolved.config;
22
25
  }
23
26
  catch (e) {
@@ -28,28 +31,27 @@ catch (e) {
28
31
  if (configDir !== process.cwd()) {
29
32
  process.chdir(configDir);
30
33
  }
31
- const proxyOptions = {
32
- target: config.target,
33
- changeOrigin: true,
34
- followRedirects: true,
35
- secure: false,
36
- ws: true,
37
- selfHandleResponse: true,
38
- };
39
- if (config.proxyHeaders) {
40
- proxyOptions.headers = config.proxyHeaders;
34
+ function buildProxyConfig(cfg) {
35
+ const proxyOptions = {
36
+ target: cfg.target,
37
+ changeOrigin: true,
38
+ followRedirects: true,
39
+ secure: false,
40
+ ws: true,
41
+ selfHandleResponse: true,
42
+ };
43
+ if (cfg.proxyHeaders) {
44
+ proxyOptions.headers = cfg.proxyHeaders;
45
+ }
46
+ return { ...cfg, proxyOptions };
41
47
  }
42
- const proxyConfig = {
43
- ...config,
44
- proxyOptions,
45
- };
46
48
  (_a = config === null || config === void 0 ? void 0 : config.scripts) === null || _a === void 0 ? void 0 : _a.forEach(script => {
47
49
  require(path_1.default.resolve(script));
48
50
  });
49
51
  // Manual composition — no DI container
50
52
  const logger = new logger_service_1.LoggerService();
51
53
  const appConfig = new config_service_1.Config();
52
- appConfig.set(proxyConfig);
54
+ appConfig.set(buildProxyConfig(config));
53
55
  const mockRulesMatcher = new mock_rules_matcher_service_1.MockRulesMatcher(appConfig);
54
56
  const rewriteRulesMatcher = new rewrite_rules_matcher_service_1.RewriteRulesMatcher(appConfig);
55
57
  const remoteRulesMatcher = new remote_rules_matcher_service_1.RemoteRulesMatcher(appConfig);
@@ -57,3 +59,8 @@ const { listen } = (0, yxorp_server_service_1.createServer)(appConfig, logger, r
57
59
  listen(config.proxyPort, () => {
58
60
  console.log(`Yxorp server started successfully on http://localhost:${config.proxyPort}`);
59
61
  });
62
+ // --- Config hot-reload ---
63
+ (0, config_watcher_1.watchConfig)(configPath, (newConfig) => {
64
+ appConfig.set(buildProxyConfig(newConfig));
65
+ logger.info('Config reloaded');
66
+ }, (e) => logger.error(`Config reload failed: ${e.message || e}`));
@@ -1,6 +1,7 @@
1
1
  import { ConfigFile } from '../types/yxorp-config';
2
2
  export interface ResolvedConfig {
3
3
  configDir: string;
4
+ configPath: string;
4
5
  config: ConfigFile;
5
6
  }
6
7
  export declare function resolveConfig(cwd: string, argv: string[]): ResolvedConfig;
@@ -20,6 +20,7 @@ function resolveConfig(cwd, argv) {
20
20
  }
21
21
  return {
22
22
  configDir: path_1.default.dirname(resolved),
23
+ configPath: resolved,
23
24
  config: JSON.parse(fs_1.default.readFileSync(resolved, 'utf-8')),
24
25
  };
25
26
  }
@@ -28,6 +29,7 @@ function resolveConfig(cwd, argv) {
28
29
  if (fs_1.default.existsSync(rootConfig)) {
29
30
  return {
30
31
  configDir: cwd,
32
+ configPath: rootConfig,
31
33
  config: JSON.parse(fs_1.default.readFileSync(rootConfig, 'utf-8')),
32
34
  };
33
35
  }
@@ -36,6 +38,7 @@ function resolveConfig(cwd, argv) {
36
38
  if (fs_1.default.existsSync(dotConfig)) {
37
39
  return {
38
40
  configDir: dotDir,
41
+ configPath: dotConfig,
39
42
  config: JSON.parse(fs_1.default.readFileSync(dotConfig, 'utf-8')),
40
43
  };
41
44
  }
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ import fs from 'fs';
3
+ import { ConfigFile } from '../types/yxorp-config';
4
+ export declare function watchConfig(configPath: string, onReload: (config: ConfigFile) => void, onError: (err: unknown) => void): fs.FSWatcher;
@@ -0,0 +1,27 @@
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.watchConfig = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ function watchConfig(configPath, onReload, onError) {
9
+ let debounceTimer = null;
10
+ return fs_1.default.watch(configPath, () => {
11
+ if (debounceTimer)
12
+ return;
13
+ debounceTimer = setTimeout(() => {
14
+ debounceTimer = null;
15
+ try {
16
+ const raw = fs_1.default.readFileSync(configPath, 'utf-8');
17
+ if (!raw.trim())
18
+ return;
19
+ onReload(JSON.parse(raw));
20
+ }
21
+ catch (e) {
22
+ onError(e);
23
+ }
24
+ }, 100);
25
+ });
26
+ }
27
+ exports.watchConfig = watchConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yxorp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A local reverse proxy for rewriting, mocking, and debugging API responses.",
5
5
  "files": [
6
6
  "dist/",