arn-browser 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/bin/cli.js +43 -0
  2. package/bin/install.js +412 -0
  3. package/package.json +8 -3
  4. package/src/index.d.ts +16 -6
  5. package/src/index.js +7 -4
  6. package/src/utility/deleteDirectory.js +2 -2
  7. package/src/utility/{multilogin_token_manager.js → mlx_token.js} +32 -43
  8. package/src/utility/{launchBrowser.d.ts → playwright/pwLaunch.d.ts} +25 -18
  9. package/src/utility/{launchBrowser.js → playwright/pwLaunch.js} +221 -137
  10. package/src/{all_routes/routeWithSuperagent.d.ts → utility/playwright/routes/pwRoute.d.ts} +4 -4
  11. package/src/{all_routes/routeWithSuperagent.js → utility/playwright/routes/pwRoute.js} +2 -2
  12. package/src/utility/proxy-utility/proxy-chain.js +30 -3
  13. package/src/utility/proxy-utility/proxy-helper.js +1 -1
  14. package/src/utility/puppeteer/ppLaunch.d.ts +199 -0
  15. package/src/utility/puppeteer/ppLaunch.js +723 -0
  16. package/src/utility/puppeteer/routes/ppRoute.d.ts +64 -0
  17. package/src/utility/puppeteer/routes/ppRoute.js +326 -0
  18. /package/src/{human-cursor → utility/playwright/human-cursor}/HumanCursor.js +0 -0
  19. /package/src/{human-cursor → utility/playwright/human-cursor}/bezier.js +0 -0
  20. /package/src/{human-cursor → utility/playwright/human-cursor}/index.d.ts +0 -0
  21. /package/src/{human-cursor → utility/playwright/human-cursor}/index.js +0 -0
  22. /package/src/{human-cursor → utility/playwright/human-cursor}/randomizer.js +0 -0
  23. /package/src/{human-cursor → utility/playwright/human-cursor}/tweening.js +0 -0
  24. /package/src/utility/{playwright-helper.d.ts → playwright/playwright-helper.d.ts} +0 -0
  25. /package/src/utility/{playwright-helper.js → playwright/playwright-helper.js} +0 -0
@@ -5,9 +5,9 @@ import { Browser, BrowserContext, Page } from "playwright";
5
5
  // ============================================================================
6
6
 
7
7
  /**
8
- * Options for the gotRoute function.
8
+ * Options for the pwRoute function.
9
9
  */
