@rushstack/playwright-browser-tunnel 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/chunked-rush-logs/playwright-browser-tunnel._phase_build.chunks.jsonl +3 -3
- package/.rush/temp/operation/_phase_build/all.log +3 -3
- package/.rush/temp/operation/_phase_build/log-chunks.jsonl +3 -3
- package/.rush/temp/operation/_phase_build/state.json +1 -1
- package/.rush/temp/rushstack+playwright-browser-tunnel-_phase_build-517a2999ebe527b217bbfe2e265943b73bf3856b.tar.log +62 -0
- package/CHANGELOG.json +12 -0
- package/CHANGELOG.md +8 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/tunneledBrowserConnection/ITunneledBrowser.d.ts +17 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowser.d.ts.map +1 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowser.js +5 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowser.js.map +1 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowserConnection.d.ts +31 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowserConnection.d.ts.map +1 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowserConnection.js +5 -0
- package/lib/tunneledBrowserConnection/ITunneledBrowserConnection.js.map +1 -0
- package/lib/tunneledBrowserConnection/TunneledBrowser.d.ts +10 -0
- package/lib/tunneledBrowserConnection/TunneledBrowser.d.ts.map +1 -0
- package/lib/tunneledBrowserConnection/TunneledBrowser.js +42 -0
- package/lib/tunneledBrowserConnection/TunneledBrowser.js.map +1 -0
- package/lib/tunneledBrowserConnection/TunneledBrowserConnection.d.ts +8 -0
- package/lib/tunneledBrowserConnection/TunneledBrowserConnection.d.ts.map +1 -0
- package/lib/{tunneledBrowserConnection.js → tunneledBrowserConnection/TunneledBrowserConnection.js} +8 -41
- package/lib/tunneledBrowserConnection/TunneledBrowserConnection.js.map +1 -0
- package/lib/tunneledBrowserConnection/constants.d.ts +3 -0
- package/lib/tunneledBrowserConnection/constants.d.ts.map +1 -0
- package/lib/tunneledBrowserConnection/constants.js +8 -0
- package/lib/tunneledBrowserConnection/constants.js.map +1 -0
- package/lib/tunneledBrowserConnection/index.d.ts +5 -0
- package/lib/tunneledBrowserConnection/index.d.ts.map +1 -0
- package/lib/tunneledBrowserConnection/index.js +10 -0
- package/lib/tunneledBrowserConnection/index.js.map +1 -0
- package/package.json +1 -1
- package/rush-logs/playwright-browser-tunnel._phase_build.cache.log +1 -1
- package/rush-logs/playwright-browser-tunnel._phase_build.log +3 -3
- package/src/tunneledBrowserConnection/ITunneledBrowser.ts +20 -0
- package/src/tunneledBrowserConnection/ITunneledBrowserConnection.ts +37 -0
- package/src/tunneledBrowserConnection/TunneledBrowser.ts +52 -0
- package/src/{tunneledBrowserConnection.ts → tunneledBrowserConnection/TunneledBrowserConnection.ts} +13 -96
- package/src/tunneledBrowserConnection/constants.ts +5 -0
- package/src/tunneledBrowserConnection/index.ts +8 -0
- package/temp/build/lint/_eslint-5eVG3S6w.json +23 -3
- package/temp/build/lint/lint.sarif +34 -9
- package/temp/build/typescript/ts_l9Fw4VUO.json +1 -1
- package/.rush/temp/rushstack+playwright-browser-tunnel-_phase_build-4eb4ec7f886146b53970b110944f3028a28c72d5.tar.log +0 -42
- package/lib/tunneledBrowserConnection.d.ts +0 -48
- package/lib/tunneledBrowserConnection.d.ts.map +0 -1
- package/lib/tunneledBrowserConnection.js.map +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{"kind":"O","text":" ---- build started ---- \n"}
|
|
3
3
|
{"kind":"O","text":"[build:typescript] Using TypeScript version 5.8.2\n"}
|
|
4
4
|
{"kind":"O","text":"[build:lint] Using ESLint version 9.37.0\n"}
|
|
5
|
-
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.56.
|
|
5
|
+
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.56.3\n"}
|
|
6
6
|
{"kind":"O","text":"[build:api-extractor] Analysis will use the bundled TypeScript version 5.8.2\n"}
|
|
7
|
-
{"kind":"O","text":" ---- build finished (22.
|
|
8
|
-
{"kind":"O","text":"\u001b[1m\u001b[32m-------------------- Finished (22.
|
|
7
|
+
{"kind":"O","text":" ---- build finished (22.551s) ---- \n"}
|
|
8
|
+
{"kind":"O","text":"\u001b[1m\u001b[32m-------------------- Finished (22.555s) --------------------\u001b[39m\u001b[22m\n"}
|
|
@@ -2,7 +2,7 @@ Invoking: heft run --only build -- --clean --production
|
|
|
2
2
|
---- build started ----
|
|
3
3
|
[build:typescript] Using TypeScript version 5.8.2
|
|
4
4
|
[build:lint] Using ESLint version 9.37.0
|
|
5
|
-
[build:api-extractor] Using API Extractor version 7.56.
|
|
5
|
+
[build:api-extractor] Using API Extractor version 7.56.3
|
|
6
6
|
[build:api-extractor] Analysis will use the bundled TypeScript version 5.8.2
|
|
7
|
-
---- build finished (22.
|
|
8
|
-
-------------------- Finished (22.
|
|
7
|
+
---- build finished (22.551s) ----
|
|
8
|
+
-------------------- Finished (22.555s) --------------------
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
{"kind":"O","text":" ---- build started ---- \n"}
|
|
3
3
|
{"kind":"O","text":"[build:typescript] Using TypeScript version 5.8.2\n"}
|
|
4
4
|
{"kind":"O","text":"[build:lint] Using ESLint version 9.37.0\n"}
|
|
5
|
-
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.56.
|
|
5
|
+
{"kind":"O","text":"[build:api-extractor] Using API Extractor version 7.56.3\n"}
|
|
6
6
|
{"kind":"O","text":"[build:api-extractor] Analysis will use the bundled TypeScript version 5.8.2\n"}
|
|
7
|
-
{"kind":"O","text":" ---- build finished (22.
|
|
8
|
-
{"kind":"O","text":"\u001b[1m\u001b[32m-------------------- Finished (22.
|
|
7
|
+
{"kind":"O","text":" ---- build finished (22.551s) ---- \n"}
|
|
8
|
+
{"kind":"O","text":"\u001b[1m\u001b[32m-------------------- Finished (22.555s) --------------------\u001b[39m\u001b[22m\n"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Start time: Wed Feb 11 2026 23:09:49 GMT+0000 (Coordinated Universal Time)
|
|
2
|
+
Invoking "/usr/bin/tar -c -f /mnt/vss/_work/1/s/common/temp/build-cache/rushstack+playwright-browser-tunnel-_phase_build-517a2999ebe527b217bbfe2e265943b73bf3856b-1ae738c4b6896bea.temp -z --files-from=-"
|
|
3
|
+
|
|
4
|
+
======= BEGIN PROCESS INPUT ======
|
|
5
|
+
.rush/temp/operation/_phase_build/all.log
|
|
6
|
+
.rush/temp/operation/_phase_build/log-chunks.jsonl
|
|
7
|
+
.rush/temp/operation/_phase_build/state.json
|
|
8
|
+
dist/playwright-browser-tunnel.d.ts
|
|
9
|
+
lib/HttpServer.d.ts
|
|
10
|
+
lib/HttpServer.d.ts.map
|
|
11
|
+
lib/HttpServer.js
|
|
12
|
+
lib/HttpServer.js.map
|
|
13
|
+
lib/LaunchOptionsValidator.d.ts
|
|
14
|
+
lib/LaunchOptionsValidator.d.ts.map
|
|
15
|
+
lib/LaunchOptionsValidator.js
|
|
16
|
+
lib/LaunchOptionsValidator.js.map
|
|
17
|
+
lib/PlaywrightBrowserTunnel.d.ts
|
|
18
|
+
lib/PlaywrightBrowserTunnel.d.ts.map
|
|
19
|
+
lib/PlaywrightBrowserTunnel.js
|
|
20
|
+
lib/PlaywrightBrowserTunnel.js.map
|
|
21
|
+
lib/index.d.ts
|
|
22
|
+
lib/index.d.ts.map
|
|
23
|
+
lib/index.js
|
|
24
|
+
lib/index.js.map
|
|
25
|
+
lib/tsdoc-metadata.json
|
|
26
|
+
lib/tunneledBrowserConnection/ITunneledBrowser.d.ts
|
|
27
|
+
lib/tunneledBrowserConnection/ITunneledBrowser.d.ts.map
|
|
28
|
+
lib/tunneledBrowserConnection/ITunneledBrowser.js
|
|
29
|
+
lib/tunneledBrowserConnection/ITunneledBrowser.js.map
|
|
30
|
+
lib/tunneledBrowserConnection/ITunneledBrowserConnection.d.ts
|
|
31
|
+
lib/tunneledBrowserConnection/ITunneledBrowserConnection.d.ts.map
|
|
32
|
+
lib/tunneledBrowserConnection/ITunneledBrowserConnection.js
|
|
33
|
+
lib/tunneledBrowserConnection/ITunneledBrowserConnection.js.map
|
|
34
|
+
lib/tunneledBrowserConnection/TunneledBrowser.d.ts
|
|
35
|
+
lib/tunneledBrowserConnection/TunneledBrowser.d.ts.map
|
|
36
|
+
lib/tunneledBrowserConnection/TunneledBrowser.js
|
|
37
|
+
lib/tunneledBrowserConnection/TunneledBrowser.js.map
|
|
38
|
+
lib/tunneledBrowserConnection/TunneledBrowserConnection.d.ts
|
|
39
|
+
lib/tunneledBrowserConnection/TunneledBrowserConnection.d.ts.map
|
|
40
|
+
lib/tunneledBrowserConnection/TunneledBrowserConnection.js
|
|
41
|
+
lib/tunneledBrowserConnection/TunneledBrowserConnection.js.map
|
|
42
|
+
lib/tunneledBrowserConnection/constants.d.ts
|
|
43
|
+
lib/tunneledBrowserConnection/constants.d.ts.map
|
|
44
|
+
lib/tunneledBrowserConnection/constants.js
|
|
45
|
+
lib/tunneledBrowserConnection/constants.js.map
|
|
46
|
+
lib/tunneledBrowserConnection/index.d.ts
|
|
47
|
+
lib/tunneledBrowserConnection/index.d.ts.map
|
|
48
|
+
lib/tunneledBrowserConnection/index.js
|
|
49
|
+
lib/tunneledBrowserConnection/index.js.map
|
|
50
|
+
lib/utilities.d.ts
|
|
51
|
+
lib/utilities.d.ts.map
|
|
52
|
+
lib/utilities.js
|
|
53
|
+
lib/utilities.js.map
|
|
54
|
+
temp/build/lint/_eslint-5eVG3S6w.json
|
|
55
|
+
temp/build/lint/lint.sarif
|
|
56
|
+
temp/build/typescript/ts_l9Fw4VUO.json
|
|
57
|
+
temp/playwright-browser-tunnel.api.md
|
|
58
|
+
======== END PROCESS INPUT =======
|
|
59
|
+
======= BEGIN PROCESS OUTPUT =======
|
|
60
|
+
======== END PROCESS OUTPUT ========
|
|
61
|
+
|
|
62
|
+
Exited with code "0"
|
package/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rushstack/playwright-browser-tunnel",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.2.4",
|
|
6
|
+
"tag": "@rushstack/playwright-browser-tunnel_v0.2.4",
|
|
7
|
+
"date": "Wed, 11 Feb 2026 23:14:09 GMT",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"comment": "Update module layout to isolate code that does not depend on Playwright."
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
},
|
|
4
16
|
{
|
|
5
17
|
"version": "0.2.3",
|
|
6
18
|
"tag": "@rushstack/playwright-browser-tunnel_v0.2.3",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# Change Log - @rushstack/playwright-browser-tunnel
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 11 Feb 2026 23:14:09 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 0.2.4
|
|
6
|
+
Wed, 11 Feb 2026 23:14:09 GMT
|
|
7
|
+
|
|
8
|
+
### Patches
|
|
9
|
+
|
|
10
|
+
- Update module layout to isolate code that does not depend on Playwright.
|
|
4
11
|
|
|
5
12
|
## 0.2.3
|
|
6
13
|
Sat, 07 Feb 2026 01:13:26 GMT
|
package/lib/tsdoc-metadata.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Browser } from 'playwright-core';
|
|
2
|
+
/**
|
|
3
|
+
* Disposable handle returned by {@link createTunneledBrowserAsync}.
|
|
4
|
+
* @beta
|
|
5
|
+
*/
|
|
6
|
+
export interface IDisposableTunneledBrowser {
|
|
7
|
+
/**
|
|
8
|
+
* The connected Playwright Browser instance.
|
|
9
|
+
*/
|
|
10
|
+
browser: Browser;
|
|
11
|
+
/**
|
|
12
|
+
* Async dispose method that closes the browser connection.
|
|
13
|
+
* Called automatically when using `await using` syntax.
|
|
14
|
+
*/
|
|
15
|
+
[Symbol.asyncDispose]: () => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=ITunneledBrowser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITunneledBrowser.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/ITunneledBrowser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
//# sourceMappingURL=ITunneledBrowser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITunneledBrowser.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/ITunneledBrowser.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Browser } from 'playwright-core';\n\n/**\n * Disposable handle returned by {@link createTunneledBrowserAsync}.\n * @beta\n */\nexport interface IDisposableTunneledBrowser {\n /**\n * The connected Playwright Browser instance.\n */\n browser: Browser;\n /**\n * Async dispose method that closes the browser connection.\n * Called automatically when using `await using` syntax.\n */\n [Symbol.asyncDispose]: () => Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LaunchOptions } from 'playwright-core';
|
|
2
|
+
import type { BrowserName } from '../PlaywrightBrowserTunnel';
|
|
3
|
+
export interface IHandshake {
|
|
4
|
+
action: 'handshake';
|
|
5
|
+
browserName: BrowserName;
|
|
6
|
+
launchOptions: LaunchOptions;
|
|
7
|
+
playwrightVersion: string;
|
|
8
|
+
}
|
|
9
|
+
export interface IHandshakeAck {
|
|
10
|
+
action: 'handshakeAck';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Disposable handle returned by {@link tunneledBrowserConnection}.
|
|
14
|
+
* @beta
|
|
15
|
+
*/
|
|
16
|
+
export interface IDisposableTunneledBrowserConnection {
|
|
17
|
+
/**
|
|
18
|
+
* The WebSocket endpoint URL that the local Playwright client should connect to.
|
|
19
|
+
*/
|
|
20
|
+
remoteEndpoint: string;
|
|
21
|
+
/**
|
|
22
|
+
* Dispose method that closes the WebSocket servers.
|
|
23
|
+
* Called automatically when using `using` syntax.
|
|
24
|
+
*/
|
|
25
|
+
[Symbol.dispose]: () => void;
|
|
26
|
+
/**
|
|
27
|
+
* Promise that resolves when the remote WebSocket server closes.
|
|
28
|
+
*/
|
|
29
|
+
closePromise: Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=ITunneledBrowserConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITunneledBrowserConnection.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/ITunneledBrowserConnection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,cAAc,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,oCAAoC;IACnD;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
//# sourceMappingURL=ITunneledBrowserConnection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ITunneledBrowserConnection.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/ITunneledBrowserConnection.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { LaunchOptions } from 'playwright-core';\n\nimport type { BrowserName } from '../PlaywrightBrowserTunnel';\n\nexport interface IHandshake {\n action: 'handshake';\n browserName: BrowserName;\n launchOptions: LaunchOptions;\n playwrightVersion: string;\n}\n\nexport interface IHandshakeAck {\n action: 'handshakeAck';\n}\n\n/**\n * Disposable handle returned by {@link tunneledBrowserConnection}.\n * @beta\n */\nexport interface IDisposableTunneledBrowserConnection {\n /**\n * The WebSocket endpoint URL that the local Playwright client should connect to.\n */\n remoteEndpoint: string;\n /**\n * Dispose method that closes the WebSocket servers.\n * Called automatically when using `using` syntax.\n */\n [Symbol.dispose]: () => void;\n /**\n * Promise that resolves when the remote WebSocket server closes.\n */\n closePromise: Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LaunchOptions } from 'playwright-core';
|
|
2
|
+
import type { ITerminal } from '@rushstack/terminal';
|
|
3
|
+
import type { BrowserName } from '../PlaywrightBrowserTunnel';
|
|
4
|
+
import type { IDisposableTunneledBrowser } from './ITunneledBrowser';
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Playwright Browser instance connected via a tunneled WebSocket connection.
|
|
7
|
+
* @beta
|
|
8
|
+
*/
|
|
9
|
+
export declare function createTunneledBrowserAsync(browserName: BrowserName, launchOptions: LaunchOptions, logger?: ITerminal, port?: number): Promise<IDisposableTunneledBrowser>;
|
|
10
|
+
//# sourceMappingURL=TunneledBrowser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunneledBrowser.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/TunneledBrowser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAIrE;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,MAAM,CAAC,EAAE,SAAS,EAClB,IAAI,GAAE,MAA4B,GACjC,OAAO,CAAC,0BAA0B,CAAC,CA2BrC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createTunneledBrowserAsync = createTunneledBrowserAsync;
|
|
9
|
+
const playwright_core_1 = __importDefault(require("playwright-core"));
|
|
10
|
+
const terminal_1 = require("@rushstack/terminal");
|
|
11
|
+
const constants_1 = require("./constants");
|
|
12
|
+
const TunneledBrowserConnection_1 = require("./TunneledBrowserConnection");
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Playwright Browser instance connected via a tunneled WebSocket connection.
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
async function createTunneledBrowserAsync(browserName, launchOptions, logger, port = constants_1.DEFAULT_LISTEN_PORT) {
|
|
18
|
+
// Establish the tunnel first (remoteEndpoint here refers to local proxy endpoint for connect())
|
|
19
|
+
if (!logger) {
|
|
20
|
+
const terminalProvider = new terminal_1.ConsoleTerminalProvider();
|
|
21
|
+
logger = new terminal_1.Terminal(terminalProvider);
|
|
22
|
+
}
|
|
23
|
+
const connection = await (0, TunneledBrowserConnection_1.tunneledBrowserConnection)(logger, port);
|
|
24
|
+
const { remoteEndpoint } = connection;
|
|
25
|
+
// Append query params for browser and launchOptions
|
|
26
|
+
const urlObj = new URL(remoteEndpoint);
|
|
27
|
+
urlObj.searchParams.set('browser', browserName);
|
|
28
|
+
urlObj.searchParams.set('launchOptions', JSON.stringify(launchOptions || {}));
|
|
29
|
+
const connectEndpoint = urlObj.toString();
|
|
30
|
+
const browser = await playwright_core_1.default[browserName].connect(connectEndpoint);
|
|
31
|
+
logger.writeLine(`Connected to remote browser at ${connectEndpoint}`);
|
|
32
|
+
return {
|
|
33
|
+
browser,
|
|
34
|
+
async [Symbol.asyncDispose]() {
|
|
35
|
+
logger.writeLine('Disposing browser');
|
|
36
|
+
await browser.close();
|
|
37
|
+
// Dispose the tunnel connection after browser is closed
|
|
38
|
+
connection[Symbol.dispose]();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=TunneledBrowser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunneledBrowser.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/TunneledBrowser.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;;;AAkB3D,gEAgCC;AA/CD,sEAAyC;AAGzC,kDAAwE;AAGxE,2CAAkD;AAGlD,2EAAwE;AAExE;;;GAGG;AACI,KAAK,UAAU,0BAA0B,CAC9C,WAAwB,EACxB,aAA4B,EAC5B,MAAkB,EAClB,OAAe,+BAAmB;IAElC,gGAAgG;IAEhG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,gBAAgB,GAA4B,IAAI,kCAAuB,EAAE,CAAC;QAChF,MAAM,GAAG,IAAI,mBAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,UAAU,GAAyC,MAAM,IAAA,qDAAyB,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACvG,MAAM,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;IACtC,oDAAoD;IACpD,MAAM,MAAM,GAAQ,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAChD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,eAAe,GAAW,MAAM,CAAC,QAAQ,EAAE,CAAC;IAClD,MAAM,OAAO,GAAY,MAAM,yBAAU,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAChF,MAAM,CAAC,SAAS,CAAC,kCAAkC,eAAe,EAAE,CAAC,CAAC;IAEtE,OAAO;QACL,OAAO;QACP,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;YACzB,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;YACtC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,wDAAwD;YACxD,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { Browser, LaunchOptions } from 'playwright-core';\nimport playwright from 'playwright-core';\n\nimport type { ITerminal } from '@rushstack/terminal';\nimport { ConsoleTerminalProvider, Terminal } from '@rushstack/terminal';\n\nimport type { BrowserName } from '../PlaywrightBrowserTunnel';\nimport { DEFAULT_LISTEN_PORT } from './constants';\nimport type { IDisposableTunneledBrowser } from './ITunneledBrowser';\nimport type { IDisposableTunneledBrowserConnection } from './ITunneledBrowserConnection';\nimport { tunneledBrowserConnection } from './TunneledBrowserConnection';\n\n/**\n * Creates a Playwright Browser instance connected via a tunneled WebSocket connection.\n * @beta\n */\nexport async function createTunneledBrowserAsync(\n browserName: BrowserName,\n launchOptions: LaunchOptions,\n logger?: ITerminal,\n port: number = DEFAULT_LISTEN_PORT\n): Promise<IDisposableTunneledBrowser> {\n // Establish the tunnel first (remoteEndpoint here refers to local proxy endpoint for connect())\n\n if (!logger) {\n const terminalProvider: ConsoleTerminalProvider = new ConsoleTerminalProvider();\n logger = new Terminal(terminalProvider);\n }\n\n const connection: IDisposableTunneledBrowserConnection = await tunneledBrowserConnection(logger, port);\n const { remoteEndpoint } = connection;\n // Append query params for browser and launchOptions\n const urlObj: URL = new URL(remoteEndpoint);\n urlObj.searchParams.set('browser', browserName);\n urlObj.searchParams.set('launchOptions', JSON.stringify(launchOptions || {}));\n const connectEndpoint: string = urlObj.toString();\n const browser: Browser = await playwright[browserName].connect(connectEndpoint);\n logger.writeLine(`Connected to remote browser at ${connectEndpoint}`);\n\n return {\n browser,\n async [Symbol.asyncDispose]() {\n logger.writeLine('Disposing browser');\n await browser.close();\n // Dispose the tunnel connection after browser is closed\n connection[Symbol.dispose]();\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ITerminal } from '@rushstack/terminal';
|
|
2
|
+
import type { IDisposableTunneledBrowserConnection } from './ITunneledBrowserConnection';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a tunneled WebSocket endpoint that a local Playwright client can connect to.
|
|
5
|
+
* @beta
|
|
6
|
+
*/
|
|
7
|
+
export declare function tunneledBrowserConnection(logger: ITerminal, port?: number): Promise<IDisposableTunneledBrowserConnection>;
|
|
8
|
+
//# sourceMappingURL=TunneledBrowserConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunneledBrowserConnection.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/TunneledBrowserConnection.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAUrD,OAAO,KAAK,EACV,oCAAoC,EAGrC,MAAM,8BAA8B,CAAC;AAKtC;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,SAAS,EACjB,IAAI,GAAE,MAA4B,GACjC,OAAO,CAAC,oCAAoC,CAAC,CAqM/C"}
|
package/lib/{tunneledBrowserConnection.js → tunneledBrowserConnection/TunneledBrowserConnection.js}
RENAMED
|
@@ -6,21 +6,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
};
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.tunneledBrowserConnection = tunneledBrowserConnection;
|
|
9
|
-
exports.createTunneledBrowserAsync = createTunneledBrowserAsync;
|
|
10
|
-
const playwright_core_1 = __importDefault(require("playwright-core"));
|
|
11
|
-
const ws_1 = require("ws");
|
|
12
9
|
const package_json_1 = __importDefault(require("playwright-core/package.json"));
|
|
13
|
-
const
|
|
14
|
-
const HttpServer_1 = require("
|
|
15
|
-
const utilities_1 = require("
|
|
10
|
+
const ws_1 = require("ws");
|
|
11
|
+
const HttpServer_1 = require("../HttpServer");
|
|
12
|
+
const utilities_1 = require("../utilities");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
16
14
|
const { version: playwrightVersion } = package_json_1.default;
|
|
17
|
-
const SUPPORTED_BROWSER_NAMES = new Set(['chromium', 'firefox', 'webkit']);
|
|
18
|
-
const DEFAULT_LISTEN_PORT = 56767;
|
|
19
15
|
/**
|
|
20
16
|
* Creates a tunneled WebSocket endpoint that a local Playwright client can connect to.
|
|
21
17
|
* @beta
|
|
22
18
|
*/
|
|
23
|
-
async function tunneledBrowserConnection(logger, port = DEFAULT_LISTEN_PORT) {
|
|
19
|
+
async function tunneledBrowserConnection(logger, port = constants_1.DEFAULT_LISTEN_PORT) {
|
|
24
20
|
// Server that remote peer (actual browser host) connects to
|
|
25
21
|
const remoteWsServer = new ws_1.WebSocketServer({ port });
|
|
26
22
|
// Local HTTP + WebSocket server where the playwright client will connect providing params
|
|
@@ -129,7 +125,7 @@ async function tunneledBrowserConnection(logger, port = DEFAULT_LISTEN_PORT) {
|
|
|
129
125
|
const parsed = new URL(urlString, 'http://localhost');
|
|
130
126
|
logger.writeLine(`Local client connected with query params: ${parsed.searchParams.toString()}`);
|
|
131
127
|
const bName = parsed.searchParams.get('browser');
|
|
132
|
-
if (bName && SUPPORTED_BROWSER_NAMES.has(bName)) {
|
|
128
|
+
if (bName && constants_1.SUPPORTED_BROWSER_NAMES.has(bName)) {
|
|
133
129
|
browserName = bName;
|
|
134
130
|
}
|
|
135
131
|
const launchOptionsParam = parsed.searchParams.get('launchOptions');
|
|
@@ -147,7 +143,7 @@ async function tunneledBrowserConnection(logger, port = DEFAULT_LISTEN_PORT) {
|
|
|
147
143
|
logger.writeErrorLine(`Error parsing local connection query params: ${e}`);
|
|
148
144
|
}
|
|
149
145
|
if (!browserName) {
|
|
150
|
-
const supportedBrowsersString = Array.from(SUPPORTED_BROWSER_NAMES).join('|');
|
|
146
|
+
const supportedBrowsersString = Array.from(constants_1.SUPPORTED_BROWSER_NAMES).join('|');
|
|
151
147
|
logger.writeErrorLine(`browser query param required (${supportedBrowsersString})`);
|
|
152
148
|
localWs.close(utilities_1.WebSocketCloseCode.PROTOCOL_ERROR, 'Missing browser param');
|
|
153
149
|
return;
|
|
@@ -202,33 +198,4 @@ async function tunneledBrowserConnection(logger, port = DEFAULT_LISTEN_PORT) {
|
|
|
202
198
|
});
|
|
203
199
|
});
|
|
204
200
|
}
|
|
205
|
-
|
|
206
|
-
* Creates a Playwright Browser instance connected via a tunneled WebSocket connection.
|
|
207
|
-
* @beta
|
|
208
|
-
*/
|
|
209
|
-
async function createTunneledBrowserAsync(browserName, launchOptions, logger, port = DEFAULT_LISTEN_PORT) {
|
|
210
|
-
// Establish the tunnel first (remoteEndpoint here refers to local proxy endpoint for connect())
|
|
211
|
-
if (!logger) {
|
|
212
|
-
const terminalProvider = new terminal_1.ConsoleTerminalProvider();
|
|
213
|
-
logger = new terminal_1.Terminal(terminalProvider);
|
|
214
|
-
}
|
|
215
|
-
const connection = await tunneledBrowserConnection(logger, port);
|
|
216
|
-
const { remoteEndpoint } = connection;
|
|
217
|
-
// Append query params for browser and launchOptions
|
|
218
|
-
const urlObj = new URL(remoteEndpoint);
|
|
219
|
-
urlObj.searchParams.set('browser', browserName);
|
|
220
|
-
urlObj.searchParams.set('launchOptions', JSON.stringify(launchOptions || {}));
|
|
221
|
-
const connectEndpoint = urlObj.toString();
|
|
222
|
-
const browser = await playwright_core_1.default[browserName].connect(connectEndpoint);
|
|
223
|
-
logger.writeLine(`Connected to remote browser at ${connectEndpoint}`);
|
|
224
|
-
return {
|
|
225
|
-
browser,
|
|
226
|
-
async [Symbol.asyncDispose]() {
|
|
227
|
-
logger.writeLine('Disposing browser');
|
|
228
|
-
await browser.close();
|
|
229
|
-
// Dispose the tunnel connection after browser is closed
|
|
230
|
-
connection[Symbol.dispose]();
|
|
231
|
-
}
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
//# sourceMappingURL=tunneledBrowserConnection.js.map
|
|
201
|
+
//# sourceMappingURL=TunneledBrowserConnection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TunneledBrowserConnection.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/TunneledBrowserConnection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport type { LaunchOptions } from 'playwright-core';\nimport playwrightPackageJson from 'playwright-core/package.json';\nimport type { RawData } from 'ws';\nimport { WebSocket, WebSocketServer } from 'ws';\n\nimport type { ITerminal } from '@rushstack/terminal';\n\nimport { HttpServer } from '../HttpServer';\nimport type { BrowserName } from '../PlaywrightBrowserTunnel';\nimport {\n getNormalizedErrorString,\n getWebSocketCloseReason,\n getWebSocketReadyStateString,\n WebSocketCloseCode\n} from '../utilities';\nimport type {\n IDisposableTunneledBrowserConnection,\n IHandshake,\n IHandshakeAck\n} from './ITunneledBrowserConnection';\nimport { DEFAULT_LISTEN_PORT, SUPPORTED_BROWSER_NAMES } from './constants';\n\nconst { version: playwrightVersion } = playwrightPackageJson;\n\n/**\n * Creates a tunneled WebSocket endpoint that a local Playwright client can connect to.\n * @beta\n */\nexport async function tunneledBrowserConnection(\n logger: ITerminal,\n port: number = DEFAULT_LISTEN_PORT\n): Promise<IDisposableTunneledBrowserConnection> {\n // Server that remote peer (actual browser host) connects to\n const remoteWsServer: WebSocketServer = new WebSocketServer({ port });\n // Local HTTP + WebSocket server where the playwright client will connect providing params\n const httpServer: HttpServer = new HttpServer(logger);\n await httpServer.listenAsync();\n logger.writeLine(`Remote WebSocket server listening on ws://localhost:${port}`);\n\n const localProxyWs: WebSocketServer = httpServer.wsServer;\n const localProxyWsEndpoint: string = httpServer.endpoint;\n\n let browserName: BrowserName | undefined;\n let launchOptions: LaunchOptions | undefined;\n let remoteSocket: WebSocket | undefined;\n let handshakeAck: boolean = false;\n let handshakeSent: boolean = false;\n\n function maybeSendHandshake(): void {\n if (!handshakeSent && remoteSocket && browserName && launchOptions) {\n const handshake: IHandshake = {\n action: 'handshake',\n browserName,\n launchOptions,\n playwrightVersion\n };\n // Log handshake without 'headless' to avoid confusion (tunnel enforces headless: false)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { headless, ...logOptions } = launchOptions;\n const logHandshake: Omit<IHandshake, 'launchOptions'> & {\n launchOptions: Omit<LaunchOptions, 'headless'>;\n } = {\n ...handshake,\n launchOptions: logOptions\n };\n logger.writeLine(`Sending handshake to remote: ${JSON.stringify(logHandshake)}`);\n handshakeSent = true;\n remoteSocket.send(JSON.stringify(handshake));\n }\n }\n\n return await new Promise((resolve) => {\n remoteWsServer.on('error', (error) => {\n logger.writeErrorLine(`Remote WebSocket server error: ${error}`);\n });\n\n remoteWsServer.on('close', () => {\n logger.writeLine('Remote WebSocket server closed');\n });\n\n const bufferedLocalMessages: Array<RawData> = [];\n\n remoteWsServer.on('connection', (ws) => {\n logger.writeLine('Remote websocket connected');\n remoteSocket = ws;\n handshakeAck = false;\n maybeSendHandshake();\n\n ws.on('message', (message) => {\n if (!handshakeAck) {\n try {\n const receivedHandshake: IHandshakeAck = JSON.parse(message.toString());\n if (receivedHandshake.action === 'handshakeAck') {\n handshakeAck = true;\n logger.writeLine('Received handshakeAck from remote');\n } else {\n logger.writeErrorLine('Invalid handshake ack message');\n ws.close(WebSocketCloseCode.PROTOCOL_ERROR, 'Invalid handshake ack');\n return;\n }\n } catch (e) {\n logger.writeErrorLine(`Failed parsing handshake ack: ${e}`);\n ws.close(WebSocketCloseCode.PROTOCOL_ERROR, 'Failed parsing handshake');\n return;\n }\n // Resolve only once local proxy available and handshake acknowledged\n if (handshakeAck) {\n // Flush any buffered local messages now that tunnel is active\n const activeRemote: WebSocket | undefined = remoteSocket;\n if (activeRemote && activeRemote.readyState === WebSocket.OPEN) {\n while (bufferedLocalMessages.length > 0) {\n const m: Buffer | ArrayBuffer | Buffer[] | string | undefined = bufferedLocalMessages.shift();\n if (m !== undefined) {\n logger.writeLine(`Flushing buffered local message to remote: ${m}`);\n activeRemote.send(m);\n }\n }\n }\n }\n } else {\n // Forward from remote to all local clients\n localProxyWs.clients.forEach((client) => {\n if (client.readyState === WebSocket.OPEN) {\n client.send(message);\n }\n });\n }\n });\n\n ws.on('close', (code: number, reason: Buffer) => {\n const reasonStr: string = reason.toString() || 'no reason provided';\n const codeDescription: string = getWebSocketCloseReason(code);\n logger.writeDebugLine(\n `Remote websocket closed - code: ${code} (${codeDescription}), reason: ${reasonStr}`\n );\n logger.writeDebugLine(\n ` Connection state at close: handshakeSent=${handshakeSent}, handshakeAck=${handshakeAck}`\n );\n logger.writeDebugLine(` Buffered messages pending: ${bufferedLocalMessages.length}`);\n });\n ws.on('error', (err: Error) => {\n logger.writeErrorLine(`Remote websocket error: ${getNormalizedErrorString(err)}`);\n logger.writeErrorLine(` Socket readyState: ${getWebSocketReadyStateString(ws.readyState)}`);\n });\n });\n\n localProxyWs.on('connection', (localWs, request) => {\n try {\n const urlString: string | undefined = request?.url;\n if (urlString) {\n const parsed: URL = new URL(urlString, 'http://localhost');\n logger.writeLine(`Local client connected with query params: ${parsed.searchParams.toString()}`);\n const bName: string | null = parsed.searchParams.get('browser');\n if (bName && SUPPORTED_BROWSER_NAMES.has(bName)) {\n browserName = bName as BrowserName;\n }\n const launchOptionsParam: string | null = parsed.searchParams.get('launchOptions');\n if (launchOptionsParam) {\n try {\n launchOptions = JSON.parse(launchOptionsParam);\n } catch (e) {\n logger.writeErrorLine('Invalid launchOptions JSON provided');\n }\n }\n }\n } catch (e) {\n logger.writeErrorLine(`Error parsing local connection query params: ${e}`);\n }\n\n if (!browserName) {\n const supportedBrowsersString: string = Array.from(SUPPORTED_BROWSER_NAMES).join('|');\n logger.writeErrorLine(`browser query param required (${supportedBrowsersString})`);\n localWs.close(WebSocketCloseCode.PROTOCOL_ERROR, 'Missing browser param');\n return;\n }\n if (!launchOptions) {\n launchOptions = {} as LaunchOptions; // default empty if not provided\n }\n\n maybeSendHandshake();\n\n localWs.on('message', (message) => {\n if (handshakeAck && remoteSocket?.readyState === WebSocket.OPEN) {\n remoteSocket.send(message);\n } else {\n // Buffer until handshakeAck to avoid losing early protocol messages from Playwright\n bufferedLocalMessages.push(message);\n }\n });\n localWs.on('close', (code: number, reason: Buffer) => {\n const reasonStr: string = reason.toString() || 'no reason provided';\n const codeDescription: string = getWebSocketCloseReason(code);\n logger.writeDebugLine(\n `Local client websocket closed - code: ${code} (${codeDescription}), reason: ${reasonStr}`\n );\n logger.writeDebugLine(\n ` Remote socket state: ${remoteSocket ? getWebSocketReadyStateString(remoteSocket.readyState) : 'undefined'}`\n );\n logger.writeDebugLine(` handshakeAck: ${handshakeAck}`);\n });\n localWs.on('error', (err: Error) => {\n logger.writeErrorLine(`Local client websocket error: ${getNormalizedErrorString(err)}`);\n });\n });\n\n // Resolve immediately so caller can initiate local connection with query params (handshake completes later)\n resolve({\n remoteEndpoint: localProxyWsEndpoint,\n [Symbol.dispose]() {\n try {\n remoteWsServer.close();\n } catch {\n // ignore errors during remote WebSocket server shutdown\n }\n try {\n httpServer[Symbol.dispose]();\n } catch {\n // ignore errors during HTTP/WebSocket server shutdown\n }\n },\n // eslint-disable-next-line promise/param-names\n closePromise: new Promise<void>((resolve2) => {\n remoteWsServer.once('close', () => {\n resolve2();\n });\n })\n });\n });\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB,EAAE,GAAG,CAAC,MAAM,CAA8C,CAAC;AAC/F,eAAO,MAAM,mBAAmB,EAAE,MAAc,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.DEFAULT_LISTEN_PORT = exports.SUPPORTED_BROWSER_NAMES = void 0;
|
|
6
|
+
exports.SUPPORTED_BROWSER_NAMES = new Set(['chromium', 'firefox', 'webkit']);
|
|
7
|
+
exports.DEFAULT_LISTEN_PORT = 56767;
|
|
8
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/constants.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE9C,QAAA,uBAAuB,GAAgB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;AAClF,QAAA,mBAAmB,GAAW,KAAK,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport const SUPPORTED_BROWSER_NAMES: Set<string> = new Set(['chromium', 'firefox', 'webkit']);\nexport const DEFAULT_LISTEN_PORT: number = 56767;\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createTunneledBrowserAsync } from './TunneledBrowser';
|
|
2
|
+
export { tunneledBrowserConnection } from './TunneledBrowserConnection';
|
|
3
|
+
export type { IDisposableTunneledBrowser } from './ITunneledBrowser';
|
|
4
|
+
export type { IDisposableTunneledBrowserConnection } from './ITunneledBrowserConnection';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE,YAAY,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACrE,YAAY,EAAE,oCAAoC,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
3
|
+
// See LICENSE in the project root for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.tunneledBrowserConnection = exports.createTunneledBrowserAsync = void 0;
|
|
6
|
+
var TunneledBrowser_1 = require("./TunneledBrowser");
|
|
7
|
+
Object.defineProperty(exports, "createTunneledBrowserAsync", { enumerable: true, get: function () { return TunneledBrowser_1.createTunneledBrowserAsync; } });
|
|
8
|
+
var TunneledBrowserConnection_1 = require("./TunneledBrowserConnection");
|
|
9
|
+
Object.defineProperty(exports, "tunneledBrowserConnection", { enumerable: true, get: function () { return TunneledBrowserConnection_1.tunneledBrowserConnection; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tunneledBrowserConnection/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,qDAA+D;AAAtD,6HAAA,0BAA0B,OAAA;AACnC,yEAAwE;AAA/D,sIAAA,yBAAyB,OAAA","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nexport { createTunneledBrowserAsync } from './TunneledBrowser';\nexport { tunneledBrowserConnection } from './TunneledBrowserConnection';\n\nexport type { IDisposableTunneledBrowser } from './ITunneledBrowser';\nexport type { IDisposableTunneledBrowserConnection } from './ITunneledBrowserConnection';\n"]}
|
package/package.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
Caching build output folders: dist, lib, temp, .rush/temp/operation/_phase_build
|
|
2
2
|
Successfully set cache entry.
|
|
3
|
-
Cache key: rushstack+playwright-browser-tunnel-_phase_build-
|
|
3
|
+
Cache key: rushstack+playwright-browser-tunnel-_phase_build-517a2999ebe527b217bbfe2e265943b73bf3856b
|
|
@@ -2,7 +2,7 @@ Invoking: heft run --only build -- --clean --production
|
|
|
2
2
|
---- build started ----
|
|
3
3
|
[build:typescript] Using TypeScript version 5.8.2
|
|
4
4
|
[build:lint] Using ESLint version 9.37.0
|
|
5
|
-
[build:api-extractor] Using API Extractor version 7.56.
|
|
5
|
+
[build:api-extractor] Using API Extractor version 7.56.3
|
|
6
6
|
[build:api-extractor] Analysis will use the bundled TypeScript version 5.8.2
|
|
7
|
-
---- build finished (22.
|
|
8
|
-
-------------------- Finished (22.
|
|
7
|
+
---- build finished (22.551s) ----
|
|
8
|
+
-------------------- Finished (22.555s) --------------------
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
|
|
4
|
+
import type { Browser } from 'playwright-core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Disposable handle returned by {@link createTunneledBrowserAsync}.
|
|
8
|
+
* @beta
|
|
9
|
+
*/
|
|
10
|
+
export interface IDisposableTunneledBrowser {
|
|
11
|
+
/**
|
|
12
|
+
* The connected Playwright Browser instance.
|
|
13
|
+
*/
|
|
14
|
+
browser: Browser;
|
|
15
|
+
/**
|
|
16
|
+
* Async dispose method that closes the browser connection.
|
|
17
|
+
* Called automatically when using `await using` syntax.
|
|
18
|
+
*/
|
|
19
|
+
[Symbol.asyncDispose]: () => Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
|
|
4
|
+
import type { LaunchOptions } from 'playwright-core';
|
|
5
|
+
|
|
6
|
+
import type { BrowserName } from '../PlaywrightBrowserTunnel';
|
|
7
|
+
|
|
8
|
+
export interface IHandshake {
|
|
9
|
+
action: 'handshake';
|
|
10
|
+
browserName: BrowserName;
|
|
11
|
+
launchOptions: LaunchOptions;
|
|
12
|
+
playwrightVersion: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface IHandshakeAck {
|
|
16
|
+
action: 'handshakeAck';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Disposable handle returned by {@link tunneledBrowserConnection}.
|
|
21
|
+
* @beta
|
|
22
|
+
*/
|
|
23
|
+
export interface IDisposableTunneledBrowserConnection {
|
|
24
|
+
/**
|
|
25
|
+
* The WebSocket endpoint URL that the local Playwright client should connect to.
|
|
26
|
+
*/
|
|
27
|
+
remoteEndpoint: string;
|
|
28
|
+
/**
|
|
29
|
+
* Dispose method that closes the WebSocket servers.
|
|
30
|
+
* Called automatically when using `using` syntax.
|
|
31
|
+
*/
|
|
32
|
+
[Symbol.dispose]: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Promise that resolves when the remote WebSocket server closes.
|
|
35
|
+
*/
|
|
36
|
+
closePromise: Promise<void>;
|
|
37
|
+
}
|