pinggy 0.4.9 → 0.5.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.
@@ -3,6 +3,22 @@ import winston from "winston";
3
3
  import fs from "fs";
4
4
  import path from "path";
5
5
  import { pinggy, LogLevel } from "@pinggy/pinggy";
6
+ var _currentLevel = process.env.PINGGY_LOG_LEVEL || "info";
7
+ var _sdkLogFilePath = null;
8
+ function getLogLevel() {
9
+ return _currentLevel;
10
+ }
11
+ function setLogLevel(level) {
12
+ _currentLevel = level;
13
+ getLogger().level = level;
14
+ if (_sdkLogFilePath) {
15
+ enableLoggingByLogLevelInSdk(level, _sdkLogFilePath);
16
+ }
17
+ import("./daemonConfig-G6S46GPJ.js").then(({ writeDaemonConfig }) => writeDaemonConfig({ logLevel: level })).catch(() => {
18
+ });
19
+ import("./TunnelManager-OPUMAZFX.js").then(({ TunnelManager }) => TunnelManager.getInstance().applyLogLevelToActiveTunnels(level)).catch(() => {
20
+ });
21
+ }
6
22
  var _logger = null;
7
23
  function getLogger() {
8
24
  if (!_logger) {
@@ -22,6 +38,7 @@ function applyLoggingConfig(cfg) {
22
38
  } = cfg;
23
39
  if (enableSdkLog) {
24
40
  enableLoggingByLogLevelInSdk(level ?? "info", filePath);
41
+ _sdkLogFilePath = filePath ?? null;
25
42
  }
26
43
  if (filePath) {
27
44
  const dir = path.dirname(filePath);
@@ -34,22 +51,30 @@ function applyLoggingConfig(cfg) {
34
51
  format: winston.format.combine(
35
52
  winston.format.colorize(),
36
53
  winston.format.timestamp(),
37
- winston.format.printf(({ level: level2, message, timestamp, ...meta }) => {
38
- const srcLabel = source ? "[CLI] " : "";
39
- return `${timestamp} ${srcLabel}[${level2}] ${message} ${Object.keys(meta).length ? JSON.stringify(meta) : ""}`;
54
+ winston.format.printf(({ level: level2, message, timestamp, tunnelId, source: src, ...meta }) => {
55
+ const srcLabel = source && src && src !== "libpinggy" && src !== "sdk-js" ? `[${src}] ` : "";
56
+ const tunnelLabel = tunnelId ? `[tunnel:${String(tunnelId).slice(0, 8)}] ` : "";
57
+ return `${timestamp} ${tunnelLabel}[${level2}] ${srcLabel}${message}${Object.keys(meta).length ? " " + JSON.stringify(meta) : ""}`;
40
58
  })
41
59
  )
42
60
  })
43
61
  );
44
62
  }
45
63
  if (filePath) {
64
+ const daemonFilter = winston.format((info) => {
65
+ if (info.source === "libpinggy" || info.source === "sdk-js") return false;
66
+ return info;
67
+ });
46
68
  transports.push(
47
69
  new winston.transports.File({
48
70
  filename: filePath,
49
71
  format: winston.format.combine(
72
+ daemonFilter(),
50
73
  winston.format.timestamp(),
51
- winston.format.printf(({ level: level2, message, timestamp, ...meta }) => {
52
- return `${timestamp} [${level2}] ${message} ${Object.keys(meta).length ? JSON.stringify(meta) : ""}`;
74
+ winston.format.printf(({ level: level2, message, timestamp, tunnelId, source: src, ...meta }) => {
75
+ const srcLabel = src ? `[${src}] ` : "";
76
+ const tunnelLabel = tunnelId ? `[tunnel:${String(tunnelId).slice(0, 8)}] ` : "";
77
+ return `${timestamp} ${tunnelLabel}[${level2}] ${srcLabel}${message}${Object.keys(meta).length ? " " + JSON.stringify(meta) : ""}`;
53
78
  })
54
79
  )
55
80
  })
@@ -61,6 +86,7 @@ function applyLoggingConfig(cfg) {
61
86
  log.add(t);
62
87
  }
63
88
  log.level = (level || process.env.PINGGY_LOG_LEVEL || "info").toLowerCase();
89
+ _currentLevel = log.level;
64
90
  log.silent = silent || transports.length === 0;
65
91
  return log;
66
92
  }
@@ -87,9 +113,9 @@ function enableLoggingByLogLevelInSdk(loglevel, logFilePath) {
87
113
  return;
88
114
  }
89
115
  const l = loglevel.toUpperCase();
90
- if (loglevel === "DEBUG") {
116
+ if (l === "DEBUG") {
91
117
  pinggy.setDebugLogging(true, LogLevel.DEBUG, logFilePath);
92
- } else if (loglevel === "ERROR") {
118
+ } else if (l === "ERROR") {
93
119
  pinggy.setDebugLogging(true, LogLevel.ERROR, logFilePath);
94
120
  } else {
95
121
  pinggy.setDebugLogging(true, LogLevel.INFO, logFilePath);
@@ -97,6 +123,8 @@ function enableLoggingByLogLevelInSdk(loglevel, logFilePath) {
97
123
  }
98
124
 
99
125
  export {
126
+ getLogLevel,
127
+ setLogLevel,
100
128
  logger,
101
129
  configureLogger,
102
130
  enablePackageLogging
@@ -0,0 +1,164 @@
1
+ // src/daemon/ipc/ipcClient.ts
2
+ import http from "http";
3
+
4
+ // src/daemon/ipc/ipcRoutes.ts
5
+ var Route = {
6
+ Ping: "GET /ping",
7
+ ListTunnels: "GET /tunnels",
8
+ ListTunnelsV1: "GET /tunnels-v1",
9
+ StartTunnel: "POST /tunnels/start",
10
+ StartTunnelConfig: "POST /tunnels/start-config",
11
+ StartTunnelV1: "POST /tunnels/start-v1",
12
+ StopTunnel: "POST /tunnels/stop",
13
+ RestartTunnel: "POST /tunnels/restart",
14
+ UpdateConfig: "POST /tunnels/update-config",
15
+ UpdateConfigV2: "POST /tunnels/update-config-v2",
16
+ RemoveStopped: "POST /tunnels/remove-stopped",
17
+ Shutdown: "POST /shutdown",
18
+ GetLogLevel: "GET /loglevel",
19
+ SetLogLevel: "POST /loglevel",
20
+ GetTunnelLogging: "GET /config/tunnel-logging",
21
+ SetTunnelLogging: "POST /config/tunnel-logging",
22
+ GetLogPaths: "GET /logs/paths"
23
+ };
24
+ var SessionMode = {
25
+ Foreground: "foreground",
26
+ Detached: "detached"
27
+ };
28
+
29
+ // src/daemon/ipc/ipcClient.ts
30
+ var REQUEST_TIMEOUT_MS = 1e4;
31
+ var IPCClient = class {
32
+ constructor(port, origin = "cli") {
33
+ this.port = port;
34
+ this.origin = origin;
35
+ }
36
+ async ping(timeoutMs) {
37
+ return this.call(Route.Ping, void 0, timeoutMs);
38
+ }
39
+ async listTunnels() {
40
+ return this.call(Route.ListTunnels, void 0);
41
+ }
42
+ async getTunnel(tunnelId) {
43
+ return this.request("GET", `/tunnels/${tunnelId}`);
44
+ }
45
+ async getTunnelStats(tunnelId) {
46
+ return this.request("GET", `/tunnels/${encodeURIComponent(tunnelId)}/stats`);
47
+ }
48
+ async startTunnel(name, mode) {
49
+ return this.call(Route.StartTunnel, { name, mode });
50
+ }
51
+ async startTunnelWithConfig(config, mode, noWait) {
52
+ return this.call(Route.StartTunnelConfig, { config, mode, noWait });
53
+ }
54
+ async stopTunnel(tunnelid) {
55
+ return this.call(Route.StopTunnel, { tunnelid });
56
+ }
57
+ async restartTunnel(tunnelid) {
58
+ return this.call(Route.RestartTunnel, { tunnelid });
59
+ }
60
+ // v1 operations (used by remote management via daemon)
61
+ async startTunnelV1(config, mode, noWait) {
62
+ return this.call(Route.StartTunnelV1, { config, mode, noWait });
63
+ }
64
+ async listTunnelsV1() {
65
+ return this.call(Route.ListTunnelsV1, void 0);
66
+ }
67
+ async updateConfig(config, noWait) {
68
+ return this.call(Route.UpdateConfig, { config, noWait });
69
+ }
70
+ async updateConfigV2(config, noWait) {
71
+ return this.call(Route.UpdateConfigV2, { config, noWait });
72
+ }
73
+ async removeStoppedTunnel(opts) {
74
+ return this.call(Route.RemoveStopped, opts);
75
+ }
76
+ async shutdown() {
77
+ return this.call(Route.Shutdown, {});
78
+ }
79
+ async getLogLevel() {
80
+ return this.call(Route.GetLogLevel, void 0);
81
+ }
82
+ async setLogLevel(level) {
83
+ return this.call(Route.SetLogLevel, { level });
84
+ }
85
+ async getTunnelLogging() {
86
+ return this.call(Route.GetTunnelLogging, void 0);
87
+ }
88
+ async setTunnelLogging(enabled) {
89
+ return this.call(Route.SetTunnelLogging, { enabled });
90
+ }
91
+ async getLogPaths() {
92
+ return this.call(Route.GetLogPaths, void 0);
93
+ }
94
+ async resolveLogPath(q) {
95
+ return this.request("GET", `/logs/resolve?q=${encodeURIComponent(q)}`);
96
+ }
97
+ /**
98
+ * Get the WebSocket URL for event streaming.
99
+ */
100
+ getWsUrl() {
101
+ return `ws://127.0.0.1:${this.port}/ws`;
102
+ }
103
+ getPort() {
104
+ return this.port;
105
+ }
106
+ call(key, body, timeoutMs) {
107
+ const spaceIdx = key.indexOf(" ");
108
+ const method = key.slice(0, spaceIdx);
109
+ const path = key.slice(spaceIdx + 1);
110
+ const payload = method === "GET" ? void 0 : JSON.stringify(body ?? {});
111
+ return this.request(method, path, payload, timeoutMs);
112
+ }
113
+ request(method, path, body, timeoutMs) {
114
+ return new Promise((resolve, reject) => {
115
+ const headers = {
116
+ "X-Pinggy-Origin": this.origin
117
+ };
118
+ if (body) {
119
+ headers["Content-Type"] = "application/json";
120
+ headers["Content-Length"] = Buffer.byteLength(body);
121
+ }
122
+ const req = http.request(
123
+ {
124
+ hostname: "127.0.0.1",
125
+ port: this.port,
126
+ path,
127
+ method,
128
+ headers,
129
+ timeout: timeoutMs ?? REQUEST_TIMEOUT_MS
130
+ },
131
+ (res) => {
132
+ const chunks = [];
133
+ res.on("data", (chunk) => chunks.push(chunk));
134
+ res.on("end", () => {
135
+ const text = Buffer.concat(chunks).toString("utf-8");
136
+ const statusCode = res.statusCode ?? 0;
137
+ if (statusCode < 200 || statusCode >= 300) {
138
+ reject(new Error(`Daemon returned HTTP ${statusCode}: ${text.slice(0, 200)}`));
139
+ return;
140
+ }
141
+ try {
142
+ resolve(JSON.parse(text));
143
+ } catch {
144
+ reject(new Error(`Invalid JSON from daemon: ${text.slice(0, 200)}`));
145
+ }
146
+ });
147
+ }
148
+ );
149
+ req.on("error", (err) => reject(new Error(`Cannot connect to daemon: ${err.message}`)));
150
+ req.on("timeout", () => {
151
+ req.destroy();
152
+ reject(new Error("Daemon request timed out"));
153
+ });
154
+ if (body) req.write(body);
155
+ req.end();
156
+ });
157
+ }
158
+ };
159
+
160
+ export {
161
+ Route,
162
+ SessionMode,
163
+ IPCClient
164
+ };