ninja-reverse-proxy 1.0.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 (47) hide show
  1. package/README.md +480 -0
  2. package/config.example.yaml +99 -0
  3. package/dist/Serviceregistry.d.ts +31 -0
  4. package/dist/Serviceregistry.d.ts.map +1 -0
  5. package/dist/Serviceregistry.js +95 -0
  6. package/dist/Serviceregistry.js.map +1 -0
  7. package/dist/auto-scaler.d.ts +27 -0
  8. package/dist/auto-scaler.d.ts.map +1 -0
  9. package/dist/auto-scaler.js +133 -0
  10. package/dist/auto-scaler.js.map +1 -0
  11. package/dist/cache.d.ts +22 -0
  12. package/dist/cache.d.ts.map +1 -0
  13. package/dist/cache.js +112 -0
  14. package/dist/cache.js.map +1 -0
  15. package/dist/config-schema.d.ts +52 -0
  16. package/dist/config-schema.d.ts.map +1 -0
  17. package/dist/config-schema.js +77 -0
  18. package/dist/config-schema.js.map +1 -0
  19. package/dist/config.d.ts +46 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +73 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/health.d.ts +5 -0
  24. package/dist/health.d.ts.map +1 -0
  25. package/dist/health.js +78 -0
  26. package/dist/health.js.map +1 -0
  27. package/dist/index.d.ts +3 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +63 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/loadBalancer.d.ts +31 -0
  32. package/dist/loadBalancer.d.ts.map +1 -0
  33. package/dist/loadBalancer.js +158 -0
  34. package/dist/loadBalancer.js.map +1 -0
  35. package/dist/rate-limiter.d.ts +16 -0
  36. package/dist/rate-limiter.d.ts.map +1 -0
  37. package/dist/rate-limiter.js +59 -0
  38. package/dist/rate-limiter.js.map +1 -0
  39. package/dist/server-schema.d.ts +25 -0
  40. package/dist/server-schema.d.ts.map +1 -0
  41. package/dist/server-schema.js +18 -0
  42. package/dist/server-schema.js.map +1 -0
  43. package/dist/server.d.ts +10 -0
  44. package/dist/server.d.ts.map +1 -0
  45. package/dist/server.js +518 -0
  46. package/dist/server.js.map +1 -0
  47. package/package.json +39 -0
