@limrun/api
Advanced tools
+4
-0
| # Changelog | ||
| ## 0.13.2 (2025-11-11) | ||
| Full Changelog: [v0.13.1...v0.13.2](https://github.com/limrun-inc/typescript-sdk/compare/v0.13.1...v0.13.2) | ||
| ## 0.13.1 (2025-11-08) | ||
@@ -4,0 +8,0 @@ |
+1
-1
@@ -6,4 +6,4 @@ export { Limrun as default } from "./client.mjs"; | ||
| export { PagePromise } from "./core/pagination.mjs"; | ||
| export { createInstanceClient } from "./instance-client.mjs"; | ||
| export * from "./instance-client.mjs"; | ||
| export { LimrunError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.mjs"; | ||
| //# sourceMappingURL=index.d.mts.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE;OAC9B,EAAE,WAAW,EAAE;OACf,EAAE,oBAAoB,EAAE;OACxB,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} | ||
| {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE;OAC9B,EAAE,WAAW,EAAE;;OAEf,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} |
+1
-1
@@ -6,4 +6,4 @@ export { Limrun as default } from "./client.js"; | ||
| export { PagePromise } from "./core/pagination.js"; | ||
| export { createInstanceClient } from "./instance-client.js"; | ||
| export * from "./instance-client.js"; | ||
| export { LimrunError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.js"; | ||
| //# sourceMappingURL=index.d.ts.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE;OAC9B,EAAE,WAAW,EAAE;OACf,EAAE,oBAAoB,EAAE;OACxB,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"OAEO,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAE,KAAK,UAAU,EAAE,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE;OAC9B,EAAE,WAAW,EAAE;;OAEf,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} |
+3
-3
@@ -7,3 +7,4 @@ "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.LimrunError = exports.createInstanceClient = exports.PagePromise = exports.Limrun = exports.APIPromise = exports.toFile = exports.default = void 0; | ||
| exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.LimrunError = exports.PagePromise = exports.Limrun = exports.APIPromise = exports.toFile = exports.default = void 0; | ||
| const tslib_1 = require("./internal/tslib.js"); | ||
| var client_1 = require("./client.js"); | ||
@@ -19,4 +20,3 @@ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return client_1.Limrun; } }); | ||
| Object.defineProperty(exports, "PagePromise", { enumerable: true, get: function () { return pagination_1.PagePromise; } }); | ||
| var instance_client_1 = require("./instance-client.js"); | ||
| Object.defineProperty(exports, "createInstanceClient", { enumerable: true, get: function () { return instance_client_1.createInstanceClient; } }); | ||
| tslib_1.__exportStar(require("./instance-client.js"), exports); | ||
| var error_1 = require("./core/error.js"); | ||
@@ -23,0 +23,0 @@ Object.defineProperty(exports, "LimrunError", { enumerable: true, get: function () { return error_1.LimrunError; } }); |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;AAEtF,sCAA6C;AAApC,iGAAA,MAAM,OAAW;AAE1B,6CAAyD;AAA/B,iGAAA,MAAM,OAAA;AAChC,qDAAgD;AAAvC,yGAAA,UAAU,OAAA;AACnB,sCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mDAAgD;AAAvC,yGAAA,WAAW,OAAA;AACpB,wDAAyD;AAAhD,uHAAA,oBAAoB,OAAA;AAC7B,yCAcsB;AAbpB,oGAAA,WAAW,OAAA;AACX,iGAAA,QAAQ,OAAA;AACR,2GAAA,kBAAkB,OAAA;AAClB,kHAAA,yBAAyB,OAAA;AACzB,0GAAA,iBAAiB,OAAA;AACjB,sGAAA,aAAa,OAAA;AACb,sGAAA,aAAa,OAAA;AACb,uGAAA,cAAc,OAAA;AACd,wGAAA,eAAe,OAAA;AACf,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,8GAAA,qBAAqB,OAAA;AACrB,iHAAA,wBAAwB,OAAA"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;AAEtF,sCAA6C;AAApC,iGAAA,MAAM,OAAW;AAE1B,6CAAyD;AAA/B,iGAAA,MAAM,OAAA;AAChC,qDAAgD;AAAvC,yGAAA,UAAU,OAAA;AACnB,sCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mDAAgD;AAAvC,yGAAA,WAAW,OAAA;AACpB,+DAAkC;AAClC,yCAcsB;AAbpB,oGAAA,WAAW,OAAA;AACX,iGAAA,QAAQ,OAAA;AACR,2GAAA,kBAAkB,OAAA;AAClB,kHAAA,yBAAyB,OAAA;AACzB,0GAAA,iBAAiB,OAAA;AACjB,sGAAA,aAAa,OAAA;AACb,sGAAA,aAAa,OAAA;AACb,uGAAA,cAAc,OAAA;AACd,wGAAA,eAAe,OAAA;AACf,4GAAA,mBAAmB,OAAA;AACnB,4GAAA,mBAAmB,OAAA;AACnB,8GAAA,qBAAqB,OAAA;AACrB,iHAAA,wBAAwB,OAAA"} |
+1
-1
@@ -7,4 +7,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. | ||
| export { PagePromise } from "./core/pagination.mjs"; | ||
| export { createInstanceClient } from "./instance-client.mjs"; | ||
| export * from "./instance-client.mjs"; | ||
| export { LimrunError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.mjs"; | ||
| //# sourceMappingURL=index.mjs.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.mjs","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAmB,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAsB;OAC9B,EAAE,WAAW,EAAE;OACf,EAAE,oBAAoB,EAAE;OACxB,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} | ||
| {"version":3,"file":"index.mjs","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAE/E,EAAE,MAAM,IAAI,OAAO,EAAE;OAErB,EAAmB,MAAM,EAAE;OAC3B,EAAE,UAAU,EAAE;OACd,EAAE,MAAM,EAAsB;OAC9B,EAAE,WAAW,EAAE;;OAEf,EACL,WAAW,EACX,QAAQ,EACR,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,GACzB"} |
| import type { Tunnel } from "./tunnel.mjs"; | ||
| /** | ||
| * Connection state of the instance client | ||
| */ | ||
| export type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for connection state changes | ||
| */ | ||
| export type ConnectionStateCallback = (state: ConnectionState) => void; | ||
| /** | ||
| * A client for interacting with a Limbar instance | ||
@@ -26,2 +34,11 @@ */ | ||
| sendAsset: (url: string) => Promise<void>; | ||
| /** | ||
| * Get current connection state | ||
| */ | ||
| getConnectionState: () => ConnectionState; | ||
| /** | ||
| * Register callback for connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: ConnectionStateCallback) => () => void; | ||
| }; | ||
@@ -58,2 +75,17 @@ /** | ||
| logLevel?: LogLevel; | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| }; | ||
@@ -60,0 +92,0 @@ type ScreenshotData = { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"instance-client.d.mts","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"OAIO,KAAK,EAAE,MAAM,EAAE;AAEtB;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;;OAGG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAaF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA0BF;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0OlG"} | ||
| {"version":3,"file":"instance-client.d.mts","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"OAIO,KAAK,EAAE,MAAM,EAAE;AAEtB;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAE3F;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;;OAGG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,kBAAkB,EAAE,MAAM,eAAe,CAAC;IAE1C;;;OAGG;IACH,uBAAuB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,MAAM,IAAI,CAAC;CAC5E,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAaF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA0BF;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8WlG"} |
+32
-0
| import type { Tunnel } from "./tunnel.js"; | ||
| /** | ||
| * Connection state of the instance client | ||
| */ | ||
| export type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for connection state changes | ||
| */ | ||
| export type ConnectionStateCallback = (state: ConnectionState) => void; | ||
| /** | ||
| * A client for interacting with a Limbar instance | ||
@@ -26,2 +34,11 @@ */ | ||
| sendAsset: (url: string) => Promise<void>; | ||
| /** | ||
| * Get current connection state | ||
| */ | ||
| getConnectionState: () => ConnectionState; | ||
| /** | ||
| * Register callback for connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: ConnectionStateCallback) => () => void; | ||
| }; | ||
@@ -58,2 +75,17 @@ /** | ||
| logLevel?: LogLevel; | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| }; | ||
@@ -60,0 +92,0 @@ type ScreenshotData = { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"instance-client.d.ts","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"OAIO,KAAK,EAAE,MAAM,EAAE;AAEtB;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;;OAGG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAaF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA0BF;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CA0OlG"} | ||
| {"version":3,"file":"instance-client.d.ts","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"OAIO,KAAK,EAAE,MAAM,EAAE;AAEtB;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAE3F;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C;;OAEG;IACH,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB;;;OAGG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC;;;;OAIG;IACH,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,kBAAkB,EAAE,MAAM,eAAe,CAAC;IAE1C;;;OAGG;IACH,uBAAuB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,MAAM,IAAI,CAAC;CAC5E,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAaF,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA0BF;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CA8WlG"} |
+193
-87
@@ -15,5 +15,13 @@ "use strict"; | ||
| const logLevel = options.logLevel ?? 'info'; | ||
| const maxReconnectAttempts = options.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options.maxReconnectDelay ?? 30000; | ||
| let ws = undefined; | ||
| let connectionState = 'connecting'; | ||
| let reconnectAttempts = 0; | ||
| let reconnectTimeout; | ||
| let intentionalDisconnect = false; | ||
| const screenshotRequests = new Map(); | ||
| const assetRequests = new Map(); | ||
| const stateChangeCallbacks = new Set(); | ||
| // Logger functions | ||
@@ -38,84 +46,175 @@ const logger = { | ||
| }; | ||
| const updateConnectionState = (newState) => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } | ||
| catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const failPendingRequests = (reason) => { | ||
| screenshotRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| screenshotRequests.clear(); | ||
| assetRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| assetRequests.clear(); | ||
| }; | ||
| const cleanup = () => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === ws_1.WebSocket.OPEN || ws.readyState === ws_1.WebSocket.CONNECTING) { | ||
| ws.close(); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| let pingInterval; | ||
| return new Promise((resolveConnection, rejectConnection) => { | ||
| logger.debug(`Attempting to connect to WebSocket server at ${serverAddress}...`); | ||
| ws = new ws_1.WebSocket(serverAddress); | ||
| ws.on('message', (data) => { | ||
| let message; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| let hasResolved = false; | ||
| // Reconnection logic with exponential backoff | ||
| const scheduleReconnect = () => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Giving up.`); | ||
| updateConnectionState('disconnected'); | ||
| return; | ||
| } | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = () => { | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new ws_1.WebSocket(serverAddress); | ||
| ws.on('message', (data) => { | ||
| let message; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| } | ||
| catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| return; | ||
| } | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| break; | ||
| } | ||
| const screenshotMessage = message; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`); | ||
| break; | ||
| } | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| } | ||
| const screenshotMessage = message; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`); | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| break; | ||
| } | ||
| const errorMessage = message; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot error for unknown or already handled session: ${errorMessage.id}`); | ||
| break; | ||
| } | ||
| logger.error(`Server reported an error capturing screenshot for session ${errorMessage.id}:`, errorMessage.message); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| } | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| break; | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = message; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot error for unknown or already handled session: ${errorMessage.id}`); | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| logger.error(`Server reported an error capturing screenshot for session ${errorMessage.id}:`, errorMessage.message); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| break; | ||
| }); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (!hasResolved && (ws?.readyState === ws_1.WebSocket.CONNECTING || ws?.readyState === ws_1.WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| }); | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('Disconnected from server.'); | ||
| failPendingRequests('Connection closed'); | ||
| if (shouldReconnect) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
| if (ws && ws.readyState === ws_1.WebSocket.OPEN) { | ||
| ws.ping(); | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| }, 30000); | ||
| if (!hasResolved) { | ||
| hasResolved = true; | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| } | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| }); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (ws && (ws.readyState === ws_1.WebSocket.CONNECTING || ws.readyState === ws_1.WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter(err)); | ||
| }); | ||
| ws.on('close', () => { | ||
| logger.debug('Disconnected from server.'); | ||
| screenshotRequests.forEach((request) => request.rejecter('Disconnected from server')); | ||
| }); | ||
| }); | ||
| }; | ||
| const screenshot = async () => { | ||
@@ -160,8 +259,17 @@ if (!ws || ws.readyState !== ws_1.WebSocket.OPEN) { | ||
| const disconnect = () => { | ||
| if (ws) { | ||
| logger.debug('Closing WebSocket connection.'); | ||
| ws.close(); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter('Websocket connection closed')); | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| failPendingRequests('Intentional disconnect'); | ||
| logger.debug('Intentionally disconnected from WebSocket.'); | ||
| }; | ||
| const getConnectionState = () => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| /** | ||
@@ -172,6 +280,11 @@ * Opens a WebSocket TCP proxy for the ADB port and connects the local adb | ||
| const startAdbTunnel = async () => { | ||
| const { address, close } = await (0, tunnel_1.startTcpTunnel)(options.adbUrl, options.token, '127.0.0.1', 0); | ||
| const tunnel = await (0, tunnel_1.startTcpTunnel)(options.adbUrl, options.token, '127.0.0.1', 0, { | ||
| maxReconnectAttempts, | ||
| reconnectDelay, | ||
| maxReconnectDelay, | ||
| logLevel, | ||
| }); | ||
| try { | ||
| await new Promise((resolve, reject) => { | ||
| (0, node_child_process_1.exec)(`${options.adbPath ?? 'adb'} connect ${address.address}:${address.port}`, (err) => { | ||
| (0, node_child_process_1.exec)(`${options.adbPath ?? 'adb'} connect ${tunnel.address.address}:${tunnel.address.port}`, (err) => { | ||
| if (err) | ||
@@ -182,9 +295,9 @@ return reject(err); | ||
| }); | ||
| logger.debug(`ADB connected on ${address.address}`); | ||
| logger.debug(`ADB connected on ${tunnel.address.address}`); | ||
| } | ||
| catch (err) { | ||
| close(); | ||
| tunnel.close(); | ||
| throw err; | ||
| } | ||
| return { address, close }; | ||
| return tunnel; | ||
| }; | ||
@@ -208,13 +321,6 @@ const sendAsset = async (url) => { | ||
| }; | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| }); | ||
| }); | ||
| // Start the initial connection | ||
| setupWebSocket(); | ||
| }); | ||
| } | ||
| //# sourceMappingURL=instance-client.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"instance-client.js","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"instance-client.js","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"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"} |
+193
-87
@@ -12,5 +12,13 @@ import { WebSocket } from 'ws'; | ||
| const logLevel = options.logLevel ?? 'info'; | ||
| const maxReconnectAttempts = options.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options.maxReconnectDelay ?? 30000; | ||
| let ws = undefined; | ||
| let connectionState = 'connecting'; | ||
| let reconnectAttempts = 0; | ||
| let reconnectTimeout; | ||
| let intentionalDisconnect = false; | ||
| const screenshotRequests = new Map(); | ||
| const assetRequests = new Map(); | ||
| const stateChangeCallbacks = new Set(); | ||
| // Logger functions | ||
@@ -35,84 +43,175 @@ const logger = { | ||
| }; | ||
| const updateConnectionState = (newState) => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } | ||
| catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const failPendingRequests = (reason) => { | ||
| screenshotRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| screenshotRequests.clear(); | ||
| assetRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| assetRequests.clear(); | ||
| }; | ||
| const cleanup = () => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { | ||
| ws.close(); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| let pingInterval; | ||
| return new Promise((resolveConnection, rejectConnection) => { | ||
| logger.debug(`Attempting to connect to WebSocket server at ${serverAddress}...`); | ||
| ws = new WebSocket(serverAddress); | ||
| ws.on('message', (data) => { | ||
| let message; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| let hasResolved = false; | ||
| // Reconnection logic with exponential backoff | ||
| const scheduleReconnect = () => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Giving up.`); | ||
| updateConnectionState('disconnected'); | ||
| return; | ||
| } | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = () => { | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new WebSocket(serverAddress); | ||
| ws.on('message', (data) => { | ||
| let message; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| } | ||
| catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| return; | ||
| } | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| break; | ||
| } | ||
| const screenshotMessage = message; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`); | ||
| break; | ||
| } | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| } | ||
| const screenshotMessage = message; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`); | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| break; | ||
| } | ||
| const errorMessage = message; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot error for unknown or already handled session: ${errorMessage.id}`); | ||
| break; | ||
| } | ||
| logger.error(`Server reported an error capturing screenshot for session ${errorMessage.id}:`, errorMessage.message); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| } | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| break; | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = message; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| if (!request) { | ||
| logger.warn(`Received screenshot error for unknown or already handled session: ${errorMessage.id}`); | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| logger.error(`Server reported an error capturing screenshot for session ${errorMessage.id}:`, errorMessage.message); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| break; | ||
| }); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (!hasResolved && (ws?.readyState === WebSocket.CONNECTING || ws?.readyState === WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| }); | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('Disconnected from server.'); | ||
| failPendingRequests('Connection closed'); | ||
| if (shouldReconnect) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
| if (ws && ws.readyState === WebSocket.OPEN) { | ||
| ws.ping(); | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| } | ||
| const errorMessage = typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url); | ||
| break; | ||
| }, 30000); | ||
| if (!hasResolved) { | ||
| hasResolved = true; | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| } | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| }); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (ws && (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter(err)); | ||
| }); | ||
| ws.on('close', () => { | ||
| logger.debug('Disconnected from server.'); | ||
| screenshotRequests.forEach((request) => request.rejecter('Disconnected from server')); | ||
| }); | ||
| }); | ||
| }; | ||
| const screenshot = async () => { | ||
@@ -157,8 +256,17 @@ if (!ws || ws.readyState !== WebSocket.OPEN) { | ||
| const disconnect = () => { | ||
| if (ws) { | ||
| logger.debug('Closing WebSocket connection.'); | ||
| ws.close(); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter('Websocket connection closed')); | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| failPendingRequests('Intentional disconnect'); | ||
| logger.debug('Intentionally disconnected from WebSocket.'); | ||
| }; | ||
| const getConnectionState = () => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| /** | ||
@@ -169,6 +277,11 @@ * Opens a WebSocket TCP proxy for the ADB port and connects the local adb | ||
| const startAdbTunnel = async () => { | ||
| const { address, close } = await startTcpTunnel(options.adbUrl, options.token, '127.0.0.1', 0); | ||
| const tunnel = await startTcpTunnel(options.adbUrl, options.token, '127.0.0.1', 0, { | ||
| maxReconnectAttempts, | ||
| reconnectDelay, | ||
| maxReconnectDelay, | ||
| logLevel, | ||
| }); | ||
| try { | ||
| await new Promise((resolve, reject) => { | ||
| exec(`${options.adbPath ?? 'adb'} connect ${address.address}:${address.port}`, (err) => { | ||
| exec(`${options.adbPath ?? 'adb'} connect ${tunnel.address.address}:${tunnel.address.port}`, (err) => { | ||
| if (err) | ||
@@ -179,9 +292,9 @@ return reject(err); | ||
| }); | ||
| logger.debug(`ADB connected on ${address.address}`); | ||
| logger.debug(`ADB connected on ${tunnel.address.address}`); | ||
| } | ||
| catch (err) { | ||
| close(); | ||
| tunnel.close(); | ||
| throw err; | ||
| } | ||
| return { address, close }; | ||
| return tunnel; | ||
| }; | ||
@@ -205,13 +318,6 @@ const sendAsset = async (url) => { | ||
| }; | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| }); | ||
| }); | ||
| // Start the initial connection | ||
| setupWebSocket(); | ||
| }); | ||
| } | ||
| //# sourceMappingURL=instance-client.mjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"instance-client.mjs","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"instance-client.mjs","sourceRoot":"","sources":["src/instance-client.ts"],"names":[],"mappings":"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"} |
+1
-1
| { | ||
| "name": "@limrun/api", | ||
| "version": "0.13.1", | ||
| "version": "0.13.2", | ||
| "description": "The official TypeScript library for the Limrun API", | ||
@@ -5,0 +5,0 @@ "author": "Limrun <contact@limrun.com>", |
+1
-1
@@ -9,3 +9,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. | ||
| export { PagePromise } from './core/pagination'; | ||
| export { createInstanceClient } from './instance-client'; | ||
| export * from './instance-client'; | ||
| export { | ||
@@ -12,0 +12,0 @@ LimrunError, |
+267
-99
@@ -8,2 +8,12 @@ import { WebSocket, Data } from 'ws'; | ||
| /** | ||
| * Connection state of the instance client | ||
| */ | ||
| export type ConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for connection state changes | ||
| */ | ||
| export type ConnectionStateCallback = (state: ConnectionState) => void; | ||
| /** | ||
| * A client for interacting with a Limbar instance | ||
@@ -33,2 +43,13 @@ */ | ||
| sendAsset: (url: string) => Promise<void>; | ||
| /** | ||
| * Get current connection state | ||
| */ | ||
| getConnectionState: () => ConnectionState; | ||
| /** | ||
| * Register callback for connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: ConnectionStateCallback) => () => void; | ||
| }; | ||
@@ -67,2 +88,17 @@ | ||
| logLevel?: LogLevel; | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| }; | ||
@@ -117,3 +153,11 @@ | ||
| const logLevel = options.logLevel ?? 'info'; | ||
| const maxReconnectAttempts = options.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options.maxReconnectDelay ?? 30000; | ||
| let ws: WebSocket | undefined = undefined; | ||
| let connectionState: ConnectionState = 'connecting'; | ||
| let reconnectAttempts = 0; | ||
| let reconnectTimeout: NodeJS.Timeout | undefined; | ||
| let intentionalDisconnect = false; | ||
@@ -136,2 +180,4 @@ const screenshotRequests: Map< | ||
| const stateChangeCallbacks: Set<ConnectionStateCallback> = new Set(); | ||
| // Logger functions | ||
@@ -153,101 +199,210 @@ const logger = { | ||
| const updateConnectionState = (newState: ConnectionState): void => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const failPendingRequests = (reason: string): void => { | ||
| screenshotRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| screenshotRequests.clear(); | ||
| assetRequests.forEach((request) => request.rejecter(new Error(reason))); | ||
| assetRequests.clear(); | ||
| }; | ||
| const cleanup = (): void => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { | ||
| ws.close(); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| let pingInterval: NodeJS.Timeout | undefined; | ||
| return new Promise<InstanceClient>((resolveConnection, rejectConnection) => { | ||
| logger.debug(`Attempting to connect to WebSocket server at ${serverAddress}...`); | ||
| ws = new WebSocket(serverAddress); | ||
| ws.on('message', (data: Data) => { | ||
| let message: ServerMessage; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| } catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| let hasResolved = false; | ||
| // Reconnection logic with exponential backoff | ||
| const scheduleReconnect = (): void => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| break; | ||
| } | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Giving up.`); | ||
| updateConnectionState('disconnected'); | ||
| return; | ||
| } | ||
| const screenshotMessage = message as ScreenshotResponse; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| if (!request) { | ||
| logger.warn( | ||
| `Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`, | ||
| ); | ||
| break; | ||
| } | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = (): void => { | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new WebSocket(serverAddress); | ||
| ws.on('message', (data: Data) => { | ||
| let message: ServerMessage; | ||
| try { | ||
| message = JSON.parse(data.toString()); | ||
| } catch (e) { | ||
| logger.error({ data, error: e }, 'Failed to parse JSON message'); | ||
| return; | ||
| } | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| switch (message.type) { | ||
| case 'screenshot': { | ||
| if (!('dataUri' in message) || typeof message.dataUri !== 'string' || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot message:', message); | ||
| break; | ||
| } | ||
| const screenshotMessage = message as ScreenshotResponse; | ||
| const request = screenshotRequests.get(screenshotMessage.id); | ||
| if (!request) { | ||
| logger.warn( | ||
| `Received screenshot data for unknown or already handled session: ${screenshotMessage.id}`, | ||
| ); | ||
| break; | ||
| } | ||
| logger.debug(`Received screenshot data URI for session ${screenshotMessage.id}.`); | ||
| request.resolver({ dataUri: screenshotMessage.dataUri }); | ||
| screenshotRequests.delete(screenshotMessage.id); | ||
| break; | ||
| } | ||
| case 'screenshotError': { | ||
| if (!('message' in message) || !('id' in message)) { | ||
| logger.warn('Received invalid screenshot error message:', message); | ||
| break; | ||
| } | ||
| const errorMessage = message as ScreenshotErrorResponse; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| const errorMessage = message as ScreenshotErrorResponse; | ||
| const request = screenshotRequests.get(errorMessage.id); | ||
| if (!request) { | ||
| logger.warn( | ||
| `Received screenshot error for unknown or already handled session: ${errorMessage.id}`, | ||
| if (!request) { | ||
| logger.warn( | ||
| `Received screenshot error for unknown or already handled session: ${errorMessage.id}`, | ||
| ); | ||
| break; | ||
| } | ||
| logger.error( | ||
| `Server reported an error capturing screenshot for session ${errorMessage.id}:`, | ||
| errorMessage.message, | ||
| ); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| logger.error( | ||
| `Server reported an error capturing screenshot for session ${errorMessage.id}:`, | ||
| errorMessage.message, | ||
| ); | ||
| request.rejecter(new Error(errorMessage.message)); | ||
| screenshotRequests.delete(errorMessage.id); | ||
| break; | ||
| } | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url as string); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| case 'assetResult': { | ||
| logger.debug('Received assetResult:', message); | ||
| const request = assetRequests.get(message.url as string); | ||
| if (!request) { | ||
| logger.warn(`Received assetResult for unknown or already handled url: ${message.url}`); | ||
| break; | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url as string); | ||
| break; | ||
| } | ||
| const errorMessage = | ||
| typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url as string); | ||
| break; | ||
| } | ||
| if (message.result === 'success') { | ||
| logger.debug('Asset result is success'); | ||
| request.resolver(); | ||
| assetRequests.delete(message.url as string); | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| const errorMessage = | ||
| typeof message.message === 'string' && message.message ? | ||
| message.message | ||
| : `Asset processing failed: ${JSON.stringify(message)}`; | ||
| logger.debug('Asset result is failure', errorMessage); | ||
| request.rejecter(new Error(errorMessage)); | ||
| assetRequests.delete(message.url as string); | ||
| break; | ||
| } | ||
| default: | ||
| logger.warn(`Received unexpected message type: ${message.type}`); | ||
| break; | ||
| } | ||
| }); | ||
| }); | ||
| ws.on('error', (err: Error) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (ws && (ws.readyState === WebSocket.CONNECTING || ws.readyState === WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter(err)); | ||
| }); | ||
| ws.on('error', (err: Error) => { | ||
| logger.error('WebSocket error:', err.message); | ||
| if (!hasResolved && (ws?.readyState === WebSocket.CONNECTING || ws?.readyState === WebSocket.OPEN)) { | ||
| rejectConnection(err); | ||
| } | ||
| }); | ||
| ws.on('close', () => { | ||
| logger.debug('Disconnected from server.'); | ||
| screenshotRequests.forEach((request) => request.rejecter('Disconnected from server')); | ||
| }); | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('Disconnected from server.'); | ||
| failPendingRequests('Connection closed'); | ||
| if (shouldReconnect) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
| if (ws && ws.readyState === WebSocket.OPEN) { | ||
| (ws as any).ping(); | ||
| } | ||
| }, 30_000); | ||
| if (!hasResolved) { | ||
| hasResolved = true; | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| } | ||
| }); | ||
| }; | ||
| const screenshot = async (): Promise<ScreenshotData> => { | ||
@@ -296,9 +451,20 @@ if (!ws || ws.readyState !== WebSocket.OPEN) { | ||
| const disconnect = (): void => { | ||
| if (ws) { | ||
| logger.debug('Closing WebSocket connection.'); | ||
| ws.close(); | ||
| } | ||
| screenshotRequests.forEach((request) => request.rejecter('Websocket connection closed')); | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| failPendingRequests('Intentional disconnect'); | ||
| logger.debug('Intentionally disconnected from WebSocket.'); | ||
| }; | ||
| const getConnectionState = (): ConnectionState => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback: ConnectionStateCallback): (() => void) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| /** | ||
@@ -309,16 +475,24 @@ * Opens a WebSocket TCP proxy for the ADB port and connects the local adb | ||
| const startAdbTunnel = async (): Promise<Tunnel> => { | ||
| const { address, close } = await startTcpTunnel(options.adbUrl, options.token, '127.0.0.1', 0); | ||
| const tunnel = await startTcpTunnel(options.adbUrl, options.token, '127.0.0.1', 0, { | ||
| maxReconnectAttempts, | ||
| reconnectDelay, | ||
| maxReconnectDelay, | ||
| logLevel, | ||
| }); | ||
| try { | ||
| await new Promise<void>((resolve, reject) => { | ||
| exec(`${options.adbPath ?? 'adb'} connect ${address.address}:${address.port}`, (err) => { | ||
| if (err) return reject(err); | ||
| resolve(); | ||
| }); | ||
| exec( | ||
| `${options.adbPath ?? 'adb'} connect ${tunnel.address.address}:${tunnel.address.port}`, | ||
| (err) => { | ||
| if (err) return reject(err); | ||
| resolve(); | ||
| }, | ||
| ); | ||
| }); | ||
| logger.debug(`ADB connected on ${address.address}`); | ||
| logger.debug(`ADB connected on ${tunnel.address.address}`); | ||
| } catch (err) { | ||
| close(); | ||
| tunnel.close(); | ||
| throw err; | ||
| } | ||
| return { address, close }; | ||
| return tunnel; | ||
| }; | ||
@@ -343,12 +517,6 @@ | ||
| }; | ||
| ws.on('open', () => { | ||
| logger.debug(`Connected to ${serverAddress}`); | ||
| resolveConnection({ | ||
| screenshot, | ||
| disconnect, | ||
| startAdbTunnel, | ||
| sendAsset, | ||
| }); | ||
| }); | ||
| // Start the initial connection | ||
| setupWebSocket(); | ||
| }); | ||
| } |
+262
-43
| import * as net from 'net'; | ||
| import { WebSocket } from 'ws'; | ||
| /** | ||
| * Controls the verbosity of logging in the tunnel | ||
| */ | ||
| export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug'; | ||
| /** | ||
| * Connection state of the tunnel | ||
| */ | ||
| export type TunnelConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for tunnel connection state changes | ||
| */ | ||
| export type TunnelConnectionStateCallback = (state: TunnelConnectionState) => void; | ||
| export interface Tunnel { | ||
@@ -10,13 +25,44 @@ address: { | ||
| close: () => void; | ||
| /** | ||
| * Get current WebSocket connection state | ||
| */ | ||
| getConnectionState: () => TunnelConnectionState; | ||
| /** | ||
| * Register callback for WebSocket connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: TunnelConnectionStateCallback) => () => void; | ||
| } | ||
| export interface TcpTunnelOptions { | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| /** | ||
| * Controls logging verbosity | ||
| * @default 'info' | ||
| */ | ||
| logLevel?: LogLevel; | ||
| } | ||
| /** | ||
| * Starts a one-shot TCP → WebSocket proxy. | ||
| * Starts a persistent TCP → WebSocket proxy. | ||
| * | ||
| * The function creates a local TCP server that listens on an ephemeral port on | ||
| * 127.0.0.1. As soon as the **first** TCP client connects the server stops | ||
| * accepting further connections and forwards all traffic between that client | ||
| * and `remoteURL` through an authenticated WebSocket. If you need to proxy | ||
| * more than one TCP connection, call `startTcpTunnel` again to create a new | ||
| * proxy instance. | ||
| * 127.0.0.1. When a TCP client connects, it forwards all traffic between that | ||
| * client and `remoteURL` through an authenticated WebSocket. The server remains | ||
| * active even after the client disconnects, allowing reconnection without | ||
| * recreating the tunnel. | ||
| * | ||
@@ -28,2 +74,3 @@ * @param remoteURL Remote WebSocket endpoint (e.g. wss://example.com/instance) | ||
| * to find an available non-privileged port. | ||
| * @param options Optional reconnection configuration | ||
| */ | ||
@@ -35,3 +82,26 @@ export async function startTcpTunnel( | ||
| port: number, | ||
| options?: TcpTunnelOptions, | ||
| ): Promise<Tunnel> { | ||
| const maxReconnectAttempts = options?.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options?.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options?.maxReconnectDelay ?? 30000; | ||
| const logLevel = options?.logLevel ?? 'info'; | ||
| // Logger functions | ||
| const logger = { | ||
| debug: (...args: any[]) => { | ||
| if (logLevel === 'debug') console.log('[Tunnel]', ...args); | ||
| }, | ||
| info: (...args: any[]) => { | ||
| if (logLevel === 'info' || logLevel === 'debug') console.log('[Tunnel]', ...args); | ||
| }, | ||
| warn: (...args: any[]) => { | ||
| if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug') | ||
| console.warn('[Tunnel]', ...args); | ||
| }, | ||
| error: (...args: any[]) => { | ||
| if (logLevel !== 'none') console.error('[Tunnel]', ...args); | ||
| }, | ||
| }; | ||
| return new Promise((resolve, reject) => { | ||
@@ -42,5 +112,29 @@ const server = net.createServer(); | ||
| let pingInterval: NodeJS.Timeout | undefined; | ||
| let reconnectTimeout: NodeJS.Timeout | undefined; | ||
| let reconnectAttempts = 0; | ||
| let intentionalDisconnect = false; | ||
| let tcpSocket: net.Socket | undefined; | ||
| let connectionState: TunnelConnectionState = 'connecting'; | ||
| // close helper | ||
| const close = () => { | ||
| const stateChangeCallbacks: Set<TunnelConnectionStateCallback> = new Set(); | ||
| const updateConnectionState = (newState: TunnelConnectionState): void => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const cleanup = () => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
@@ -50,5 +144,18 @@ clearInterval(pingInterval); | ||
| } | ||
| if (ws && ws.readyState === WebSocket.OPEN) { | ||
| ws.close(1000, 'close'); | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { | ||
| ws.close(1000, 'close'); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| const close = () => { | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| } | ||
| if (server.listening) { | ||
@@ -59,25 +166,40 @@ server.close(); | ||
| // No AbortController support – proxy can be closed via the returned handle | ||
| const scheduleReconnect = (): void => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.debug('Skipping reconnection (TCP socket closed)'); | ||
| return; | ||
| } | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Closing tunnel.`); | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| return; | ||
| } | ||
| resolve({ address, close }); | ||
| }); | ||
| // On first TCP connection | ||
| server.on('connection', (tcpSocket) => { | ||
| // Single-connection proxy | ||
| server.close(); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = (): void => { | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.error('Cannot setup WebSocket: TCP socket is closed'); | ||
| return; | ||
| } | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new WebSocket(remoteURL, { | ||
@@ -88,12 +210,34 @@ headers: { Authorization: `Bearer ${token}` }, | ||
| // WebSocket error | ||
| ws.once('error', (err: any) => { | ||
| console.error('WebSocket error:', err); | ||
| tcpSocket.destroy(); | ||
| close(); | ||
| ws.on('error', (err: any) => { | ||
| logger.error('WebSocket error:', err.message || err); | ||
| }); | ||
| ws.once('open', () => { | ||
| const socket = ws as WebSocket; // non-undefined after open | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('WebSocket disconnected'); | ||
| // Pause TCP socket to apply backpressure - TCP will handle buffering | ||
| if (tcpSocket && !tcpSocket.destroyed && !tcpSocket.isPaused()) { | ||
| logger.debug('Pausing TCP socket (applying backpressure)'); | ||
| tcpSocket.pause(); | ||
| } | ||
| if (shouldReconnect && tcpSocket && !tcpSocket.destroyed) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| const socket = ws as WebSocket; | ||
| logger.debug('WebSocket connected'); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
@@ -105,12 +249,23 @@ if (socket.readyState === WebSocket.OPEN) { | ||
| // TCP → WS | ||
| tcpSocket.on('data', (chunk) => { | ||
| // Resume TCP socket - queued data will flow through | ||
| if (tcpSocket && tcpSocket.isPaused()) { | ||
| logger.debug('Resuming TCP socket (releasing backpressure)'); | ||
| tcpSocket.resume(); | ||
| } | ||
| // TCP → WS: Forward data directly | ||
| const onTcpData = (chunk: Buffer) => { | ||
| if (socket.readyState === WebSocket.OPEN) { | ||
| socket.send(chunk); | ||
| } | ||
| }); | ||
| // If WebSocket is not ready, data will queue in TCP buffers (backpressure) | ||
| }; | ||
| // Remove old listener if exists and add new one | ||
| tcpSocket!.removeListener('data', onTcpData); | ||
| tcpSocket!.on('data', onTcpData); | ||
| // WS → TCP | ||
| socket.on('message', (data: any) => { | ||
| if (!tcpSocket.destroyed) { | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.write(data as Buffer); | ||
@@ -120,11 +275,75 @@ } | ||
| }); | ||
| }; | ||
| // Mutual close | ||
| tcpSocket.on('close', close); | ||
| tcpSocket.on('error', (err: any) => { | ||
| console.error('TCP socket error:', err); | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| const getConnectionState = (): TunnelConnectionState => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback: TunnelConnectionStateCallback): (() => void) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| } | ||
| resolve({ | ||
| address, | ||
| close, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| }); | ||
| ws.on('close', () => tcpSocket.destroy()); | ||
| // Helper to clean up current connection but keep server alive | ||
| const cleanupConnection = () => { | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| tcpSocket = undefined; | ||
| } | ||
| // Reset reconnection state for next connection | ||
| reconnectAttempts = 0; | ||
| intentionalDisconnect = false; | ||
| logger.debug('Connection cleaned up, ready for new TCP connection'); | ||
| }; | ||
| // On TCP connection (can happen multiple times) | ||
| server.on('connection', (socket) => { | ||
| // If there's already an active connection, reject the new one | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| logger.debug('Rejecting new TCP connection - already have an active connection'); | ||
| socket.destroy(); | ||
| return; | ||
| } | ||
| logger.debug('TCP client connected'); | ||
| tcpSocket = socket; | ||
| // TCP socket handlers | ||
| tcpSocket.on('close', () => { | ||
| logger.debug('TCP socket closed by client'); | ||
| cleanupConnection(); | ||
| }); | ||
| tcpSocket.on('error', (err: any) => { | ||
| logger.error('TCP socket error:', err); | ||
| cleanupConnection(); | ||
| }); | ||
| // Start WebSocket connection | ||
| setupWebSocket(); | ||
| }); | ||
@@ -131,0 +350,0 @@ |
+1
-1
@@ -1,1 +0,1 @@ | ||
| export const VERSION = '0.13.1'; // x-release-please-version | ||
| export const VERSION = '0.13.2'; // x-release-please-version |
+50
-7
@@ -0,1 +1,13 @@ | ||
| /** | ||
| * Controls the verbosity of logging in the tunnel | ||
| */ | ||
| export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug'; | ||
| /** | ||
| * Connection state of the tunnel | ||
| */ | ||
| export type TunnelConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for tunnel connection state changes | ||
| */ | ||
| export type TunnelConnectionStateCallback = (state: TunnelConnectionState) => void; | ||
| export interface Tunnel { | ||
@@ -7,12 +19,42 @@ address: { | ||
| close: () => void; | ||
| /** | ||
| * Get current WebSocket connection state | ||
| */ | ||
| getConnectionState: () => TunnelConnectionState; | ||
| /** | ||
| * Register callback for WebSocket connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: TunnelConnectionStateCallback) => () => void; | ||
| } | ||
| export interface TcpTunnelOptions { | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| /** | ||
| * Controls logging verbosity | ||
| * @default 'info' | ||
| */ | ||
| logLevel?: LogLevel; | ||
| } | ||
| /** | ||
| * Starts a one-shot TCP → WebSocket proxy. | ||
| * Starts a persistent TCP → WebSocket proxy. | ||
| * | ||
| * The function creates a local TCP server that listens on an ephemeral port on | ||
| * 127.0.0.1. As soon as the **first** TCP client connects the server stops | ||
| * accepting further connections and forwards all traffic between that client | ||
| * and `remoteURL` through an authenticated WebSocket. If you need to proxy | ||
| * more than one TCP connection, call `startTcpTunnel` again to create a new | ||
| * proxy instance. | ||
| * 127.0.0.1. When a TCP client connects, it forwards all traffic between that | ||
| * client and `remoteURL` through an authenticated WebSocket. The server remains | ||
| * active even after the client disconnects, allowing reconnection without | ||
| * recreating the tunnel. | ||
| * | ||
@@ -24,4 +66,5 @@ * @param remoteURL Remote WebSocket endpoint (e.g. wss://example.com/instance) | ||
| * to find an available non-privileged port. | ||
| * @param options Optional reconnection configuration | ||
| */ | ||
| export declare function startTcpTunnel(remoteURL: string, token: string, hostname: string, port: number): Promise<Tunnel>; | ||
| export declare function startTcpTunnel(remoteURL: string, token: string, hostname: string, port: number, options?: TcpTunnelOptions): Promise<Tunnel>; | ||
| //# sourceMappingURL=tunnel.d.mts.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"tunnel.d.mts","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA6FjB"} | ||
| {"version":3,"file":"tunnel.d.mts","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAEjG;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAEnF,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;OAEG;IACH,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;IAChD;;;OAGG;IACH,uBAAuB,EAAE,CAAC,QAAQ,EAAE,6BAA6B,KAAK,MAAM,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,CAwQjB"} |
+50
-7
@@ -0,1 +1,13 @@ | ||
| /** | ||
| * Controls the verbosity of logging in the tunnel | ||
| */ | ||
| export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug'; | ||
| /** | ||
| * Connection state of the tunnel | ||
| */ | ||
| export type TunnelConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting'; | ||
| /** | ||
| * Callback function for tunnel connection state changes | ||
| */ | ||
| export type TunnelConnectionStateCallback = (state: TunnelConnectionState) => void; | ||
| export interface Tunnel { | ||
@@ -7,12 +19,42 @@ address: { | ||
| close: () => void; | ||
| /** | ||
| * Get current WebSocket connection state | ||
| */ | ||
| getConnectionState: () => TunnelConnectionState; | ||
| /** | ||
| * Register callback for WebSocket connection state changes | ||
| * @returns A function to unregister the callback | ||
| */ | ||
| onConnectionStateChange: (callback: TunnelConnectionStateCallback) => () => void; | ||
| } | ||
| export interface TcpTunnelOptions { | ||
| /** | ||
| * Maximum number of reconnection attempts | ||
| * @default 6 | ||
| */ | ||
| maxReconnectAttempts?: number; | ||
| /** | ||
| * Initial reconnection delay in milliseconds | ||
| * @default 1000 | ||
| */ | ||
| reconnectDelay?: number; | ||
| /** | ||
| * Maximum reconnection delay in milliseconds | ||
| * @default 30000 | ||
| */ | ||
| maxReconnectDelay?: number; | ||
| /** | ||
| * Controls logging verbosity | ||
| * @default 'info' | ||
| */ | ||
| logLevel?: LogLevel; | ||
| } | ||
| /** | ||
| * Starts a one-shot TCP → WebSocket proxy. | ||
| * Starts a persistent TCP → WebSocket proxy. | ||
| * | ||
| * The function creates a local TCP server that listens on an ephemeral port on | ||
| * 127.0.0.1. As soon as the **first** TCP client connects the server stops | ||
| * accepting further connections and forwards all traffic between that client | ||
| * and `remoteURL` through an authenticated WebSocket. If you need to proxy | ||
| * more than one TCP connection, call `startTcpTunnel` again to create a new | ||
| * proxy instance. | ||
| * 127.0.0.1. When a TCP client connects, it forwards all traffic between that | ||
| * client and `remoteURL` through an authenticated WebSocket. The server remains | ||
| * active even after the client disconnects, allowing reconnection without | ||
| * recreating the tunnel. | ||
| * | ||
@@ -24,4 +66,5 @@ * @param remoteURL Remote WebSocket endpoint (e.g. wss://example.com/instance) | ||
| * to find an available non-privileged port. | ||
| * @param options Optional reconnection configuration | ||
| */ | ||
| export declare function startTcpTunnel(remoteURL: string, token: string, hostname: string, port: number): Promise<Tunnel>; | ||
| export declare function startTcpTunnel(remoteURL: string, token: string, hostname: string, port: number, options?: TcpTunnelOptions): Promise<Tunnel>; | ||
| //# sourceMappingURL=tunnel.d.ts.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA6FjB"} | ||
| {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAEjG;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAEnF,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;OAEG;IACH,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;IAChD;;;OAGG;IACH,uBAAuB,EAAE,CAAC,QAAQ,EAAE,6BAA6B,KAAK,MAAM,IAAI,CAAC;CAClF;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC,CAwQjB"} |
+195
-44
@@ -8,10 +8,9 @@ "use strict"; | ||
| /** | ||
| * Starts a one-shot TCP → WebSocket proxy. | ||
| * Starts a persistent TCP → WebSocket proxy. | ||
| * | ||
| * The function creates a local TCP server that listens on an ephemeral port on | ||
| * 127.0.0.1. As soon as the **first** TCP client connects the server stops | ||
| * accepting further connections and forwards all traffic between that client | ||
| * and `remoteURL` through an authenticated WebSocket. If you need to proxy | ||
| * more than one TCP connection, call `startTcpTunnel` again to create a new | ||
| * proxy instance. | ||
| * 127.0.0.1. When a TCP client connects, it forwards all traffic between that | ||
| * client and `remoteURL` through an authenticated WebSocket. The server remains | ||
| * active even after the client disconnects, allowing reconnection without | ||
| * recreating the tunnel. | ||
| * | ||
@@ -23,4 +22,28 @@ * @param remoteURL Remote WebSocket endpoint (e.g. wss://example.com/instance) | ||
| * to find an available non-privileged port. | ||
| * @param options Optional reconnection configuration | ||
| */ | ||
| async function startTcpTunnel(remoteURL, token, hostname, port) { | ||
| async function startTcpTunnel(remoteURL, token, hostname, port, options) { | ||
| const maxReconnectAttempts = options?.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options?.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options?.maxReconnectDelay ?? 30000; | ||
| const logLevel = options?.logLevel ?? 'info'; | ||
| // Logger functions | ||
| const logger = { | ||
| debug: (...args) => { | ||
| if (logLevel === 'debug') | ||
| console.log('[Tunnel]', ...args); | ||
| }, | ||
| info: (...args) => { | ||
| if (logLevel === 'info' || logLevel === 'debug') | ||
| console.log('[Tunnel]', ...args); | ||
| }, | ||
| warn: (...args) => { | ||
| if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug') | ||
| console.warn('[Tunnel]', ...args); | ||
| }, | ||
| error: (...args) => { | ||
| if (logLevel !== 'none') | ||
| console.error('[Tunnel]', ...args); | ||
| }, | ||
| }; | ||
| return new Promise((resolve, reject) => { | ||
@@ -30,4 +53,27 @@ const server = net.createServer(); | ||
| let pingInterval; | ||
| // close helper | ||
| const close = () => { | ||
| let reconnectTimeout; | ||
| let reconnectAttempts = 0; | ||
| let intentionalDisconnect = false; | ||
| let tcpSocket; | ||
| let connectionState = 'connecting'; | ||
| const stateChangeCallbacks = new Set(); | ||
| const updateConnectionState = (newState) => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } | ||
| catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const cleanup = () => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
@@ -37,5 +83,17 @@ clearInterval(pingInterval); | ||
| } | ||
| if (ws && ws.readyState === ws_1.WebSocket.OPEN) { | ||
| ws.close(1000, 'close'); | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === ws_1.WebSocket.OPEN || ws.readyState === ws_1.WebSocket.CONNECTING) { | ||
| ws.close(1000, 'close'); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| const close = () => { | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| } | ||
| if (server.listening) { | ||
@@ -45,21 +103,32 @@ server.close(); | ||
| }; | ||
| // No AbortController support – proxy can be closed via the returned handle | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| const scheduleReconnect = () => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.debug('Skipping reconnection (TCP socket closed)'); | ||
| return; | ||
| } | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Closing tunnel.`); | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| return; | ||
| } | ||
| resolve({ address, close }); | ||
| }); | ||
| // On first TCP connection | ||
| server.on('connection', (tcpSocket) => { | ||
| // Single-connection proxy | ||
| server.close(); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = () => { | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.error('Cannot setup WebSocket: TCP socket is closed'); | ||
| return; | ||
| } | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new ws_1.WebSocket(remoteURL, { | ||
@@ -69,10 +138,27 @@ headers: { Authorization: `Bearer ${token}` }, | ||
| }); | ||
| // WebSocket error | ||
| ws.once('error', (err) => { | ||
| console.error('WebSocket error:', err); | ||
| tcpSocket.destroy(); | ||
| close(); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message || err); | ||
| }); | ||
| ws.once('open', () => { | ||
| const socket = ws; // non-undefined after open | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('WebSocket disconnected'); | ||
| // Pause TCP socket to apply backpressure - TCP will handle buffering | ||
| if (tcpSocket && !tcpSocket.destroyed && !tcpSocket.isPaused()) { | ||
| logger.debug('Pausing TCP socket (applying backpressure)'); | ||
| tcpSocket.pause(); | ||
| } | ||
| if (shouldReconnect && tcpSocket && !tcpSocket.destroyed) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| const socket = ws; | ||
| logger.debug('WebSocket connected'); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
@@ -83,11 +169,20 @@ if (socket.readyState === ws_1.WebSocket.OPEN) { | ||
| }, 30000); | ||
| // TCP → WS | ||
| tcpSocket.on('data', (chunk) => { | ||
| // Resume TCP socket - queued data will flow through | ||
| if (tcpSocket && tcpSocket.isPaused()) { | ||
| logger.debug('Resuming TCP socket (releasing backpressure)'); | ||
| tcpSocket.resume(); | ||
| } | ||
| // TCP → WS: Forward data directly | ||
| const onTcpData = (chunk) => { | ||
| if (socket.readyState === ws_1.WebSocket.OPEN) { | ||
| socket.send(chunk); | ||
| } | ||
| }); | ||
| // If WebSocket is not ready, data will queue in TCP buffers (backpressure) | ||
| }; | ||
| // Remove old listener if exists and add new one | ||
| tcpSocket.removeListener('data', onTcpData); | ||
| tcpSocket.on('data', onTcpData); | ||
| // WS → TCP | ||
| socket.on('message', (data) => { | ||
| if (!tcpSocket.destroyed) { | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.write(data); | ||
@@ -97,10 +192,66 @@ } | ||
| }); | ||
| // Mutual close | ||
| tcpSocket.on('close', close); | ||
| tcpSocket.on('error', (err) => { | ||
| console.error('TCP socket error:', err); | ||
| }; | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| const getConnectionState = () => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| } | ||
| resolve({ | ||
| address, | ||
| close, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| ws.on('close', () => tcpSocket.destroy()); | ||
| }); | ||
| // Helper to clean up current connection but keep server alive | ||
| const cleanupConnection = () => { | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| tcpSocket = undefined; | ||
| } | ||
| // Reset reconnection state for next connection | ||
| reconnectAttempts = 0; | ||
| intentionalDisconnect = false; | ||
| logger.debug('Connection cleaned up, ready for new TCP connection'); | ||
| }; | ||
| // On TCP connection (can happen multiple times) | ||
| server.on('connection', (socket) => { | ||
| // If there's already an active connection, reject the new one | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| logger.debug('Rejecting new TCP connection - already have an active connection'); | ||
| socket.destroy(); | ||
| return; | ||
| } | ||
| logger.debug('TCP client connected'); | ||
| tcpSocket = socket; | ||
| // TCP socket handlers | ||
| tcpSocket.on('close', () => { | ||
| logger.debug('TCP socket closed by client'); | ||
| cleanupConnection(); | ||
| }); | ||
| tcpSocket.on('error', (err) => { | ||
| logger.error('TCP socket error:', err); | ||
| cleanupConnection(); | ||
| }); | ||
| // Start WebSocket connection | ||
| setupWebSocket(); | ||
| }); | ||
| // Start listening | ||
@@ -107,0 +258,0 @@ server.listen(port, hostname); |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"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"} |
+195
-44
| import * as net from 'net'; | ||
| import { WebSocket } from 'ws'; | ||
| /** | ||
| * Starts a one-shot TCP → WebSocket proxy. | ||
| * Starts a persistent TCP → WebSocket proxy. | ||
| * | ||
| * The function creates a local TCP server that listens on an ephemeral port on | ||
| * 127.0.0.1. As soon as the **first** TCP client connects the server stops | ||
| * accepting further connections and forwards all traffic between that client | ||
| * and `remoteURL` through an authenticated WebSocket. If you need to proxy | ||
| * more than one TCP connection, call `startTcpTunnel` again to create a new | ||
| * proxy instance. | ||
| * 127.0.0.1. When a TCP client connects, it forwards all traffic between that | ||
| * client and `remoteURL` through an authenticated WebSocket. The server remains | ||
| * active even after the client disconnects, allowing reconnection without | ||
| * recreating the tunnel. | ||
| * | ||
@@ -18,4 +17,28 @@ * @param remoteURL Remote WebSocket endpoint (e.g. wss://example.com/instance) | ||
| * to find an available non-privileged port. | ||
| * @param options Optional reconnection configuration | ||
| */ | ||
| export async function startTcpTunnel(remoteURL, token, hostname, port) { | ||
| export async function startTcpTunnel(remoteURL, token, hostname, port, options) { | ||
| const maxReconnectAttempts = options?.maxReconnectAttempts ?? 6; | ||
| const reconnectDelay = options?.reconnectDelay ?? 1000; | ||
| const maxReconnectDelay = options?.maxReconnectDelay ?? 30000; | ||
| const logLevel = options?.logLevel ?? 'info'; | ||
| // Logger functions | ||
| const logger = { | ||
| debug: (...args) => { | ||
| if (logLevel === 'debug') | ||
| console.log('[Tunnel]', ...args); | ||
| }, | ||
| info: (...args) => { | ||
| if (logLevel === 'info' || logLevel === 'debug') | ||
| console.log('[Tunnel]', ...args); | ||
| }, | ||
| warn: (...args) => { | ||
| if (logLevel === 'warn' || logLevel === 'info' || logLevel === 'debug') | ||
| console.warn('[Tunnel]', ...args); | ||
| }, | ||
| error: (...args) => { | ||
| if (logLevel !== 'none') | ||
| console.error('[Tunnel]', ...args); | ||
| }, | ||
| }; | ||
| return new Promise((resolve, reject) => { | ||
@@ -25,4 +48,27 @@ const server = net.createServer(); | ||
| let pingInterval; | ||
| // close helper | ||
| const close = () => { | ||
| let reconnectTimeout; | ||
| let reconnectAttempts = 0; | ||
| let intentionalDisconnect = false; | ||
| let tcpSocket; | ||
| let connectionState = 'connecting'; | ||
| const stateChangeCallbacks = new Set(); | ||
| const updateConnectionState = (newState) => { | ||
| if (connectionState !== newState) { | ||
| connectionState = newState; | ||
| logger.debug(`Connection state changed to: ${newState}`); | ||
| stateChangeCallbacks.forEach((callback) => { | ||
| try { | ||
| callback(newState); | ||
| } | ||
| catch (err) { | ||
| logger.error('Error in connection state callback:', err); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| const cleanup = () => { | ||
| if (reconnectTimeout) { | ||
| clearTimeout(reconnectTimeout); | ||
| reconnectTimeout = undefined; | ||
| } | ||
| if (pingInterval) { | ||
@@ -32,5 +78,17 @@ clearInterval(pingInterval); | ||
| } | ||
| if (ws && ws.readyState === WebSocket.OPEN) { | ||
| ws.close(1000, 'close'); | ||
| if (ws) { | ||
| ws.removeAllListeners(); | ||
| if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) { | ||
| ws.close(1000, 'close'); | ||
| } | ||
| ws = undefined; | ||
| } | ||
| }; | ||
| const close = () => { | ||
| intentionalDisconnect = true; | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| } | ||
| if (server.listening) { | ||
@@ -40,21 +98,32 @@ server.close(); | ||
| }; | ||
| // No AbortController support – proxy can be closed via the returned handle | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| const scheduleReconnect = () => { | ||
| if (intentionalDisconnect) { | ||
| logger.debug('Skipping reconnection (intentional disconnect)'); | ||
| return; | ||
| } | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.debug('Skipping reconnection (TCP socket closed)'); | ||
| return; | ||
| } | ||
| if (reconnectAttempts >= maxReconnectAttempts) { | ||
| logger.error(`Max reconnection attempts (${maxReconnectAttempts}) reached. Closing tunnel.`); | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| return; | ||
| } | ||
| resolve({ address, close }); | ||
| }); | ||
| // On first TCP connection | ||
| server.on('connection', (tcpSocket) => { | ||
| // Single-connection proxy | ||
| server.close(); | ||
| const currentDelay = Math.min(reconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay); | ||
| reconnectAttempts++; | ||
| logger.debug(`Scheduling reconnection attempt ${reconnectAttempts} in ${currentDelay}ms...`); | ||
| updateConnectionState('reconnecting'); | ||
| reconnectTimeout = setTimeout(() => { | ||
| logger.debug(`Attempting to reconnect (attempt ${reconnectAttempts})...`); | ||
| setupWebSocket(); | ||
| }, currentDelay); | ||
| }; | ||
| const setupWebSocket = () => { | ||
| if (!tcpSocket || tcpSocket.destroyed) { | ||
| logger.error('Cannot setup WebSocket: TCP socket is closed'); | ||
| return; | ||
| } | ||
| cleanup(); | ||
| updateConnectionState('connecting'); | ||
| ws = new WebSocket(remoteURL, { | ||
@@ -64,10 +133,27 @@ headers: { Authorization: `Bearer ${token}` }, | ||
| }); | ||
| // WebSocket error | ||
| ws.once('error', (err) => { | ||
| console.error('WebSocket error:', err); | ||
| tcpSocket.destroy(); | ||
| close(); | ||
| ws.on('error', (err) => { | ||
| logger.error('WebSocket error:', err.message || err); | ||
| }); | ||
| ws.once('open', () => { | ||
| const socket = ws; // non-undefined after open | ||
| ws.on('close', () => { | ||
| if (pingInterval) { | ||
| clearInterval(pingInterval); | ||
| pingInterval = undefined; | ||
| } | ||
| const shouldReconnect = !intentionalDisconnect && connectionState !== 'disconnected'; | ||
| updateConnectionState('disconnected'); | ||
| logger.debug('WebSocket disconnected'); | ||
| // Pause TCP socket to apply backpressure - TCP will handle buffering | ||
| if (tcpSocket && !tcpSocket.destroyed && !tcpSocket.isPaused()) { | ||
| logger.debug('Pausing TCP socket (applying backpressure)'); | ||
| tcpSocket.pause(); | ||
| } | ||
| if (shouldReconnect && tcpSocket && !tcpSocket.destroyed) { | ||
| scheduleReconnect(); | ||
| } | ||
| }); | ||
| ws.on('open', () => { | ||
| const socket = ws; | ||
| logger.debug('WebSocket connected'); | ||
| reconnectAttempts = 0; | ||
| updateConnectionState('connected'); | ||
| pingInterval = setInterval(() => { | ||
@@ -78,11 +164,20 @@ if (socket.readyState === WebSocket.OPEN) { | ||
| }, 30000); | ||
| // TCP → WS | ||
| tcpSocket.on('data', (chunk) => { | ||
| // Resume TCP socket - queued data will flow through | ||
| if (tcpSocket && tcpSocket.isPaused()) { | ||
| logger.debug('Resuming TCP socket (releasing backpressure)'); | ||
| tcpSocket.resume(); | ||
| } | ||
| // TCP → WS: Forward data directly | ||
| const onTcpData = (chunk) => { | ||
| if (socket.readyState === WebSocket.OPEN) { | ||
| socket.send(chunk); | ||
| } | ||
| }); | ||
| // If WebSocket is not ready, data will queue in TCP buffers (backpressure) | ||
| }; | ||
| // Remove old listener if exists and add new one | ||
| tcpSocket.removeListener('data', onTcpData); | ||
| tcpSocket.on('data', onTcpData); | ||
| // WS → TCP | ||
| socket.on('message', (data) => { | ||
| if (!tcpSocket.destroyed) { | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.write(data); | ||
@@ -92,10 +187,66 @@ } | ||
| }); | ||
| // Mutual close | ||
| tcpSocket.on('close', close); | ||
| tcpSocket.on('error', (err) => { | ||
| console.error('TCP socket error:', err); | ||
| }; | ||
| // TCP server error | ||
| server.once('error', (err) => { | ||
| close(); | ||
| reject(new Error(`TCP server error: ${err.message}`)); | ||
| }); | ||
| const getConnectionState = () => { | ||
| return connectionState; | ||
| }; | ||
| const onConnectionStateChange = (callback) => { | ||
| stateChangeCallbacks.add(callback); | ||
| return () => { | ||
| stateChangeCallbacks.delete(callback); | ||
| }; | ||
| }; | ||
| // Listening | ||
| server.once('listening', () => { | ||
| const address = server.address(); | ||
| if (!address || typeof address === 'string') { | ||
| close(); | ||
| return reject(new Error('Failed to obtain listening address')); | ||
| } | ||
| resolve({ | ||
| address, | ||
| close, | ||
| getConnectionState, | ||
| onConnectionStateChange, | ||
| }); | ||
| ws.on('close', () => tcpSocket.destroy()); | ||
| }); | ||
| // Helper to clean up current connection but keep server alive | ||
| const cleanupConnection = () => { | ||
| cleanup(); | ||
| updateConnectionState('disconnected'); | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| tcpSocket.destroy(); | ||
| tcpSocket = undefined; | ||
| } | ||
| // Reset reconnection state for next connection | ||
| reconnectAttempts = 0; | ||
| intentionalDisconnect = false; | ||
| logger.debug('Connection cleaned up, ready for new TCP connection'); | ||
| }; | ||
| // On TCP connection (can happen multiple times) | ||
| server.on('connection', (socket) => { | ||
| // If there's already an active connection, reject the new one | ||
| if (tcpSocket && !tcpSocket.destroyed) { | ||
| logger.debug('Rejecting new TCP connection - already have an active connection'); | ||
| socket.destroy(); | ||
| return; | ||
| } | ||
| logger.debug('TCP client connected'); | ||
| tcpSocket = socket; | ||
| // TCP socket handlers | ||
| tcpSocket.on('close', () => { | ||
| logger.debug('TCP socket closed by client'); | ||
| cleanupConnection(); | ||
| }); | ||
| tcpSocket.on('error', (err) => { | ||
| logger.error('TCP socket error:', err); | ||
| cleanupConnection(); | ||
| }); | ||
| // Start WebSocket connection | ||
| setupWebSocket(); | ||
| }); | ||
| // Start listening | ||
@@ -102,0 +253,0 @@ server.listen(port, hostname); |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"tunnel.mjs","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"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"} | ||
| {"version":3,"file":"tunnel.mjs","sourceRoot":"","sources":["src/tunnel.ts"],"names":[],"mappings":"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"} |
+1
-1
@@ -1,2 +0,2 @@ | ||
| export declare const VERSION = "0.13.1"; | ||
| export declare const VERSION = "0.13.2"; | ||
| //# sourceMappingURL=version.d.mts.map |
+1
-1
@@ -1,2 +0,2 @@ | ||
| export declare const VERSION = "0.13.1"; | ||
| export declare const VERSION = "0.13.2"; | ||
| //# sourceMappingURL=version.d.ts.map |
+1
-1
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.VERSION = void 0; | ||
| exports.VERSION = '0.13.1'; // x-release-please-version | ||
| exports.VERSION = '0.13.2'; // x-release-please-version | ||
| //# sourceMappingURL=version.js.map |
+1
-1
@@ -1,2 +0,2 @@ | ||
| export const VERSION = '0.13.1'; // x-release-please-version | ||
| export const VERSION = '0.13.2'; // x-release-please-version | ||
| //# sourceMappingURL=version.mjs.map |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
773039
7.7%10433
9.67%