pinggy 0.5.1 → 0.5.3

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/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { TunnelConfigurationV1, TunnelUsageType, TunnelInstance, TunnelType, RemoteManagementConfig } from '@pinggy/pinggy';
3
+ export { TunnelConfigurationV1 } from '@pinggy/pinggy';
3
4
  import { Worker } from 'node:worker_threads';
4
5
  import { z } from 'zod';
5
6
  import winston from 'winston';
@@ -556,6 +557,9 @@ declare const TunnelConfigV1Schema: z.ZodObject<{
556
557
  version: z.ZodString;
557
558
  name: z.ZodString;
558
559
  configId: z.ZodString;
560
+ hostKeyCheck: z.ZodOptional<z.ZodBoolean>;
561
+ platformValue: z.ZodOptional<z.ZodString>;
562
+ isQRCode: z.ZodOptional<z.ZodBoolean>;
559
563
  serverAddress: z.ZodOptional<z.ZodString>;
560
564
  token: z.ZodOptional<z.ZodString>;
561
565
  autoReconnect: z.ZodOptional<z.ZodBoolean>;
@@ -595,10 +599,21 @@ declare const TunnelConfigV1Schema: z.ZodObject<{
595
599
  httpsOnly: z.ZodOptional<z.ZodBoolean>;
596
600
  originalRequestUrl: z.ZodOptional<z.ZodBoolean>;
597
601
  allowPreflight: z.ZodOptional<z.ZodBoolean>;
598
- serve: z.ZodOptional<z.ZodString>;
599
- optional: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
602
+ optional: z.ZodOptional<z.ZodObject<{
603
+ sniServerName: z.ZodOptional<z.ZodString>;
604
+ ssl: z.ZodOptional<z.ZodBoolean>;
605
+ additionalArguments: z.ZodOptional<z.ZodString>;
606
+ serve: z.ZodOptional<z.ZodString>;
607
+ manage: z.ZodOptional<z.ZodString>;
608
+ remoteManagement: z.ZodOptional<z.ZodObject<{
609
+ serverUrl: z.ZodString;
610
+ apiKey: z.ZodString;
611
+ }, z.core.$strip>>;
612
+ noTui: z.ZodOptional<z.ZodBoolean>;
613
+ }, z.core.$catchall<z.ZodUnknown>>>;
600
614
  }, z.core.$strip>;
601
615
  type TunnelConfigV1 = z.infer<typeof TunnelConfigV1Schema>;
616
+ declare const TUNNEL_CONFIG_V1_KEYS: (keyof TunnelConfigV1)[];
602
617
 
603
618
  /**
604
619
  * Typed IPC route contract shared by IPCClient (caller) and IPCServer (handler).
@@ -667,8 +682,18 @@ type ResolveLogPathResponse = {
667
682
  } | {
668
683
  status: "not-found";
669
684
  };
685
+ declare const DaemonHost: {
686
+ readonly CLI: "cli";
687
+ readonly APP: "app";
688
+ };
689
+ type DaemonHost = typeof DaemonHost[keyof typeof DaemonHost];
690
+ declare const ShutdownStatus: {
691
+ readonly ShuttingDown: "shutting_down";
692
+ readonly RefusedInApp: "refused_in_app";
693
+ };
694
+ type ShutdownStatus = typeof ShutdownStatus[keyof typeof ShutdownStatus];
670
695
  interface ShutdownResponse {
671
- status: string;
696
+ status: ShutdownStatus;
672
697
  errors: string[];
673
698
  }
674
699
  type LogLevel = "debug" | "info" | "error";
@@ -1012,6 +1037,11 @@ declare class DaemonHealth {
1012
1037
  private reconnectedCallbacks;
1013
1038
  constructor(getIpc: () => IPCClient | null, stream: WsStream);
1014
1039
  bindPid(pid: number): void;
1040
+ /**
1041
+ * Forget a previous loss verdict. Called when the client re-binds to a
1042
+ * live daemon via ensureDaemon():
1043
+ */
1044
+ reset(): void;
1015
1045
  isLost(): boolean;
1016
1046
  onLost(cb: DaemonLostCallback): void;
1017
1047
  onReconnecting(cb: DaemonReconnectingCallback): void;
@@ -1065,6 +1095,12 @@ declare class TunnelClient {
1065
1095
  handleGet(tunnelId: string): Promise<TunnelResponse | ErrorResponse>;
1066
1096
  handleRestart(tunnelId: string): Promise<TunnelResponse | ErrorResponse>;
1067
1097
  shutdown(): Promise<void>;
1098
+ /**
1099
+ * Tear down the daemon hosted in THIS process, if any. Stops all tunnels
1100
+ * and removes daemon.json + daemon-state.json so the next CLI run doesn't
1101
+ * "crash-recover" tunnels that died with the host application.
1102
+ */
1103
+ shutdownInProcessDaemon(): boolean;
1068
1104
  getLogLevel(): Promise<string>;
1069
1105
  setLogLevel(level: "debug" | "info" | "error"): Promise<void>;
1070
1106
  getTunnelLogging(): Promise<boolean>;
@@ -1095,6 +1131,24 @@ declare class TunnelClient {
1095
1131
  private assertClient;
1096
1132
  }
1097
1133
 
1134
+ interface DaemonInfo {
1135
+ pid: number;
1136
+ port: number;
1137
+ startedAt: string;
1138
+ host?: DaemonHost;
1139
+ }
1140
+
1141
+ /**
1142
+ * Read and validate daemon.json.
1143
+ * Returns null if file doesn't exist, is malformed, or PID is stale.
1144
+ * Automatically cleans up stale daemon.json.
1145
+ */
1146
+ declare function getDaemonInfo(): DaemonInfo | null;
1147
+ /**
1148
+ * Check if the daemon is currently running.
1149
+ */
1150
+ declare function isDaemonRunning(): boolean;
1151
+
1098
1152
  interface BaseLogConfig {
1099
1153
  level?: string;
1100
1154
  filePath?: string;
@@ -1124,4 +1178,143 @@ declare function closeRemoteManagement(timeoutMs?: number): Promise<RemoteManage
1124
1178
  declare function startRemoteManagement(remoteManagementConfig: RemoteManagementConfig, tunnelHandler?: TunnelHandler): Promise<RemoteManagementState>;
1125
1179
  declare function getRemoteManagementState(): RemoteManagementState;
1126
1180
 
1127
- export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type StartListener, type StatsListener, type Status, TunnelClient, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement, startRemoteManagement };
1181
+ interface SavedTunnelConfig {
1182
+ name: string;
1183
+ configId: string;
1184
+ autoStart: boolean;
1185
+ createdAt: string;
1186
+ updatedAt: string;
1187
+ tunnelConfig: TunnelConfigurationV1;
1188
+ /**
1189
+ * App-owned UI state (e.g. `regioncode`, `isServerAddress`). The CLI
1190
+ * and daemon never read this;
1191
+ */
1192
+ uiMetadata?: Record<string, unknown>;
1193
+ }
1194
+ /**
1195
+ * Minimal logger interface for the storage module. Defaults to the cli-js
1196
+ * winston logger (silent unless the CLI configures it). Non-CLI consumers
1197
+ * (e.g. the Electron app) override it via {@link configureStorageLogger} to
1198
+ * route storage logs into their own logging pipeline
1199
+ */
1200
+ interface StorageLogger {
1201
+ info: (message: string, ...meta: unknown[]) => void;
1202
+ warn: (message: string, ...meta: unknown[]) => void;
1203
+ error: (message: string, ...meta: unknown[]) => void;
1204
+ }
1205
+ declare function configureStorageLogger(l: StorageLogger): void;
1206
+ /**
1207
+ * Sanitizes a tunnel name to be filesystem-safe.
1208
+ * Allows alphanumeric, hyphens, underscores only.
1209
+ */
1210
+ declare function sanitizeName(name: string): string;
1211
+ /**
1212
+ * Strict name validation used by the CLI's own save path: alphanumeric +
1213
+ * `_`/`-`, ≤128 chars, no reserved subcommand names.
1214
+ */
1215
+ declare function validateNameStrict(name: string): Error | null;
1216
+ /**
1217
+ * Relaxed name validation used by app-driven writes (`{ strict: false }`). The
1218
+ * app allows spaces/unicode in display names, so this only rejects what would
1219
+ * break the filesystem layout or collide with a CLI subcommand: path
1220
+ * separators, NUL/control characters, empty/whitespace-only names, and reserved
1221
+ * subcommand names. The JSON `name` keeps the original; the filename is always
1222
+ * sanitized via {@link sanitizeName}.
1223
+ */
1224
+ declare function validateNameForStorage(name: string): Error | null;
1225
+ /**
1226
+ * Backwards-compatible alias for {@link validateNameStrict}. Existing CLI
1227
+ * callers (`subcommands.ts`, `buildAndStartTunnel.ts`) import `validateName`.
1228
+ */
1229
+ declare const validateName: typeof validateNameStrict;
1230
+ /**
1231
+ * List all saved tunnel configs from the config directory.
1232
+ */
1233
+ declare function listSavedConfigs(): SavedTunnelConfig[];
1234
+ /**
1235
+ * Find a config by its exact display name (the JSON `name`). Exact on purpose:
1236
+ * `sanitizeName` is many-to-one (`"My Tunnel"`/`"My_Tunnel"` → `My_Tunnel`), so
1237
+ * it builds filenames, never decides identity. Narrows by sanitized prefix then
1238
+ * confirms the exact `name`; on a same-name/different-`configId` tie, newest wins.
1239
+ */
1240
+ declare function findConfigByName(name: string): SavedTunnelConfig | null;
1241
+ /**
1242
+ * Find a config by name or configId (supports partial configId match).
1243
+ */
1244
+ declare function findConfig(nameOrId: string): SavedTunnelConfig | null;
1245
+ /**
1246
+ * Save a tunnel config to the config store.
1247
+ * Rejects duplicate names.
1248
+ *
1249
+ * @param options.strict When `true` (default) names are validated with
1250
+ * {@link validateNameStrict}; when `false` (app-driven writes) with the
1251
+ * relaxed {@link validateNameForStorage}.
1252
+ */
1253
+ declare function saveConfig(name: string, configId: string, tunnelConfig: TunnelConfigurationV1, autoStart?: boolean, options?: {
1254
+ strict?: boolean;
1255
+ }): SavedTunnelConfig;
1256
+ /**
1257
+ * Insert or update a full saved record, keyed by `configId` (the stable
1258
+ * identity). If a record with the same `configId` exists under a different
1259
+ * filename — because its `name` changed — the old file is deleted before the
1260
+ * new one is written, so there is never a stale duplicate on disk. Only
1261
+ * validates the name when creating a brand-new record;
1262
+ */
1263
+ declare function upsertConfig(saved: SavedTunnelConfig, options?: {
1264
+ strict?: boolean;
1265
+ }): SavedTunnelConfig;
1266
+ /**
1267
+ * Replace a *bounded* set of configs in one pass. Every config in `configs` is
1268
+ * upserted;
1269
+ */
1270
+ declare function bulkReplace(configs: SavedTunnelConfig[], knownConfigIds: Set<string>, options?: {
1271
+ strict?: boolean;
1272
+ }): {
1273
+ written: string[];
1274
+ deleted: string[];
1275
+ };
1276
+ /**
1277
+ * Load a saved tunnel config by name.
1278
+ */
1279
+ declare function loadConfigByName(name: string): SavedTunnelConfig | null;
1280
+ /**
1281
+ * Delete a saved tunnel config by name or configId.
1282
+ * Returns the deleted config's name if found, null otherwise.
1283
+ */
1284
+ declare function deleteConfig(nameOrId: string): string | null;
1285
+ /**
1286
+ * Update the autoStart flag on a saved config.
1287
+ * Returns the updated config, or null if not found.
1288
+ */
1289
+ declare function updateConfigAutoStart(nameOrId: string, autoStart: boolean): SavedTunnelConfig | null;
1290
+ /**
1291
+ * Update the tunnel configuration of a saved config.
1292
+ * Returns the updated config, or null if not found.
1293
+ */
1294
+ declare function updateTunnelConfig(nameOrId: string, tunnelConfig: TunnelConfigurationV1): SavedTunnelConfig | null;
1295
+ /**
1296
+ * Get all configs marked for auto-start.
1297
+ */
1298
+ declare function getAutoStartConfigs(): SavedTunnelConfig[];
1299
+
1300
+ /**
1301
+ * Returns the base Pinggy config directory for the current platform.
1302
+ * - Linux/macOS: $XDG_CONFIG_HOME/pinggy or ~/.config/pinggy
1303
+ * - Windows: %APPDATA%/pinggy
1304
+ */
1305
+ declare function getPinggyConfigDir(): string;
1306
+ /**
1307
+ * Returns the directory where tunnel config files are stored.
1308
+ */
1309
+ declare function getTunnelConfigDir(): string;
1310
+ /**
1311
+ * Ensures the tunnel config directory exists, creating it recursively if needed.
1312
+ */
1313
+ declare function ensureTunnelConfigDir(): string;
1314
+ /**
1315
+ * Returns the path to the daemon info file (daemon.json).
1316
+ * Contains port + PID so the foreground CLI can find the running daemon.
1317
+ */
1318
+ declare function getDaemonInfoPath(): string;
1319
+
1320
+ export { type AdditionalForwarding, type DaemonInfo, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type SavedTunnelConfig, type StartListener, type StatsListener, type Status, type StorageLogger, TUNNEL_CONFIG_V1_KEYS, TunnelClient, type TunnelConfigV1, TunnelConfigV1Schema, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, bulkReplace, closeRemoteManagement, configureStorageLogger, deleteConfig, enablePackageLogging, ensureTunnelConfigDir, findConfig, findConfigByName, getAutoStartConfigs, getDaemonInfo, getDaemonInfoPath, getPinggyConfigDir, getRemoteManagementState, getTunnelConfigDir, initiateRemoteManagement, isDaemonRunning, listSavedConfigs, loadConfigByName, sanitizeName, saveConfig, startRemoteManagement, updateConfigAutoStart, updateTunnelConfig, upsertConfig, validateName, validateNameForStorage, validateNameStrict };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { TunnelConfigurationV1, TunnelUsageType, TunnelInstance, TunnelType, RemoteManagementConfig } from '@pinggy/pinggy';
3
+ export { TunnelConfigurationV1 } from '@pinggy/pinggy';
3
4
  import { Worker } from 'node:worker_threads';
4
5
  import { z } from 'zod';
5
6
  import winston from 'winston';
@@ -556,6 +557,9 @@ declare const TunnelConfigV1Schema: z.ZodObject<{
556
557
  version: z.ZodString;
557
558
  name: z.ZodString;
558
559
  configId: z.ZodString;
560
+ hostKeyCheck: z.ZodOptional<z.ZodBoolean>;
561
+ platformValue: z.ZodOptional<z.ZodString>;
562
+ isQRCode: z.ZodOptional<z.ZodBoolean>;
559
563
  serverAddress: z.ZodOptional<z.ZodString>;
560
564
  token: z.ZodOptional<z.ZodString>;
561
565
  autoReconnect: z.ZodOptional<z.ZodBoolean>;
@@ -595,10 +599,21 @@ declare const TunnelConfigV1Schema: z.ZodObject<{
595
599
  httpsOnly: z.ZodOptional<z.ZodBoolean>;
596
600
  originalRequestUrl: z.ZodOptional<z.ZodBoolean>;
597
601
  allowPreflight: z.ZodOptional<z.ZodBoolean>;
598
- serve: z.ZodOptional<z.ZodString>;
599
- optional: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
602
+ optional: z.ZodOptional<z.ZodObject<{
603
+ sniServerName: z.ZodOptional<z.ZodString>;
604
+ ssl: z.ZodOptional<z.ZodBoolean>;
605
+ additionalArguments: z.ZodOptional<z.ZodString>;
606
+ serve: z.ZodOptional<z.ZodString>;
607
+ manage: z.ZodOptional<z.ZodString>;
608
+ remoteManagement: z.ZodOptional<z.ZodObject<{
609
+ serverUrl: z.ZodString;
610
+ apiKey: z.ZodString;
611
+ }, z.core.$strip>>;
612
+ noTui: z.ZodOptional<z.ZodBoolean>;
613
+ }, z.core.$catchall<z.ZodUnknown>>>;
600
614
  }, z.core.$strip>;
601
615
  type TunnelConfigV1 = z.infer<typeof TunnelConfigV1Schema>;
616
+ declare const TUNNEL_CONFIG_V1_KEYS: (keyof TunnelConfigV1)[];
602
617
 
603
618
  /**
604
619
  * Typed IPC route contract shared by IPCClient (caller) and IPCServer (handler).
@@ -667,8 +682,18 @@ type ResolveLogPathResponse = {
667
682
  } | {
668
683
  status: "not-found";
669
684
  };
685
+ declare const DaemonHost: {
686
+ readonly CLI: "cli";
687
+ readonly APP: "app";
688
+ };
689
+ type DaemonHost = typeof DaemonHost[keyof typeof DaemonHost];
690
+ declare const ShutdownStatus: {
691
+ readonly ShuttingDown: "shutting_down";
692
+ readonly RefusedInApp: "refused_in_app";
693
+ };
694
+ type ShutdownStatus = typeof ShutdownStatus[keyof typeof ShutdownStatus];
670
695
  interface ShutdownResponse {
671
- status: string;
696
+ status: ShutdownStatus;
672
697
  errors: string[];
673
698
  }
674
699
  type LogLevel = "debug" | "info" | "error";
@@ -1012,6 +1037,11 @@ declare class DaemonHealth {
1012
1037
  private reconnectedCallbacks;
1013
1038
  constructor(getIpc: () => IPCClient | null, stream: WsStream);
1014
1039
  bindPid(pid: number): void;
1040
+ /**
1041
+ * Forget a previous loss verdict. Called when the client re-binds to a
1042
+ * live daemon via ensureDaemon():
1043
+ */
1044
+ reset(): void;
1015
1045
  isLost(): boolean;
1016
1046
  onLost(cb: DaemonLostCallback): void;
1017
1047
  onReconnecting(cb: DaemonReconnectingCallback): void;
@@ -1065,6 +1095,12 @@ declare class TunnelClient {
1065
1095
  handleGet(tunnelId: string): Promise<TunnelResponse | ErrorResponse>;
1066
1096
  handleRestart(tunnelId: string): Promise<TunnelResponse | ErrorResponse>;
1067
1097
  shutdown(): Promise<void>;
1098
+ /**
1099
+ * Tear down the daemon hosted in THIS process, if any. Stops all tunnels
1100
+ * and removes daemon.json + daemon-state.json so the next CLI run doesn't
1101
+ * "crash-recover" tunnels that died with the host application.
1102
+ */
1103
+ shutdownInProcessDaemon(): boolean;
1068
1104
  getLogLevel(): Promise<string>;
1069
1105
  setLogLevel(level: "debug" | "info" | "error"): Promise<void>;
1070
1106
  getTunnelLogging(): Promise<boolean>;
@@ -1095,6 +1131,24 @@ declare class TunnelClient {
1095
1131
  private assertClient;
1096
1132
  }
1097
1133
 
1134
+ interface DaemonInfo {
1135
+ pid: number;
1136
+ port: number;
1137
+ startedAt: string;
1138
+ host?: DaemonHost;
1139
+ }
1140
+
1141
+ /**
1142
+ * Read and validate daemon.json.
1143
+ * Returns null if file doesn't exist, is malformed, or PID is stale.
1144
+ * Automatically cleans up stale daemon.json.
1145
+ */
1146
+ declare function getDaemonInfo(): DaemonInfo | null;
1147
+ /**
1148
+ * Check if the daemon is currently running.
1149
+ */
1150
+ declare function isDaemonRunning(): boolean;
1151
+
1098
1152
  interface BaseLogConfig {
1099
1153
  level?: string;
1100
1154
  filePath?: string;
@@ -1124,4 +1178,143 @@ declare function closeRemoteManagement(timeoutMs?: number): Promise<RemoteManage
1124
1178
  declare function startRemoteManagement(remoteManagementConfig: RemoteManagementConfig, tunnelHandler?: TunnelHandler): Promise<RemoteManagementState>;
1125
1179
  declare function getRemoteManagementState(): RemoteManagementState;
1126
1180
 
1127
- export { type AdditionalForwarding, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type StartListener, type StatsListener, type Status, TunnelClient, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, closeRemoteManagement, enablePackageLogging, getRemoteManagementState, initiateRemoteManagement, startRemoteManagement };
1181
+ interface SavedTunnelConfig {
1182
+ name: string;
1183
+ configId: string;
1184
+ autoStart: boolean;
1185
+ createdAt: string;
1186
+ updatedAt: string;
1187
+ tunnelConfig: TunnelConfigurationV1;
1188
+ /**
1189
+ * App-owned UI state (e.g. `regioncode`, `isServerAddress`). The CLI
1190
+ * and daemon never read this;
1191
+ */
1192
+ uiMetadata?: Record<string, unknown>;
1193
+ }
1194
+ /**
1195
+ * Minimal logger interface for the storage module. Defaults to the cli-js
1196
+ * winston logger (silent unless the CLI configures it). Non-CLI consumers
1197
+ * (e.g. the Electron app) override it via {@link configureStorageLogger} to
1198
+ * route storage logs into their own logging pipeline
1199
+ */
1200
+ interface StorageLogger {
1201
+ info: (message: string, ...meta: unknown[]) => void;
1202
+ warn: (message: string, ...meta: unknown[]) => void;
1203
+ error: (message: string, ...meta: unknown[]) => void;
1204
+ }
1205
+ declare function configureStorageLogger(l: StorageLogger): void;
1206
+ /**
1207
+ * Sanitizes a tunnel name to be filesystem-safe.
1208
+ * Allows alphanumeric, hyphens, underscores only.
1209
+ */
1210
+ declare function sanitizeName(name: string): string;
1211
+ /**
1212
+ * Strict name validation used by the CLI's own save path: alphanumeric +
1213
+ * `_`/`-`, ≤128 chars, no reserved subcommand names.
1214
+ */
1215
+ declare function validateNameStrict(name: string): Error | null;
1216
+ /**
1217
+ * Relaxed name validation used by app-driven writes (`{ strict: false }`). The
1218
+ * app allows spaces/unicode in display names, so this only rejects what would
1219
+ * break the filesystem layout or collide with a CLI subcommand: path
1220
+ * separators, NUL/control characters, empty/whitespace-only names, and reserved
1221
+ * subcommand names. The JSON `name` keeps the original; the filename is always
1222
+ * sanitized via {@link sanitizeName}.
1223
+ */
1224
+ declare function validateNameForStorage(name: string): Error | null;
1225
+ /**
1226
+ * Backwards-compatible alias for {@link validateNameStrict}. Existing CLI
1227
+ * callers (`subcommands.ts`, `buildAndStartTunnel.ts`) import `validateName`.
1228
+ */
1229
+ declare const validateName: typeof validateNameStrict;
1230
+ /**
1231
+ * List all saved tunnel configs from the config directory.
1232
+ */
1233
+ declare function listSavedConfigs(): SavedTunnelConfig[];
1234
+ /**
1235
+ * Find a config by its exact display name (the JSON `name`). Exact on purpose:
1236
+ * `sanitizeName` is many-to-one (`"My Tunnel"`/`"My_Tunnel"` → `My_Tunnel`), so
1237
+ * it builds filenames, never decides identity. Narrows by sanitized prefix then
1238
+ * confirms the exact `name`; on a same-name/different-`configId` tie, newest wins.
1239
+ */
1240
+ declare function findConfigByName(name: string): SavedTunnelConfig | null;
1241
+ /**
1242
+ * Find a config by name or configId (supports partial configId match).
1243
+ */
1244
+ declare function findConfig(nameOrId: string): SavedTunnelConfig | null;
1245
+ /**
1246
+ * Save a tunnel config to the config store.
1247
+ * Rejects duplicate names.
1248
+ *
1249
+ * @param options.strict When `true` (default) names are validated with
1250
+ * {@link validateNameStrict}; when `false` (app-driven writes) with the
1251
+ * relaxed {@link validateNameForStorage}.
1252
+ */
1253
+ declare function saveConfig(name: string, configId: string, tunnelConfig: TunnelConfigurationV1, autoStart?: boolean, options?: {
1254
+ strict?: boolean;
1255
+ }): SavedTunnelConfig;
1256
+ /**
1257
+ * Insert or update a full saved record, keyed by `configId` (the stable
1258
+ * identity). If a record with the same `configId` exists under a different
1259
+ * filename — because its `name` changed — the old file is deleted before the
1260
+ * new one is written, so there is never a stale duplicate on disk. Only
1261
+ * validates the name when creating a brand-new record;
1262
+ */
1263
+ declare function upsertConfig(saved: SavedTunnelConfig, options?: {
1264
+ strict?: boolean;
1265
+ }): SavedTunnelConfig;
1266
+ /**
1267
+ * Replace a *bounded* set of configs in one pass. Every config in `configs` is
1268
+ * upserted;
1269
+ */
1270
+ declare function bulkReplace(configs: SavedTunnelConfig[], knownConfigIds: Set<string>, options?: {
1271
+ strict?: boolean;
1272
+ }): {
1273
+ written: string[];
1274
+ deleted: string[];
1275
+ };
1276
+ /**
1277
+ * Load a saved tunnel config by name.
1278
+ */
1279
+ declare function loadConfigByName(name: string): SavedTunnelConfig | null;
1280
+ /**
1281
+ * Delete a saved tunnel config by name or configId.
1282
+ * Returns the deleted config's name if found, null otherwise.
1283
+ */
1284
+ declare function deleteConfig(nameOrId: string): string | null;
1285
+ /**
1286
+ * Update the autoStart flag on a saved config.
1287
+ * Returns the updated config, or null if not found.
1288
+ */
1289
+ declare function updateConfigAutoStart(nameOrId: string, autoStart: boolean): SavedTunnelConfig | null;
1290
+ /**
1291
+ * Update the tunnel configuration of a saved config.
1292
+ * Returns the updated config, or null if not found.
1293
+ */
1294
+ declare function updateTunnelConfig(nameOrId: string, tunnelConfig: TunnelConfigurationV1): SavedTunnelConfig | null;
1295
+ /**
1296
+ * Get all configs marked for auto-start.
1297
+ */
1298
+ declare function getAutoStartConfigs(): SavedTunnelConfig[];
1299
+
1300
+ /**
1301
+ * Returns the base Pinggy config directory for the current platform.
1302
+ * - Linux/macOS: $XDG_CONFIG_HOME/pinggy or ~/.config/pinggy
1303
+ * - Windows: %APPDATA%/pinggy
1304
+ */
1305
+ declare function getPinggyConfigDir(): string;
1306
+ /**
1307
+ * Returns the directory where tunnel config files are stored.
1308
+ */
1309
+ declare function getTunnelConfigDir(): string;
1310
+ /**
1311
+ * Ensures the tunnel config directory exists, creating it recursively if needed.
1312
+ */
1313
+ declare function ensureTunnelConfigDir(): string;
1314
+ /**
1315
+ * Returns the path to the daemon info file (daemon.json).
1316
+ * Contains port + PID so the foreground CLI can find the running daemon.
1317
+ */
1318
+ declare function getDaemonInfoPath(): string;
1319
+
1320
+ export { type AdditionalForwarding, type DaemonInfo, type DisconnectListener, type ErrorListener, type FinalConfig, type ITunnelManager, type ManagedTunnel, type ReconnectingListener, type ReconnectionCompletedListener, type ReconnectionFailedListener, RemoteManagementUnauthorizedError, type SavedTunnelConfig, type StartListener, type StatsListener, type Status, type StorageLogger, TUNNEL_CONFIG_V1_KEYS, TunnelClient, type TunnelConfigV1, TunnelConfigV1Schema, TunnelErrorCodeType, type TunnelList, TunnelManager, TunnelOperations, type TunnelResponse, TunnelStateType, type TunnelStatus, TunnelWarningCode, type TunnelWorkerErrorListner, type Warning, type WillReconnectListener, bulkReplace, closeRemoteManagement, configureStorageLogger, deleteConfig, enablePackageLogging, ensureTunnelConfigDir, findConfig, findConfigByName, getAutoStartConfigs, getDaemonInfo, getDaemonInfoPath, getPinggyConfigDir, getRemoteManagementState, getTunnelConfigDir, initiateRemoteManagement, isDaemonRunning, listSavedConfigs, loadConfigByName, sanitizeName, saveConfig, startRemoteManagement, updateConfigAutoStart, updateTunnelConfig, upsertConfig, validateName, validateNameForStorage, validateNameStrict };
package/dist/index.js CHANGED
@@ -1,17 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RemoteManagementUnauthorizedError,
4
+ TUNNEL_CONFIG_V1_KEYS,
4
5
  TunnelClient,
6
+ TunnelConfigV1Schema,
5
7
  TunnelErrorCodeType,
6
8
  TunnelOperations,
7
9
  TunnelStateType,
8
10
  TunnelWarningCode,
9
11
  closeRemoteManagement,
12
+ getDaemonInfo,
10
13
  getRemoteManagementState,
11
14
  initiateRemoteManagement,
15
+ isDaemonRunning,
12
16
  startRemoteManagement
13
- } from "./chunk-VJ4VSZGX.js";
14
- import "./chunk-BFARGPGP.js";
17
+ } from "./chunk-GK2PQ7KX.js";
18
+ import "./chunk-5YHD6M35.js";
19
+ import {
20
+ bulkReplace,
21
+ configureStorageLogger,
22
+ deleteConfig,
23
+ findConfig,
24
+ findConfigByName,
25
+ getAutoStartConfigs,
26
+ listSavedConfigs,
27
+ loadConfigByName,
28
+ sanitizeName,
29
+ saveConfig,
30
+ updateConfigAutoStart,
31
+ updateTunnelConfig,
32
+ upsertConfig,
33
+ validateName,
34
+ validateNameForStorage,
35
+ validateNameStrict
36
+ } from "./chunk-WM7I57AA.js";
15
37
  import {
16
38
  TunnelManager,
17
39
  printer_default
@@ -20,7 +42,12 @@ import "./chunk-UB26QJ4T.js";
20
42
  import {
21
43
  enablePackageLogging
22
44
  } from "./chunk-7G6SJEEA.js";
23
- import "./chunk-GBYF2H4H.js";
45
+ import {
46
+ ensureTunnelConfigDir,
47
+ getDaemonInfoPath,
48
+ getPinggyConfigDir,
49
+ getTunnelConfigDir
50
+ } from "./chunk-GBYF2H4H.js";
24
51
 
25
52
  // src/utils/detect_vc_redist_on_windows.ts
26
53
  import fs from "fs";
@@ -112,22 +139,46 @@ async function verifyAndLoad() {
112
139
  process.exit(1);
113
140
  }
114
141
  }
115
- await import("./main-KXUDW6W5.js");
142
+ await import("./main-B2EBHFN2.js");
116
143
  }
117
144
  verifyAndLoad().catch((err) => {
118
145
  printer_default.fatal(`Failed to start CLI:, ${err}`);
119
146
  });
120
147
  export {
121
148
  RemoteManagementUnauthorizedError,
149
+ TUNNEL_CONFIG_V1_KEYS,
122
150
  TunnelClient,
151
+ TunnelConfigV1Schema,
123
152
  TunnelErrorCodeType,
124
153
  TunnelManager,
125
154
  TunnelOperations,
126
155
  TunnelStateType,
127
156
  TunnelWarningCode,
157
+ bulkReplace,
128
158
  closeRemoteManagement,
159
+ configureStorageLogger,
160
+ deleteConfig,
129
161
  enablePackageLogging,
162
+ ensureTunnelConfigDir,
163
+ findConfig,
164
+ findConfigByName,
165
+ getAutoStartConfigs,
166
+ getDaemonInfo,
167
+ getDaemonInfoPath,
168
+ getPinggyConfigDir,
130
169
  getRemoteManagementState,
170
+ getTunnelConfigDir,
131
171
  initiateRemoteManagement,
132
- startRemoteManagement
172
+ isDaemonRunning,
173
+ listSavedConfigs,
174
+ loadConfigByName,
175
+ sanitizeName,
176
+ saveConfig,
177
+ startRemoteManagement,
178
+ updateConfigAutoStart,
179
+ updateTunnelConfig,
180
+ upsertConfig,
181
+ validateName,
182
+ validateNameForStorage,
183
+ validateNameStrict
133
184
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IPCClient
3
- } from "./chunk-BFARGPGP.js";
3
+ } from "./chunk-5YHD6M35.js";
4
4
  export {
5
5
  IPCClient
6
6
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDaemonChild
4
- } from "./chunk-Y65A4BL2.js";
4
+ } from "./chunk-BBPR2LJB.js";
5
5
  import {
6
6
  RemoteManagementUnauthorizedError,
7
7
  TunnelOperations,
@@ -13,10 +13,12 @@ import {
13
13
  getRemoteManagementState,
14
14
  initiateRemoteManagement,
15
15
  isDaemonRunning
16
- } from "./chunk-VJ4VSZGX.js";
16
+ } from "./chunk-GK2PQ7KX.js";
17
17
  import "./chunk-MT44NAXX.js";
18
- import "./chunk-BFARGPGP.js";
19
- import "./chunk-HUP6YWH6.js";
18
+ import {
19
+ DaemonHost
20
+ } from "./chunk-5YHD6M35.js";
21
+ import "./chunk-WM7I57AA.js";
20
22
  import {
21
23
  TunnelManager
22
24
  } from "./chunk-DLNUDW6G.js";
@@ -26,6 +28,7 @@ import {
26
28
  } from "./chunk-7G6SJEEA.js";
27
29
  import "./chunk-GBYF2H4H.js";
28
30
  export {
31
+ DaemonHost,
29
32
  RemoteManagementUnauthorizedError,
30
33
  TunnelManager,
31
34
  TunnelOperations,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinggy",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "description": "Create secure, shareable tunnels to your localhost and manage them from the command line. ",