package/dist/health.js ADDED
@@ -0,0 +1,78 @@
1
+ import http from "http";
2
+ import { LoadBalancer } from "./loadBalancer.js";
3
+ // Initial health check
4
+ export async function initialHealthCheck(upstreams, HEALTHY_UPSTREAMS) {
5
+ console.log(`Initial health check`);
6
+ for (const upstream of upstreams) {
7
+ await new Promise((resolve) => {
8
+ const upstreamUrl = new URL(upstream.url);
9
+ const req = http.request({
10
+ host: upstreamUrl.hostname,
11
+ port: upstreamUrl.port,
12
+ path: "/health",
13
+ method: "GET",
14
+ }, (initialRes) => {
15
+ if (initialRes.statusCode === 200) {
16
+ console.log(`${upstream.id} is HEALTHY`);
17
+ HEALTHY_UPSTREAMS.add(upstream.id);
18
+ }
19
+ else {
20
+ console.log(`${upstream.id} is NOT HEALTHY`);
21
+ HEALTHY_UPSTREAMS.delete(upstream.id);
22
+ }
23
+ resolve();
24
+ });
25
+ req.on("error", () => {
26
+ console.log(`Some Error Occured`);
27
+ console.log(`${upstream.id} is NOT HEALTHY`);
28
+ HEALTHY_UPSTREAMS.delete(upstream.id);
29
+ resolve();
30
+ });
31
+ req.end();
32
+ });
33
+ }
34
+ console.log(`Initial Health Check Done!`);
35
+ console.log(`Healthy Upstreams: ${[...HEALTHY_UPSTREAMS].join(", ")}`);
36
+ }
37
+ // before reverse Proxy health check
38
+ export async function startHealthChecks(upstreams, HEALTHY_UPSTREAMS, lb) {
39
+ console.log(`Check for health check before server response`);
40
+ setInterval(() => {
41
+ console.log(`\n[HealthCheck] Checking all upstreams...`);
42
+ for (const upstream of upstreams) {
43
+ const upstreamUrl = new URL(upstream.url);
44
+ const req = http.request({
45
+ host: upstreamUrl.hostname,
46
+ port: upstreamUrl.port,
47
+ path: "/health",
48
+ method: "GET",
49
+ }, (HealthRes) => {
50
+ if (HealthRes.statusCode === 200) {
51
+ lb.recordSuccess(upstream.id);
52
+ if (!HEALTHY_UPSTREAMS.has(upstream.id)) {
53
+ HEALTHY_UPSTREAMS.add(upstream.id);
54
+ if (!lb.hasUpstream(upstream.id)) {
55
+ lb.addUpstream(upstream.id);
56
+ }
57
+ console.log(`${upstream.id} is back ONLINE!`);
58
+ }
59
+ else {
60
+ console.log(`${upstream.id} is HEALTHY`);
61
+ }
62
+ }
63
+ else {
64
+ lb.recordFailure(upstream.id);
65
+ HEALTHY_UPSTREAMS.delete(upstream.id);
66
+ console.log(`${upstream.id} is DOWN!`);
67
+ }
68
+ });
69
+ req.on('error', () => {
70
+ lb.recordFailure(upstream.id);
71
+ HEALTHY_UPSTREAMS.delete(upstream.id);
72
+ console.log(`${upstream.id} is DOWN! (connection refused)`);
73
+ });
74
+ req.end();
75
+ }
76
+ }, 10000);
77
+ }
78
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../src/health.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,63 @@
1
+ #!/usr/bin/env node
2
+ import { program } from "commander";
3
+ import { parseYAMLConfig, validateConfig } from "./config.js";
4
+ import os from "node:os";
5
+ import { createServer, reloadServerConfig } from "./server.js";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ async function main() {
9
+ program.option("--config <path>");
10
+ program.parse();
11
+ const options = program.opts();
12
+ if (options && "config" in options) {
13
+ const configPath = options.config;
14
+ const validatedConfig = await validateConfig(await parseYAMLConfig(configPath));
15
+ process.on("SIGHUP", async () => {
16
+ console.log("\n[Master] SIGHUP received — reloading configuration...");
17
+ try {
18
+ const rawConfig = await parseYAMLConfig(configPath);
19
+ const newConfig = await validateConfig(rawConfig);
20
+ await reloadServerConfig(newConfig);
21
+ console.log("[Master] Configuration reloaded successfully!");
22
+ }
23
+ catch (err) {
24
+ console.error(`[Master] Reload failed! Keeping old config. Error: ${err.message}`);
25
+ }
26
+ });
27
+ console.log(validatedConfig);
28
+ await createServer({
29
+ port: validatedConfig.server.listen,
30
+ workerCount: validatedConfig.server.workers ?? os.cpus().length,
31
+ config: validatedConfig,
32
+ });
33
+ // --- Automatic File Watcher Hot-Reload ---
34
+ let watchDebounceTimer;
35
+ const triggerReload = () => {
36
+ clearTimeout(watchDebounceTimer);
37
+ watchDebounceTimer = setTimeout(async () => {
38
+ try {
39
+ const rawConfig = await parseYAMLConfig(configPath);
40
+ const newConfig = await validateConfig(rawConfig);
41
+ await reloadServerConfig(newConfig);
42
+ console.log("[Master] Configuration reloaded automatically!");
43
+ }
44
+ catch (err) {
45
+ console.error(`[Master] Auto-reload failed: ${err.message}`);
46
+ }
47
+ }, 100); // 100ms
48
+ };
49
+ fs.watch(configPath, (eventType) => {
50
+ if (eventType === "change") {
51
+ triggerReload();
52
+ }
53
+ });
54
+ const configDir = path.join(path.dirname(configPath), "config.d");
55
+ if (fs.existsSync(configDir)) {
56
+ fs.watch(configDir, (eventType) => {
57
+ triggerReload();
58
+ });
59
+ }
60
+ }
61
+ }
62
+ main();
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export type LBStrategy = "round-robin" | "least-connections" | "ip-hash" | "random";
2
+ interface LoadBalancerConfig {
3
+ strategy: LBStrategy;
4
+ upstreams: Array<{
5
+ id: string;
6
+ weight?: number;
7
+ }>;
8
+ failureThreshold?: number;
9
+ recoveryTimeMs?: number;
10
+ }
11
+ export declare class LoadBalancer {
12
+ private states;
13
+ private strategy;
14
+ private rrIndex;
15
+ private failureThreshold;
16
+ private recoveryTimeMs;
17
+ private staticWeights;
18
+ constructor(config: LoadBalancerConfig);
19
+ addUpstream(id: string, weight?: number): void;
20
+ removeUpstream(id: string): void;
21
+ hasUpstream(id: string): boolean;
22
+ recordSuccess(id: string): void;
23
+ recordFailure(id: string): void;
24
+ private getAvailable;
25
+ pick(healthyIds: Set<string>, clientIp?: string): string | null;
26
+ pickFiltered(healthyIds: Set<string>, clientIp?: string, attemptedUpstreams?: Set<string>): string | null;
27
+ private hashIp;
28
+ getStats(): Record<string, object>;
29
+ }
30
+ export {};
31
+ //# sourceMappingURL=loadBalancer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadBalancer.d.ts","sourceRoot":"","sources":["../src/loadBalancer.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,mBAAmB,GACnB,SAAS,GACT,QAAQ,CAAC;AAab,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,UAAU,CAAC;IACrB,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAyC;IACvD,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAkC;gBAE3C,MAAM,EAAE,kBAAkB;IAqBtC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,IAAI;IAezC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKhC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIhC,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAW/B,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAc/B,OAAO,CAAC,YAAY;IAiBpB,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI/D,YAAY,CACV,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,QAAQ,CAAC,EAAE,MAAM,EACjB,kBAAkB,GAAE,GAAG,CAAC,MAAM,CAAa,GAC1C,MAAM,GAAG,IAAI;IA+ChB,OAAO,CAAC,MAAM;IAQd,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAanC"}
@@ -0,0 +1,158 @@
1
+ export class LoadBalancer {
2
+ states = new Map();
3
+ strategy;
4
+ rrIndex = 0;
5
+ failureThreshold;
6
+ recoveryTimeMs;
7
+ staticWeights = new Map();
8
+ constructor(config) {
9
+ this.strategy = config.strategy;
10
+ this.failureThreshold = config.failureThreshold ?? 3;
11
+ this.recoveryTimeMs = config.recoveryTimeMs ?? 15000;
12
+ for (const u of config.upstreams) {
13
+ const weight = u.weight ?? 1;
14
+ this.staticWeights.set(u.id, weight);
15
+ this.states.set(u.id, {
16
+ id: u.id,
17
+ activeConnections: 0,
18
+ failures: 0,
19
+ lastFailureTime: 0,
20
+ state: "CLOSED",
21
+ weight: weight,
22
+ currentWeight: 0,
23
+ effectiveWeight: weight,
24
+ });
25
+ }
26
+ }
27
+ addUpstream(id, weight = 1) {
28
+ if (this.states.has(id))
29
+ return;
30
+ this.staticWeights.set(id, weight);
31
+ this.states.set(id, {
32
+ id,
33
+ activeConnections: 0,
34
+ failures: 0,
35
+ lastFailureTime: 0,
36
+ state: "CLOSED",
37
+ weight: weight,
38
+ currentWeight: 0,
39
+ effectiveWeight: weight,
40
+ });
41
+ }
42
+ removeUpstream(id) {
43
+ this.states.delete(id);
44
+ this.staticWeights.delete(id);
45
+ }
46
+ hasUpstream(id) {
47
+ return this.states.has(id);
48
+ }
49
+ recordSuccess(id) {
50
+ const s = this.states.get(id);
51
+ if (!s)
52
+ return;
53
+ s.failures = 0;
54
+ s.state = "CLOSED";
55
+ if (s.effectiveWeight < s.weight) {
56
+ s.effectiveWeight++;
57
+ }
58
+ if (s.activeConnections > 0)
59
+ s.activeConnections--;
60
+ }
61
+ recordFailure(id) {
62
+ const s = this.states.get(id);
63
+ if (!s)
64
+ return;
65
+ s.failures++;
66
+ s.lastFailureTime = Date.now();
67
+ if (s.effectiveWeight > 1) {
68
+ s.effectiveWeight--;
69
+ }
70
+ if (s.activeConnections > 0)
71
+ s.activeConnections--;
72
+ if (s.failures >= this.failureThreshold) {
73
+ s.state = "OPEN";
74
+ }
75
+ }
76
+ getAvailable(healthyIds) {
77
+ const now = Date.now();
78
+ const available = [];
79
+ for (const [, s] of this.states) {
80
+ if (!healthyIds.has(s.id))
81
+ continue;
82
+ if (s.state === "OPEN") {
83
+ if (now - s.lastFailureTime >= this.recoveryTimeMs) {
84
+ s.state = "HALF_OPEN";
85
+ available.push(s);
86
+ }
87
+ continue;
88
+ }
89
+ available.push(s);
90
+ }
91
+ return available;
92
+ }
93
+ pick(healthyIds, clientIp) {
94
+ return this.pickFiltered(healthyIds, clientIp, new Set());
95
+ }
96
+ pickFiltered(healthyIds, clientIp, attemptedUpstreams = new Set()) {
97
+ const allAvailable = this.getAvailable(healthyIds);
98
+ const available = allAvailable.filter((s) => !attemptedUpstreams.has(s.id));
99
+ if (available.length === 0)
100
+ return null;
101
+ let chosen = available[0];
102
+ switch (this.strategy) {
103
+ case "least-connections": {
104
+ chosen = available.reduce((a, b) => a.activeConnections <= b.activeConnections ? a : b);
105
+ break;
106
+ }
107
+ case "ip-hash": {
108
+ const hash = this.hashIp(clientIp ?? "0.0.0.0");
109
+ chosen = available[hash % available.length];
110
+ break;
111
+ }
112
+ case "random": {
113
+ chosen = available[Math.floor(Math.random() * available.length)];
114
+ break;
115
+ }
116
+ case "round-robin":
117
+ default: {
118
+ let totalEffectiveWeight = 0;
119
+ let best = null;
120
+ for (const s of available) {
121
+ s.currentWeight += s.effectiveWeight;
122
+ totalEffectiveWeight += s.effectiveWeight;
123
+ if (!best || s.currentWeight > best.currentWeight) {
124
+ best = s;
125
+ }
126
+ }
127
+ if (best) {
128
+ best.currentWeight -= totalEffectiveWeight;
129
+ chosen = best;
130
+ }
131
+ break;
132
+ }
133
+ }
134
+ chosen.activeConnections++;
135
+ return chosen.id;
136
+ }
137
+ hashIp(ip) {
138
+ let hash = 5381;
139
+ for (let i = 0; i < ip.length; i++) {
140
+ hash = (hash * 33) ^ ip.charCodeAt(i);
141
+ }
142
+ return Math.abs(hash);
143
+ }
144
+ getStats() {
145
+ const out = {};
146
+ for (const [id, s] of this.states) {
147
+ out[id] = {
148
+ state: s.state,
149
+ activeConnections: s.activeConnections,
150
+ failures: s.failures,
151
+ weight: s.weight,
152
+ effectiveWeight: s.effectiveWeight,
153
+ };
154
+ }
155
+ return out;
156
+ }
157
+ }
158
+ //# sourceMappingURL=loadBalancer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadBalancer.js","sourceRoot":"","sources":["../src/loadBalancer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ interface RateLimitConfig {
2
+ windowMs: number;
3
+ maxRequests: number;
4
+ }
5
+ export declare class RateLimiter {
6
+ private ipMap;
7
+ private windowMs;
8
+ private maxRequests;
9
+ constructor(config: RateLimitConfig);
10
+ isAllowed(ip: string): boolean;
11
+ getRemainingRequests(ip: string): number;
12
+ getResetTime(ip: string): number;
13
+ private cleanup;
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AACA,UAAU,eAAe;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,WAAW;IACpB,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;gBAChB,MAAM,EAAE,eAAe;IAOnC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAuB9B,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAKxC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAKhC,OAAO,CAAC,OAAO;CAWlB"}
@@ -0,0 +1,59 @@
1
+ export class RateLimiter {
2
+ ipMap = new Map();
3
+ windowMs;
4
+ maxRequests;
5
+ constructor(config) {
6
+ this.windowMs = config.windowMs;
7
+ this.maxRequests = config.maxRequests;
8
+ setInterval(() => {
9
+ this.cleanup();
10
+ }, config.windowMs);
11
+ }
12
+ isAllowed(ip) {
13
+ const now = Date.now();
14
+ const record = this.ipMap.get(ip);
15
+ if (!record) {
16
+ this.ipMap.set(ip, {
17
+ count: 1,
18
+ windowStart: now
19
+ });
20
+ return true;
21
+ }
22
+ if (now - record.windowStart > this.windowMs) {
23
+ this.ipMap.set(ip, {
24
+ count: 1,
25
+ windowStart: now
26
+ });
27
+ return true;
28
+ }
29
+ if (record.count >= this.maxRequests) {
30
+ return false;
31
+ }
32
+ record.count++;
33
+ return true;
34
+ }
35
+ getRemainingRequests(ip) {
36
+ const record = this.ipMap.get(ip);
37
+ if (!record)
38
+ return this.maxRequests;
39
+ return Math.max(0, this.maxRequests - record.count);
40
+ }
41
+ getResetTime(ip) {
42
+ const record = this.ipMap.get(ip);
43
+ if (!record)
44
+ return Date.now() + this.windowMs;
45
+ return record.windowStart + this.windowMs;
46
+ }
47
+ cleanup() {
48
+ const now = Date.now();
49
+ for (const [ip, record] of this.ipMap.entries()) {
50
+ // if the current time - time when window started is more than window running time so delete IP
51
+ if (now - record.windowStart > this.windowMs) {
52
+ this.ipMap.delete(ip);
53
+ }
54
+ }
55
+ // after cleaning previous dead IP , resulting Map with IP
56
+ console.log(`[RateLimiter] Cleaned up. Active IPs: ${this.ipMap.size}`);
57
+ }
58
+ }
59
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,WAAW;IACZ,KAAK,GAA+B,IAAI,GAAG,EAAE,CAAC;IAC9C,QAAQ,CAAS;IACjB,WAAW,CAAS;IAC5B,YAAY,MAAuB;QAC/B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,WAAW,CAAC,GAAG,EAAE;YACb,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC;IACD,SAAS,CAAC,EAAU;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;gBACf,KAAK,EAAE,CAAC;gBACR,WAAW,EAAE,GAAG;aACnB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,GAAG,GAAG,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE;gBACf,KAAK,EAAE,CAAC;gBACR,WAAW,EAAE,GAAG;aACnB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,oBAAoB,CAAC,EAAU;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,YAAY,CAAC,EAAU;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/C,OAAO,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC9C,CAAC;IACO,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,gGAAgG;YAC9F,IAAI,GAAG,GAAG,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,CAAC;QACL,CAAC;QACD,2DAA2D;QAC3D,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;CACJ"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ export declare const workerMessageSchema: z.ZodObject<{
3
+ requestType: z.ZodEnum<{
4
+ GET: "GET";
5
+ POST: "POST";
6
+ PUT: "PUT";
7
+ DELETE: "DELETE";
8
+ }>;
9
+ headers: z.ZodAny;
10
+ body: z.ZodNullable<z.ZodString>;
11
+ url: z.ZodString;
12
+ requestId: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>;
14
+ export declare const workerMessageReplySchema: z.ZodObject<{
15
+ requestId: z.ZodOptional<z.ZodString>;
16
+ data: z.ZodString;
17
+ error: z.ZodOptional<z.ZodString>;
18
+ errorCode: z.ZodOptional<z.ZodString>;
19
+ statusCode: z.ZodOptional<z.ZodNumber>;
20
+ isCompressed: z.ZodOptional<z.ZodBoolean>;
21
+ encoding: z.ZodOptional<z.ZodString>;
22
+ }, z.core.$strip>;
23
+ export type WorkerMessageType = z.infer<typeof workerMessageSchema>;
24
+ export type WorkerReplyMessageType = z.infer<typeof workerMessageReplySchema>;
25
+ //# sourceMappingURL=server-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-schema.d.ts","sourceRoot":"","sources":["../src/server-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,eAAO,MAAM,mBAAmB;;;;;;;;;;;iBAM9B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;iBAQnC,CAAC;AAGH,MAAM,MAAO,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACrE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export const workerMessageSchema = z.object({
3
+ requestType: z.enum(['GET', 'POST', 'PUT', 'DELETE']),
4
+ headers: z.any(),
5
+ body: z.string().nullable(),
6
+ url: z.string(),
7
+ requestId: z.string().optional()
8
+ });
9
+ export const workerMessageReplySchema = z.object({
10
+ requestId: z.string().optional(),
11
+ data: z.string(),
12
+ error: z.string().optional(),
13
+ errorCode: z.string().optional(),
14
+ statusCode: z.number().optional(),
15
+ isCompressed: z.boolean().optional(),
16
+ encoding: z.string().optional(),
17
+ });
18
+ //# sourceMappingURL=server-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-schema.js","sourceRoot":"","sources":["../src/server-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,WAAW,EAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACtD,OAAO,EAAI,CAAC,CAAC,GAAG,EAAE;IAClB,IAAI,EAAG,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,GAAG,EAAG,CAAC,CAAC,MAAM,EAAE;IAChB,SAAS,EAAG,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ConfigSchemaType } from "./config-schema.js";
2
+ interface CreateServerConfig {
3
+ port: number;
4
+ workerCount: number;
5
+ config: ConfigSchemaType;
6
+ }
7
+ export declare function reloadServerConfig(newConfig: ConfigSchemaType): Promise<void>;
8
+ export declare function createServer(config: CreateServerConfig): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAoB3D,UAAU,kBAAkB;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AA4CD,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,gBAAgB,iBAuCnE;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,iBAkjB5D"}