@aluvia/sdk 1.0.0 → 1.3.0
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/README.md +425 -256
- package/dist/cjs/api/account.js +10 -74
- package/dist/cjs/api/apiUtils.js +80 -0
- package/dist/cjs/api/geos.js +2 -63
- package/dist/cjs/api/request.js +8 -2
- package/dist/cjs/bin/account.js +31 -0
- package/dist/cjs/bin/api-helpers.js +58 -0
- package/dist/cjs/bin/cli.js +245 -0
- package/dist/cjs/bin/close.js +120 -0
- package/dist/cjs/bin/geos.js +10 -0
- package/dist/cjs/bin/mcp-helpers.js +57 -0
- package/dist/cjs/bin/mcp-server.js +220 -0
- package/dist/cjs/bin/mcp-tools.js +90 -0
- package/dist/cjs/bin/open.js +293 -0
- package/dist/cjs/bin/session.js +259 -0
- package/dist/cjs/client/AluviaClient.js +411 -150
- package/dist/cjs/client/BlockDetection.js +486 -0
- package/dist/cjs/client/ConfigManager.js +26 -23
- package/dist/cjs/client/PageLoadDetection.js +175 -0
- package/dist/cjs/client/ProxyServer.js +4 -2
- package/dist/cjs/client/logger.js +4 -0
- package/dist/cjs/client/rules.js +38 -49
- package/dist/cjs/connect.js +117 -0
- package/dist/cjs/errors.js +12 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/session/lock.js +186 -0
- package/dist/esm/api/account.js +2 -66
- package/dist/esm/api/apiUtils.js +71 -0
- package/dist/esm/api/geos.js +2 -63
- package/dist/esm/api/request.js +8 -2
- package/dist/esm/bin/account.js +28 -0
- package/dist/esm/bin/api-helpers.js +53 -0
- package/dist/esm/bin/cli.js +242 -0
- package/dist/esm/bin/close.js +117 -0
- package/dist/esm/bin/geos.js +7 -0
- package/dist/esm/bin/mcp-helpers.js +51 -0
- package/dist/esm/bin/mcp-server.js +185 -0
- package/dist/esm/bin/mcp-tools.js +78 -0
- package/dist/esm/bin/open.js +256 -0
- package/dist/esm/bin/session.js +252 -0
- package/dist/esm/client/AluviaClient.js +384 -156
- package/dist/esm/client/BlockDetection.js +482 -0
- package/dist/esm/client/ConfigManager.js +21 -18
- package/dist/esm/client/PageLoadDetection.js +171 -0
- package/dist/esm/client/ProxyServer.js +5 -3
- package/dist/esm/client/logger.js +4 -0
- package/dist/esm/client/rules.js +36 -49
- package/dist/esm/connect.js +81 -0
- package/dist/esm/errors.js +10 -0
- package/dist/esm/index.js +5 -3
- package/dist/esm/session/lock.js +142 -0
- package/dist/types/api/AluviaApi.d.ts +2 -7
- package/dist/types/api/account.d.ts +1 -16
- package/dist/types/api/apiUtils.d.ts +28 -0
- package/dist/types/api/geos.d.ts +1 -1
- package/dist/types/bin/account.d.ts +1 -0
- package/dist/types/bin/api-helpers.d.ts +20 -0
- package/dist/types/bin/cli.d.ts +2 -0
- package/dist/types/bin/close.d.ts +1 -0
- package/dist/types/bin/geos.d.ts +1 -0
- package/dist/types/bin/mcp-helpers.d.ts +28 -0
- package/dist/types/bin/mcp-server.d.ts +2 -0
- package/dist/types/bin/mcp-tools.d.ts +46 -0
- package/dist/types/bin/open.d.ts +21 -0
- package/dist/types/bin/session.d.ts +11 -0
- package/dist/types/client/AluviaClient.d.ts +51 -4
- package/dist/types/client/BlockDetection.d.ts +96 -0
- package/dist/types/client/ConfigManager.d.ts +6 -1
- package/dist/types/client/PageLoadDetection.d.ts +93 -0
- package/dist/types/client/logger.d.ts +2 -0
- package/dist/types/client/rules.d.ts +18 -0
- package/dist/types/client/types.d.ts +69 -46
- package/dist/types/connect.d.ts +18 -0
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/index.d.ts +7 -5
- package/dist/types/session/lock.d.ts +43 -0
- package/package.json +11 -2
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { handleOpen } from './open.js';
|
|
3
|
+
import { handleClose } from './close.js';
|
|
4
|
+
import { listSessions } from '../session/lock.js';
|
|
5
|
+
import { requireApi, resolveSession, requireConnectionId } from './api-helpers.js';
|
|
6
|
+
import { output } from './cli.js';
|
|
7
|
+
export function parseSessionArgs(args) {
|
|
8
|
+
let url;
|
|
9
|
+
let connectionId;
|
|
10
|
+
let headed = false;
|
|
11
|
+
let sessionName;
|
|
12
|
+
let autoUnblock = false;
|
|
13
|
+
let disableBlockDetection = false;
|
|
14
|
+
let run;
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
if (args[i] === '--connection-id' && args[i + 1]) {
|
|
17
|
+
const parsed = Number(args[i + 1]);
|
|
18
|
+
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
19
|
+
output({ error: `Invalid --connection-id: '${args[i + 1]}' must be a positive integer.` }, 1);
|
|
20
|
+
}
|
|
21
|
+
connectionId = parsed;
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
else if (args[i] === '--browser-session' && args[i + 1]) {
|
|
25
|
+
sessionName = args[i + 1];
|
|
26
|
+
i++;
|
|
27
|
+
}
|
|
28
|
+
else if (args[i] === '--run' && args[i + 1]) {
|
|
29
|
+
run = args[i + 1];
|
|
30
|
+
i++;
|
|
31
|
+
}
|
|
32
|
+
else if (args[i] === '--headful') {
|
|
33
|
+
headed = true;
|
|
34
|
+
}
|
|
35
|
+
else if (args[i] === '--auto-unblock') {
|
|
36
|
+
autoUnblock = true;
|
|
37
|
+
}
|
|
38
|
+
else if (args[i] === '--disable-block-detection') {
|
|
39
|
+
disableBlockDetection = true;
|
|
40
|
+
}
|
|
41
|
+
else if (!url && !args[i].startsWith('--')) {
|
|
42
|
+
url = args[i];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { url, connectionId, headed, sessionName, autoUnblock, disableBlockDetection, run };
|
|
46
|
+
}
|
|
47
|
+
export async function handleSession(args) {
|
|
48
|
+
const subcommand = args[0];
|
|
49
|
+
if (!subcommand) {
|
|
50
|
+
return output({ error: 'Missing session subcommand. Run "aluvia help" for usage.' }, 1);
|
|
51
|
+
}
|
|
52
|
+
switch (subcommand) {
|
|
53
|
+
case 'start':
|
|
54
|
+
return handleSessionStart(args.slice(1));
|
|
55
|
+
case 'close':
|
|
56
|
+
return handleSessionClose(args.slice(1));
|
|
57
|
+
case 'list':
|
|
58
|
+
return handleSessionList();
|
|
59
|
+
case 'get':
|
|
60
|
+
return handleSessionGet(args.slice(1));
|
|
61
|
+
case 'rotate-ip':
|
|
62
|
+
return handleSessionRotateIp(args.slice(1));
|
|
63
|
+
case 'set-geo':
|
|
64
|
+
return handleSessionSetGeo(args.slice(1));
|
|
65
|
+
case 'set-rules':
|
|
66
|
+
return handleSessionSetRules(args.slice(1));
|
|
67
|
+
default:
|
|
68
|
+
return output({ error: `Unknown session subcommand: '${subcommand}'. Run "aluvia help" for usage.` }, 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function handleSessionStart(args) {
|
|
72
|
+
const parsed = parseSessionArgs(args);
|
|
73
|
+
if (!parsed.url) {
|
|
74
|
+
return output({ error: 'URL is required. Usage: aluvia session start <url> [options]' }, 1);
|
|
75
|
+
}
|
|
76
|
+
const opts = {
|
|
77
|
+
url: parsed.url,
|
|
78
|
+
connectionId: parsed.connectionId,
|
|
79
|
+
headless: !parsed.headed,
|
|
80
|
+
sessionName: parsed.sessionName,
|
|
81
|
+
autoUnblock: parsed.autoUnblock,
|
|
82
|
+
disableBlockDetection: parsed.disableBlockDetection,
|
|
83
|
+
run: parsed.run,
|
|
84
|
+
};
|
|
85
|
+
// Delegates to the existing open handler (spawns daemon, waits for ready)
|
|
86
|
+
await handleOpen(opts);
|
|
87
|
+
}
|
|
88
|
+
async function handleSessionClose(args) {
|
|
89
|
+
let sessionName;
|
|
90
|
+
let all = false;
|
|
91
|
+
for (let i = 0; i < args.length; i++) {
|
|
92
|
+
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
93
|
+
sessionName = args[i + 1];
|
|
94
|
+
i++;
|
|
95
|
+
}
|
|
96
|
+
else if (args[i] === '--all') {
|
|
97
|
+
all = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
await handleClose(sessionName, all);
|
|
101
|
+
}
|
|
102
|
+
function handleSessionList() {
|
|
103
|
+
const sessions = listSessions();
|
|
104
|
+
return output({
|
|
105
|
+
sessions: sessions.map((s) => ({
|
|
106
|
+
browserSession: s.session,
|
|
107
|
+
pid: s.pid,
|
|
108
|
+
startUrl: s.url ?? null,
|
|
109
|
+
cdpUrl: s.cdpUrl ?? null,
|
|
110
|
+
connectionId: s.connectionId ?? null,
|
|
111
|
+
blockDetection: s.blockDetection ?? false,
|
|
112
|
+
autoUnblock: s.autoUnblock ?? false,
|
|
113
|
+
})),
|
|
114
|
+
count: sessions.length,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
async function handleSessionGet(args) {
|
|
118
|
+
let sessionName;
|
|
119
|
+
for (let i = 0; i < args.length; i++) {
|
|
120
|
+
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
121
|
+
sessionName = args[i + 1];
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const { session, lock } = resolveSession(sessionName);
|
|
126
|
+
const connId = lock.connectionId;
|
|
127
|
+
const base = {
|
|
128
|
+
browserSession: session,
|
|
129
|
+
pid: lock.pid,
|
|
130
|
+
startUrl: lock.url ?? null,
|
|
131
|
+
cdpUrl: lock.cdpUrl ?? null,
|
|
132
|
+
connectionId: connId ?? null,
|
|
133
|
+
blockDetection: lock.blockDetection ?? false,
|
|
134
|
+
autoUnblock: lock.autoUnblock ?? false,
|
|
135
|
+
lastDetection: lock.lastDetection ?? null,
|
|
136
|
+
};
|
|
137
|
+
// If we have a connection ID, enrich with full connection object from API
|
|
138
|
+
if (connId != null) {
|
|
139
|
+
try {
|
|
140
|
+
const api = requireApi();
|
|
141
|
+
const conn = await api.account.connections.get(connId);
|
|
142
|
+
if (conn) {
|
|
143
|
+
base.connection = conn;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// API enrichment is best-effort; base lock data is still returned
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return output(base);
|
|
151
|
+
}
|
|
152
|
+
async function handleSessionRotateIp(args) {
|
|
153
|
+
let sessionName;
|
|
154
|
+
for (let i = 0; i < args.length; i++) {
|
|
155
|
+
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
156
|
+
sessionName = args[i + 1];
|
|
157
|
+
i++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const { session, lock } = resolveSession(sessionName);
|
|
161
|
+
const connId = requireConnectionId(lock, session);
|
|
162
|
+
const api = requireApi();
|
|
163
|
+
const newSessionId = crypto.randomUUID().replace(/-/g, '');
|
|
164
|
+
await api.account.connections.patch(connId, { session_id: newSessionId });
|
|
165
|
+
return output({
|
|
166
|
+
browserSession: session,
|
|
167
|
+
connectionId: connId,
|
|
168
|
+
sessionId: newSessionId,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async function handleSessionSetGeo(args) {
|
|
172
|
+
let sessionName;
|
|
173
|
+
let geo;
|
|
174
|
+
let clear = false;
|
|
175
|
+
for (let i = 0; i < args.length; i++) {
|
|
176
|
+
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
177
|
+
sessionName = args[i + 1];
|
|
178
|
+
i++;
|
|
179
|
+
}
|
|
180
|
+
else if (args[i] === '--clear') {
|
|
181
|
+
clear = true;
|
|
182
|
+
}
|
|
183
|
+
else if (!geo && !args[i].startsWith('--')) {
|
|
184
|
+
geo = args[i];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (!geo && !clear) {
|
|
188
|
+
return output({ error: 'Geo code is required. Usage: aluvia session set-geo <geo> [--browser-session <name>]' }, 1);
|
|
189
|
+
}
|
|
190
|
+
if (geo && !geo.trim()) {
|
|
191
|
+
return output({ error: 'Geo code cannot be empty. Provide a valid geo code or use --clear.' }, 1);
|
|
192
|
+
}
|
|
193
|
+
const { session, lock } = resolveSession(sessionName);
|
|
194
|
+
const connId = requireConnectionId(lock, session);
|
|
195
|
+
const api = requireApi();
|
|
196
|
+
const targetGeo = clear ? null : geo.trim();
|
|
197
|
+
await api.account.connections.patch(connId, { target_geo: targetGeo });
|
|
198
|
+
return output({
|
|
199
|
+
browserSession: session,
|
|
200
|
+
connectionId: connId,
|
|
201
|
+
targetGeo,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function handleSessionSetRules(args) {
|
|
205
|
+
let sessionName;
|
|
206
|
+
let removeRules;
|
|
207
|
+
let appendRules;
|
|
208
|
+
for (let i = 0; i < args.length; i++) {
|
|
209
|
+
if (args[i] === '--browser-session' && args[i + 1]) {
|
|
210
|
+
sessionName = args[i + 1];
|
|
211
|
+
i++;
|
|
212
|
+
}
|
|
213
|
+
else if (args[i] === '--remove' && args[i + 1]) {
|
|
214
|
+
removeRules = args[i + 1];
|
|
215
|
+
i++;
|
|
216
|
+
}
|
|
217
|
+
else if (!appendRules && !args[i].startsWith('--')) {
|
|
218
|
+
appendRules = args[i];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!appendRules && !removeRules) {
|
|
222
|
+
return output({ error: 'Rules are required. Usage: aluvia session set-rules <rules> [--browser-session <name>]' }, 1);
|
|
223
|
+
}
|
|
224
|
+
if (appendRules && removeRules) {
|
|
225
|
+
return output({ error: 'Cannot both append and remove rules. Use either <rules> or --remove <rules>, not both.' }, 1);
|
|
226
|
+
}
|
|
227
|
+
const { session, lock } = resolveSession(sessionName);
|
|
228
|
+
const connId = requireConnectionId(lock, session);
|
|
229
|
+
const api = requireApi();
|
|
230
|
+
// Fetch current rules
|
|
231
|
+
const conn = await api.account.connections.get(connId);
|
|
232
|
+
const currentRules = conn?.rules ?? [];
|
|
233
|
+
let newRules;
|
|
234
|
+
if (removeRules) {
|
|
235
|
+
// Remove mode: filter out specified rules
|
|
236
|
+
const toRemove = new Set(removeRules.split(',').map((r) => r.trim()).filter(Boolean));
|
|
237
|
+
newRules = currentRules.filter((r) => !toRemove.has(r));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
// Append mode: add new rules to existing (deduplicate)
|
|
241
|
+
const toAdd = appendRules.split(',').map((r) => r.trim()).filter(Boolean);
|
|
242
|
+
const existing = new Set(currentRules);
|
|
243
|
+
newRules = [...currentRules, ...toAdd.filter((r) => !existing.has(r))];
|
|
244
|
+
}
|
|
245
|
+
await api.account.connections.patch(connId, { rules: newRules });
|
|
246
|
+
return output({
|
|
247
|
+
browserSession: session,
|
|
248
|
+
connectionId: connId,
|
|
249
|
+
rules: newRules,
|
|
250
|
+
count: newRules.length,
|
|
251
|
+
});
|
|
252
|
+
}
|