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
@@ -1,61 +1,51 @@
1
- // multilogin_token_manager.js
1
+ // mlx_token.js
2
2
 
3
3
  import crypto from "crypto";
4
4
  import { arn, query } from "arn-knexjs";
5
5
 
6
- // Environment variables for Multilogin
7
- const MULTILOGIN_EMAIL = process.env.MULTILOGIN_EMAIL;
8
- const MULTILOGIN_PASSWORD = process.env.MULTILOGIN_PASSWORD;
9
- const MULTILOGIN_WORKSPACE_ID = process.env.MULTILOGIN_WORKSPACE_ID;
10
- const MULTILOGIN_ROW_ID = process.env.MULTILOGIN_ROW_ID;
6
+ // Module-level cache for credentials (fetched once per process)
7
+ let _credentials = null;
11
8
 
12
9
  /**
13
- * Validates that all required environment variables are set.
10
+ * Loads Multilogin credentials from the database.
11
+ * Queries `api_multilogin_token` for a single row where `status = 1`.
12
+ * Results are cached in-memory so the DB is only hit once per process.
13
+ * @returns {Promise<{id: string, email: string, password: string, workspace_id: string, data: object}>}
14
14
  */
15
- function validateEnv() {
16
- const required = {
17
- MULTILOGIN_EMAIL,
18
- MULTILOGIN_PASSWORD,
19
- MULTILOGIN_WORKSPACE_ID,
20
- MULTILOGIN_ROW_ID,
21
- };
15
+ async function loadCredentials() {
16
+ if (_credentials) return _credentials;
22
17
 
23
- const missing = Object.entries(required)
24
- .filter(([, value]) => !value)
25
- .map(([key]) => key);
18
+ const { data: [row] = [], error } = await arn.single(
19
+ query("api_multilogin_token").select("*").where({ status: 1 }).orderByRaw("random()").limit(1)
20
+ );
26
21
 
27
- if (missing.length > 0) {
28
- throw new Error(`[TokenManager] Missing environment variables: ${missing.join(", ")}`);
22
+ if (error || !row) {
23
+ throw new Error("[TokenManager] No active Multilogin credentials found (status = 1).");
29
24
  }
25
+
26
+ _credentials = row;
27
+ return _credentials;
30
28
  }
31
29
 
32
30
  async function saveTokens(tokens) {
33
- validateEnv();
31
+ const creds = await loadCredentials();
34
32
 
35
33
  await arn.single(
36
34
  query("api_multilogin_token")
37
35
  .update({
38
36
  data: JSON.stringify(tokens, null, 2),
39
37
  })
40
- .where({ id: MULTILOGIN_ROW_ID })
38
+ .where({ id: creds.id })
41
39
  );
42
40
  }
43
41
 
44
42
  async function loadTokens() {
45
43
  try {
46
- validateEnv();
47
-
48
- const { data: [data] = [], error } = await arn.single(
49
- query("api_multilogin_token").select("*").where({ id: MULTILOGIN_ROW_ID }).limit(1)
50
- );
51
- if (error) {
52
- console.error("Error loading tokens:", error);
53
- return null;
54
- }
55
- if (!data || !data.data) {
44
+ const creds = await loadCredentials();
45
+ if (!creds.data || Object.keys(creds.data).length === 0) {
56
46
  return null;
57
47
  }
58
- return data.data;
48
+ return creds.data;
59
49
  } catch (err) {
60
50
  return null;
61
51
  }
@@ -73,11 +63,11 @@ function isJwtExpired(token) {
73
63
  }
74
64
 
75
65
  async function loginAndSaveTokens() {
76
- validateEnv();
66
+ const creds = await loadCredentials();
77
67
 
78
- const passwordHash = crypto.createHash("md5").update(MULTILOGIN_PASSWORD).digest("hex");
68
+ const passwordHash = crypto.createHash("md5").update(creds.password).digest("hex");
79
69
  const data = {
80
- email: MULTILOGIN_EMAIL,
70
+ email: creds.email,
81
71
  password: passwordHash,
82
72
  };
83
73
 
@@ -98,8 +88,8 @@ async function loginAndSaveTokens() {
98
88
  await saveTokens({
99
89
  token,
100
90
  refresh_token,
101
- email: MULTILOGIN_EMAIL,
102
- workspace_id: MULTILOGIN_WORKSPACE_ID,
91
+ email: creds.email,
92
+ workspace_id: creds.workspace_id,
103
93
  });
104
94
 
105
95
  console.log("[LOGIN] Tokens updated and saved.");
@@ -107,12 +97,12 @@ async function loginAndSaveTokens() {
107
97
  }
108
98
 
109
99
  async function refreshAndSaveTokens(refresh_token) {
110
- validateEnv();
100
+ const creds = await loadCredentials();
111
101
 
112
102
  const data = {
113
- email: MULTILOGIN_EMAIL,
103
+ email: creds.email,
114
104
  refresh_token: refresh_token,
115
- workspace_id: MULTILOGIN_WORKSPACE_ID,
105
+ workspace_id: creds.workspace_id,
116
106
  };
117
107
 
118
108
  const res = await fetch("https://api.multilogin.com/user/refresh_token", {
@@ -132,8 +122,8 @@ async function refreshAndSaveTokens(refresh_token) {
132
122
  await saveTokens({
133
123
  token,
134
124
  refresh_token: new_refresh,
135
- email: MULTILOGIN_EMAIL,
136
- workspace_id: MULTILOGIN_WORKSPACE_ID,
125
+ email: creds.email,
126
+ workspace_id: creds.workspace_id,
137
127
  });
138
128
 
139
129
  console.log("[REFRESH] Tokens refreshed and saved.");
@@ -141,7 +131,6 @@ async function refreshAndSaveTokens(refresh_token) {
141
131
  }
142
132
 
143
133
  async function getMultiloginToken() {
144
- validateEnv();
145
134
  let tokens = await loadTokens();
146
135
 
147
136
  if (tokens && tokens.token && !isJwtExpired(tokens.token)) {
@@ -1,6 +1,6 @@
1
1
  import { Browser, BrowserContext, Page } from "playwright";
2
2
  import type { FingerprintGeneratorOptions } from "fingerprint-generator";
3
- import type { HumanPage, CreateCursorOptions } from "../human-cursor/index";
3
+ import type { HumanPage, CreateCursorOptions } from "./human-cursor/index";
4
4
  type Screen = FingerprintGeneratorOptions["screen"];
5
5
  /**
6
6
  * Proxy configuration object.
@@ -119,7 +119,7 @@ export interface MultiloginOptions {
119
119
  /**
120
120
  * Options for launching the browser.
121
121
  */
122
- export interface LaunchOptions {
122
+ export interface PwLaunchOptions {
123
123
  // ========================================================================
124
124
  // 1. GENERAL & NETWORK
125
125
  // ========================================================================
@@ -141,7 +141,15 @@ export interface LaunchOptions {
141
141
 
142
142
  /**
143
143
  * Which browser engine to launch.
144
- * Default: "chromium"
144
+ *
145
+ * - `"chromium"`: Playwright's bundled Chromium
146
+ * - `"chrome"`: Alias for Chromium
147
+ * - `"firefox"`: Playwright's bundled Firefox
148
+ * - `"brave"`: Brave Browser (requires local binary)
149
+ * - `"camoufox"`: Camoufox anti-detect Firefox (requires local binary)
150
+ * - `"multilogin"`: Multilogin anti-detect browser (via API)
151
+ *
152
+ * Default: `"chromium"`
145
153
  */
146
154
  which_browser?: "chromium" | "chrome" | "firefox" | "brave" | "braveLauncher" | "camoufox" | "multilogin";
147
155
 
@@ -150,23 +158,22 @@ export interface LaunchOptions {
150
158
  // ========================================================================
151
159
 
152
160
  /**
153
- * Path to a browser profile.
161
+ * Path to a persistent profile.
154
162
  * - If absolute path: Uses that path exactly (no prefix added).
155
- * - If folder name: Creates inside `~/.arn-browser/browser_profiles/` with a browser prefix (e.g., `brave_myProfile`).
156
- * - If null: Creates a temporary, random profile that is deleted on browser close.
157
- *
158
- * When combined with `cleanupMinutes`, named profiles can be auto-deleted
159
- * after a period of inactivity (based on `_profile_meta.json`).
163
+ * - If folder name: Creates inside `~/.arn-browser/pw/persistent/` AND adds a browser prefix (e.g., `brave_myProfile`).
164
+ * - If null: Creates a temporary, random profile in `~/.arn-browser/pw/temp/`.
160
165
  */
161
166
  profile_path?: string | null;
162
167
 
163
168
  /**
164
- * Auto-delete schedule for named profiles (in minutes).
165
- * - `0` or not set: Profile is permanent (never auto-deleted).
166
- * - `> 0`: Profile is auto-deleted after this many minutes of inactivity.
167
- * The inactivity timer resets on each launch.
168
- * - Only applies to named profiles (with `profile_path`).
169
- * Unnamed profiles are always deleted on close regardless.
169
+ * Auto-cleanup profiles after X minutes since last launch.
170
+ *
171
+ * **Persistent profiles:** Cleaned after X minutes since last launch. Default: 0 (never clean).
172
+ * **Temp profiles:** Default: 15 minutes if not specified.
173
+ *
174
+ * Each profile stores a `_profile_meta.json` with `created_at`, `last_launched_at`,
175
+ * and `cleanup_minutes`. The profile currently being launched is always skipped during cleanup.
176
+ *
170
177
  * Default: 0
171
178
  */
172
179
  cleanupMinutes?: number;
@@ -232,7 +239,7 @@ export interface LaunchOptions {
232
239
  humanize_options?: HumanizeOptions;
233
240
 
234
241
  // ========================================================================
235
- // 7. LOGGING
242
+ // 6. LOGGING
236
243
  // ========================================================================
237
244
 
238
245
  /**
@@ -294,9 +301,9 @@ export interface BrowserControllerError {
294
301
  * The object returned by launchBrowser.
295
302
  * Check launchError to discriminate between success and failure states.
296
303
  */
297
- export type BrowserController = BrowserControllerSuccess | BrowserControllerError;
304
+ export type PwBrowserController = BrowserControllerSuccess | BrowserControllerError;
298
305
 
299
306
  /**
300
307
  * Launches a browser based on the provided options.
301
308
  */
302
- export function launchBrowser(options: LaunchOptions): Promise<BrowserController>;
309
+ export function pwLaunch(options?: PwLaunchOptions): Promise<PwBrowserController>;