10
- export interface GotRouteOptions {
10
+ export interface PwRouteOptions {
11
11
  /** Playwright Context (provide either context or page) */
12
12
  context?: BrowserContext | null;
13
13
 
@@ -57,11 +57,11 @@ export interface GotRouteOptions {
57
57
  /**
58
58
  * Sets up request interception, caching, and ad-blocking on a Playwright page or context.
59
59
  */
60
- export function gotRoute(options: GotRouteOptions): Promise<void>;
60
+ export function pwRoute(options: PwRouteOptions): Promise<void>;
61
61
 
62
62
  /**
63
63
  * Starts logging cache statistics to the console at a set interval.
64
64
  * @param log_cache Optional NodeCache instance (uses global by default)
65
65
  * @param interval Interval in seconds (default: 10)
66
66
  */
67
- export function showCacheLogs(log_cache?: any, interval?: number): void;
67
+ export function pwCacheLogs(log_cache?: any, interval?: number): void;
@@ -20,7 +20,7 @@ const globalCache = new NodeCache({
20
20
  * @param {Object} log_cache - The cache instance to monitor
21
21
  * @param {number} interval - The interval in seconds between log outputs
22
22
  */
23
- export function showCacheLogs(log_cache = globalCache, interval = 10) {
23
+ export function pwCacheLogs(log_cache = globalCache, interval = 10) {
24
24
  if (interval > 0) {
25
25
  setInterval(() => {
26
26
  const stats = log_cache.stats;
@@ -109,7 +109,7 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
109
109
  * @param {Array<string>} options.allowImagePatterns - Array of strings/patterns. If a URL contains any of these, it will NOT be blocked even if blockImage is true.
110
110
  * @param {Array<string>} options.skipGotPatterns - Array of strings/patterns. If a URL contains any of these, it will skip the custom Superagent fetch.
111
111
  */
112
- export async function gotRoute({
112
+ export async function pwRoute({
113
113
  context = null,
114
114
  page = null,
115
115
  successLogs = false,
@@ -217,9 +217,10 @@ export async function startProxyServer({
217
217
  fetchProxyDetails(upstreamProxies.p2, ip2LocationKey),
218
218
  ]);
219
219
 
220
- // Warn only if proxy was configured (URL exists) but details came back null (Connection failed)
221
- if (upstreamProxies.p1 && !p1Details) console.warn("░░ Warning: PROXY_1 configured but unreachable.");
222
- if (upstreamProxies.p2 && !p2Details) console.warn("░░ Warning: PROXY_2 configured but unreachable.");
220
+ // Throw error if proxy was configured (URL exists) but details came back null (Connection failed)
221
+ if (upstreamProxies.default && !defaultDetails) throw new Error("DEFAULT_PROXY configured but unreachable.");
222
+ if (upstreamProxies.p1 && !p1Details) throw new Error("PROXY_1 configured but unreachable.");
223
+ if (upstreamProxies.p2 && !p2Details) throw new Error("PROXY_2 configured but unreachable.");
223
224
 
224
225
  // 5. Stats
225
226
  const stats = {
@@ -239,6 +240,9 @@ export async function startProxyServer({
239
240
  const connectionMap = {}; // Maps connectionId -> { type: "..." }
240
241
  let serverRunning = false;
241
242
 
243
+ // Track all open sockets so we can force-destroy them on close
244
+ const activeSockets = new Set();
245
+
242
246
  // 6. Server
243
247
  const server = new ProxyChain.Server({
244
248
  port: selectedPort,
@@ -327,6 +331,23 @@ export async function startProxyServer({
327
331
  try {
328
332
  await server.listen();
329
333
  serverRunning = true;
334
+
335
+ // Track sockets so closeServer() can destroy them all
336
+ server.server.on('connection', (socket) => {
337
+ activeSockets.add(socket);
338
+ socket.once('close', () => activeSockets.delete(socket));
339
+
340
+ // Intercept pipe to catch the upstream target sockets created by proxy-chain
341
+ const originalPipe = socket.pipe;
342
+ socket.pipe = function(destination, options) {
343
+ if (destination && typeof destination.destroy === 'function') {
344
+ activeSockets.add(destination);
345
+ destination.once('close', () => activeSockets.delete(destination));
346
+ }
347
+ return originalPipe.apply(this, arguments);
348
+ };
349
+ });
350
+
330
351
  console.log(`░░ Local Proxy Started: http://127.0.0.1:${selectedPort}`);
331
352
  } catch (err) {
332
353
  console.error("░░ Failed to start proxy server:", err);
@@ -397,6 +418,12 @@ export async function startProxyServer({
397
418
  await server.close(true);
398
419
  serverRunning = false;
399
420
 
421
+ // Force-destroy any lingering sockets so Node can exit
422
+ for (const socket of activeSockets) {
423
+ socket.destroy();
424
+ }
425
+ activeSockets.clear();
426
+
400
427
  // Auto console.log stats on close
401
428
  if (proxy_stats) {
402
429
  console.log("░░ Proxy Stats:", getProxyStatsFormatted());
@@ -1,6 +1,6 @@
1
1
  import { setTimeout as sleep } from "timers/promises";
2
2
  import randomstring from "randomstring";
3
- import { getMultiloginToken } from "../multilogin_token_manager.js";
3
+ import { getMultiloginToken } from "../mlx_token.js";
4
4
  import { getActiveProxyWithStartStop as fetchAwsProxy } from "./custom-proxy.js";
5
5
  import { arn, query } from "arn-knexjs";
6
6
 
@@ -0,0 +1,199 @@
1
+ import { Browser, Page } from "puppeteer-core";
2
+ import type { ProxyConfig } from "../pwLaunch";
3
+
4
+ /**
5
+ * Configuration options specific to Multilogin (Puppeteer CDP).
6
+ */
7
+ export interface PpMultiloginOptions {
8
+ /**
9
+ * Multilogin Profile ID. If provided, launches an existing profile.
10
+ */
11
+ profileId?: string | null;
12
+
13
+ /**
14
+ * OS Type for Multilogin profile creation.
15
+ * Default: detected OS
16
+ */
17
+ os_type?: "windows" | "macos" | "linux" | "android";
18
+
19
+ /**
20
+ * Multilogin flag: Canvas noise masking.
21
+ * Default: true
22
+ */
23
+ canvas_noise?: boolean;
24
+
25
+ /**
26
+ * Multilogin flag: Media devices masking.
27
+ * Default: true
28
+ */
29
+ media_masking?: boolean;
30
+
31
+ /**
32
+ * Multilogin flag: Audio masking.
33
+ * Default: true
34
+ */
35
+ audio_masking?: boolean;
36
+ }
37
+
38
+ /**
39
+ * Options for launching a browser via Puppeteer CDP.
40
+ */
41
+ export interface PpLaunchOptions {
42
+ // ========================================================================
43
+ // 1. BROWSER SELECTION
44
+ // ========================================================================
45
+
46
+ /**
47
+ * Which browser to launch.
48
+ *
49
+ * - `"chrome"`: Chromium browser (locally installed)
50
+ * - `"chromium"`: Alias for Chrome
51
+ * - `"brave"`: Brave Browser (requires local binary)
52
+ * - `"multilogin"`: Multilogin anti-detect browser (via API)
53
+ *
54
+ * Default: `"chrome"`
55
+ */
56
+ which_browser?: "chrome" | "chromium" | "brave" | "multilogin";
57
+
58
+ // ========================================================================
59
+ // 2. STORAGE & PROFILES
60
+ // ========================================================================
61
+
62
+ /**
63
+ * Path to a persistent profile.
64
+ * - If absolute path: Uses that path exactly (no prefix added).
65
+ * - If folder name: Creates inside `~/.arn-browser/pp/persistent/` with a browser prefix (e.g., `brave_myProfile`).
66
+ * - If null: Creates a temporary, random profile in `~/.arn-browser/pp/temp/`.
67
+ */
68
+ profile_path?: string | null;
69
+
70
+ /**
71
+ * Auto-cleanup profiles after X minutes since last launch.
72
+ *
73
+ * **Persistent profiles:** Cleaned after X minutes since last launch. Default: 0 (never clean).
74
+ * **Temp profiles:** Default: 15 minutes if not specified.
75
+ *
76
+ * Default: 0
77
+ */
78
+ cleanupMinutes?: number;
79
+
80
+ // ========================================================================
81
+ // 3. NETWORK
82
+ // ========================================================================
83
+
84
+ /**
85
+ * Proxy settings (URL string or config object).
86
+ * Passed as `--proxy-server` flag to the browser.
87
+ */
88
+ proxy?: ProxyConfig | string | null;
89
+
90
+ // ========================================================================
91
+ // 4. BROWSER ARGS
92
+ // ========================================================================
93
+
94
+ /**
95
+ * Additional CLI arguments to pass to the browser process.
96
+ * These are appended after the default args.
97
+ *
98
+ * @example ["--disable-gpu", "--window-size=1920,1080"]
99
+ */
100
+ extraArgs?: string[];
101
+
102
+ // ========================================================================
103
+ // 5. ENGINE SPECIFIC
104
+ // ========================================================================
105
+
106
+ /**
107
+ * Options specific to the Multilogin engine.
108
+ */
109
+ multilogin_options?: PpMultiloginOptions;
110
+
111
+ // ========================================================================
112
+ // 6. FINGERPRINT SPOOFING
113
+ // ========================================================================
114
+
115
+ /**
116
+ * Configuration for browser fingerprint spoofing (per-page via fingerprint-injector).
117
+ *
118
+ * - `false`: No fingerprint spoofing (default)
119
+ * - `true`: Spoof fingerprint with default screen dimensions
120
+ * - `{ minWidth?, maxWidth?, minHeight?, maxHeight? }`: Spoof fingerprint with screen constraints
121
+ *
122
+ * Default: false
123
+ */
124
+ spoof_fingerprint?: boolean | {
125
+ minWidth?: number;
126
+ maxWidth?: number;
127
+ minHeight?: number;
128
+ maxHeight?: number;
129
+ };
130
+
131
+ // ========================================================================
132
+ // 7. LOGGING
133
+ // ========================================================================
134
+
135
+ /**
136
+ * Enable launch-related console logs.
137
+ * Default: false
138
+ */
139
+ launch_logs?: boolean;
140
+
141
+ /**
142
+ * Enable cleanup-related console logs.
143
+ * Default: false
144
+ */
145
+ cleanup_logs?: boolean;
146
+ }
147
+
148
+ /**
149
+ * Successful Puppeteer browser launch result.
150
+ * When launchError is null, browser/context/page are guaranteed to be valid.
151
+ */
152
+ export interface PpBrowserControllerSuccess {
153
+ /** The Puppeteer Browser instance. */
154
+ browser: Browser;
155
+ /** The browser instance (alias for browser in Puppeteer, since there's no separate BrowserContext). */
156
+ context: Browser;
157
+ /** The initial Page object. */
158
+ page: Page;
159
+ /** Returns true if the browser is still connected. */
160
+ isBrowserRunning: () => boolean;
161
+ /** Safely closes the browser, kills the process, and cleans up temporary directories. */
162
+ closeBrowser: () => Promise<boolean>;
163
+ /** No error occurred during launch. */
164
+ launchError: null;
165
+ }
166
+
167
+ /**
168
+ * Failed Puppeteer browser launch result.
169
+ * When launchError is set, browser/context/page are null.
170
+ */
171
+ export interface PpBrowserControllerError {
172
+ /** Null on launch failure. */
173
+ browser: null;
174
+ /** Null on launch failure. */
175
+ context: null;
176
+ /** Null on launch failure. */
177
+ page: null;
178
+ /** Returns false since the browser failed to launch. */
179
+ isBrowserRunning: () => boolean;
180
+ /** No-op cleanup function. */
181
+ closeBrowser: () => Promise<boolean>;
182
+ /** The error that occurred during launch. */
183
+ launchError: Error;
184
+ }
185
+
186
+ /**
187
+ * The object returned by launchPuppeteer.
188
+ * Check launchError to discriminate between success and failure states.
189
+ */
190
+ export type PpBrowserController = PpBrowserControllerSuccess | PpBrowserControllerError;
191
+
192
+ /**
193
+ * Launches a browser via Puppeteer CDP based on the provided options.
194
+ * Spawns the browser process, connects via Chrome DevTools Protocol.
195
+ *
196
+ * Supported browsers: Chrome, Brave, Multilogin.
197
+ * Profile directory: ~/.arn-browser/pp/
198
+ */
199
+ export function ppLaunch(options?: PpLaunchOptions): Promise<PpBrowserController>;