lexmount 0.2.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/LICENSE +21 -0
- package/README.md +493 -0
- package/dist/index.d.mts +492 -0
- package/dist/index.d.ts +492 -0
- package/dist/index.js +903 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +846 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Lexmount
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
# Lexmount Node.js SDK
|
|
2
|
+
|
|
3
|
+
[English](#english) | [中文](#中文)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## English
|
|
8
|
+
|
|
9
|
+
Node.js SDK for the Lexmount browser automation service.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
- Node.js 18+ only
|
|
14
|
+
- Typed public API with ESM and CommonJS support
|
|
15
|
+
- Session management with pagination support
|
|
16
|
+
- Persistent context management
|
|
17
|
+
- Structured SDK errors
|
|
18
|
+
- Configurable SDK logging
|
|
19
|
+
- TSDoc + TypeDoc based API documentation generation
|
|
20
|
+
|
|
21
|
+
### Requirements
|
|
22
|
+
|
|
23
|
+
- Node.js 18 LTS or later
|
|
24
|
+
- npm 9+ recommended
|
|
25
|
+
- Playwright is optional and only needed when you connect to browser sessions
|
|
26
|
+
|
|
27
|
+
### Installation
|
|
28
|
+
|
|
29
|
+
#### Internal package / tgz
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install <lexmount-package-or-tgz>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### From source
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone <repository-url>
|
|
39
|
+
cd lexmount-js-sdk
|
|
40
|
+
npm install
|
|
41
|
+
npm run build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Configuration
|
|
45
|
+
|
|
46
|
+
The SDK reads credentials from constructor options or environment variables.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
LEXMOUNT_API_KEY=your-api-key
|
|
50
|
+
LEXMOUNT_PROJECT_ID=your-project-id
|
|
51
|
+
LEXMOUNT_BASE_URL=https://api.lexmount.cn
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`LEXMOUNT_BASE_URL` is optional. The default is `https://api.lexmount.cn`.
|
|
55
|
+
|
|
56
|
+
### Quick Start
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { Lexmount } from 'lexmount';
|
|
60
|
+
|
|
61
|
+
const client = new Lexmount({
|
|
62
|
+
apiKey: process.env.LEXMOUNT_API_KEY,
|
|
63
|
+
projectId: process.env.LEXMOUNT_PROJECT_ID,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const session = await client.sessions.create();
|
|
67
|
+
console.log(session.id);
|
|
68
|
+
console.log(session.connectUrl);
|
|
69
|
+
|
|
70
|
+
await session.close();
|
|
71
|
+
client.close();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Sessions
|
|
75
|
+
|
|
76
|
+
Create a session:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const session = await client.sessions.create({
|
|
80
|
+
browserMode: 'normal',
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Create a session with a persistent context:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const context = await client.contexts.create({
|
|
88
|
+
metadata: { userId: '1001' },
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const session = await client.sessions.create({
|
|
92
|
+
context: { id: context.id, mode: 'readWrite' },
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
List sessions with pagination metadata:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
const result = await client.sessions.list({ status: 'active' });
|
|
100
|
+
|
|
101
|
+
console.log(result.pagination.totalCount);
|
|
102
|
+
for (const session of result) {
|
|
103
|
+
console.log(session.id, session.status);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Delete a session:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
await client.sessions.delete({ sessionId: 'session-id' });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Contexts
|
|
114
|
+
|
|
115
|
+
Create and inspect contexts:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const context = await client.contexts.create({
|
|
119
|
+
metadata: { owner: 'demo' },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const details = await client.contexts.get(context.id);
|
|
123
|
+
console.log(details.status);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
List contexts:
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
const contexts = await client.contexts.list({
|
|
130
|
+
status: 'available',
|
|
131
|
+
limit: 20,
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Force release a stuck lock:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
await client.contexts.forceRelease('context-id');
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Playwright Example
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
import { chromium } from 'playwright';
|
|
145
|
+
import { Lexmount } from 'lexmount';
|
|
146
|
+
|
|
147
|
+
const client = new Lexmount();
|
|
148
|
+
const session = await client.sessions.create();
|
|
149
|
+
|
|
150
|
+
const browser = await chromium.connectOverCDP(session.connectUrl);
|
|
151
|
+
const context = browser.contexts()[0];
|
|
152
|
+
const page = context.pages()[0] ?? (await context.newPage());
|
|
153
|
+
|
|
154
|
+
await page.goto('https://example.com');
|
|
155
|
+
console.log(await page.title());
|
|
156
|
+
|
|
157
|
+
await browser.close();
|
|
158
|
+
await session.close();
|
|
159
|
+
client.close();
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Error Handling
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import {
|
|
166
|
+
AuthenticationError,
|
|
167
|
+
ContextLockedError,
|
|
168
|
+
NetworkError,
|
|
169
|
+
TimeoutError,
|
|
170
|
+
} from 'lexmount';
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
await client.sessions.create({
|
|
174
|
+
context: { id: 'ctx_123', mode: 'readWrite' },
|
|
175
|
+
});
|
|
176
|
+
} catch (error) {
|
|
177
|
+
if (error instanceof AuthenticationError) {
|
|
178
|
+
console.error('Authentication failed');
|
|
179
|
+
} else if (error instanceof ContextLockedError) {
|
|
180
|
+
console.error(error.activeSessionId, error.retryAfter);
|
|
181
|
+
} else if (error instanceof TimeoutError || error instanceof NetworkError) {
|
|
182
|
+
console.error('Temporary connectivity issue');
|
|
183
|
+
} else {
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Logging
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
import { setLogLevel } from 'lexmount';
|
|
193
|
+
|
|
194
|
+
setLogLevel('DEBUG');
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Available levels:
|
|
198
|
+
|
|
199
|
+
- `DEBUG`
|
|
200
|
+
- `INFO`
|
|
201
|
+
- `WARNING`
|
|
202
|
+
- `ERROR`
|
|
203
|
+
- `CRITICAL`
|
|
204
|
+
- `SILENT`
|
|
205
|
+
|
|
206
|
+
### Documentation Generation
|
|
207
|
+
|
|
208
|
+
Public API docs are generated from TSDoc comments.
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
npm run docs:api
|
|
212
|
+
npm run docs:html
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Generated files are written to `generated-docs/` and are not meant to be committed.
|
|
216
|
+
|
|
217
|
+
### Examples
|
|
218
|
+
|
|
219
|
+
Example scripts live in [examples](./examples):
|
|
220
|
+
|
|
221
|
+
- `playwright-basic.ts`
|
|
222
|
+
- `session-management.ts`
|
|
223
|
+
- `context-basic.ts`
|
|
224
|
+
- `context-list-get.ts`
|
|
225
|
+
- `context-modes.ts`
|
|
226
|
+
- `context-lock-handling.ts`
|
|
227
|
+
|
|
228
|
+
Run them with:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
cd examples
|
|
232
|
+
npm install
|
|
233
|
+
npm run playwright-basic
|
|
234
|
+
npm run session-management
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Development
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npm run build
|
|
241
|
+
npm run typecheck
|
|
242
|
+
npm test
|
|
243
|
+
npm run docs:api
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### License
|
|
247
|
+
|
|
248
|
+
MIT License
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 中文
|
|
253
|
+
|
|
254
|
+
Lexmount 浏览器自动化服务的 Node.js SDK。
|
|
255
|
+
|
|
256
|
+
### 特性
|
|
257
|
+
|
|
258
|
+
- 仅支持 Node.js 18+
|
|
259
|
+
- 提供完整类型定义,同时支持 ESM 和 CommonJS
|
|
260
|
+
- 会话管理,支持分页信息
|
|
261
|
+
- 持久化 context 管理
|
|
262
|
+
- 结构化 SDK 异常
|
|
263
|
+
- 可配置 SDK 日志
|
|
264
|
+
- 基于 TSDoc + TypeDoc 的自动文档生成能力
|
|
265
|
+
|
|
266
|
+
### 运行要求
|
|
267
|
+
|
|
268
|
+
- Node.js 18 LTS 或更高版本
|
|
269
|
+
- 建议使用 npm 9+
|
|
270
|
+
- 如果需要连接浏览器会话,才需要额外安装 Playwright
|
|
271
|
+
|
|
272
|
+
### 安装
|
|
273
|
+
|
|
274
|
+
#### 内部包 / tgz
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npm install <lexmount-package-or-tgz>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### 从源码安装
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
git clone <repository-url>
|
|
284
|
+
cd lexmount-js-sdk
|
|
285
|
+
npm install
|
|
286
|
+
npm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### 配置
|
|
290
|
+
|
|
291
|
+
SDK 会优先读取构造参数,其次读取环境变量:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
LEXMOUNT_API_KEY=your-api-key
|
|
295
|
+
LEXMOUNT_PROJECT_ID=your-project-id
|
|
296
|
+
LEXMOUNT_BASE_URL=https://api.lexmount.cn
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
`LEXMOUNT_BASE_URL` 可选,默认值是 `https://api.lexmount.cn`。
|
|
300
|
+
|
|
301
|
+
### 快速开始
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
import { Lexmount } from 'lexmount';
|
|
305
|
+
|
|
306
|
+
const client = new Lexmount({
|
|
307
|
+
apiKey: process.env.LEXMOUNT_API_KEY,
|
|
308
|
+
projectId: process.env.LEXMOUNT_PROJECT_ID,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const session = await client.sessions.create();
|
|
312
|
+
console.log(session.id);
|
|
313
|
+
console.log(session.connectUrl);
|
|
314
|
+
|
|
315
|
+
await session.close();
|
|
316
|
+
client.close();
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Sessions
|
|
320
|
+
|
|
321
|
+
创建会话:
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
const session = await client.sessions.create({
|
|
325
|
+
browserMode: 'normal',
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
结合持久化 context 创建会话:
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
const context = await client.contexts.create({
|
|
333
|
+
metadata: { userId: '1001' },
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const session = await client.sessions.create({
|
|
337
|
+
context: { id: context.id, mode: 'readWrite' },
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
分页列出会话:
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
const result = await client.sessions.list({ status: 'active' });
|
|
345
|
+
|
|
346
|
+
console.log(result.pagination.totalCount);
|
|
347
|
+
for (const session of result) {
|
|
348
|
+
console.log(session.id, session.status);
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
删除会话:
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
await client.sessions.delete({ sessionId: 'session-id' });
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Contexts
|
|
359
|
+
|
|
360
|
+
创建并查看 context:
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
const context = await client.contexts.create({
|
|
364
|
+
metadata: { owner: 'demo' },
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const details = await client.contexts.get(context.id);
|
|
368
|
+
console.log(details.status);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
列出 context:
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
const contexts = await client.contexts.list({
|
|
375
|
+
status: 'available',
|
|
376
|
+
limit: 20,
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
强制释放卡住的锁:
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
await client.contexts.forceRelease('context-id');
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Playwright 示例
|
|
387
|
+
|
|
388
|
+
```ts
|
|
389
|
+
import { chromium } from 'playwright';
|
|
390
|
+
import { Lexmount } from 'lexmount';
|
|
391
|
+
|
|
392
|
+
const client = new Lexmount();
|
|
393
|
+
const session = await client.sessions.create();
|
|
394
|
+
|
|
395
|
+
const browser = await chromium.connectOverCDP(session.connectUrl);
|
|
396
|
+
const context = browser.contexts()[0];
|
|
397
|
+
const page = context.pages()[0] ?? (await context.newPage());
|
|
398
|
+
|
|
399
|
+
await page.goto('https://example.com');
|
|
400
|
+
console.log(await page.title());
|
|
401
|
+
|
|
402
|
+
await browser.close();
|
|
403
|
+
await session.close();
|
|
404
|
+
client.close();
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### 错误处理
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
import {
|
|
411
|
+
AuthenticationError,
|
|
412
|
+
ContextLockedError,
|
|
413
|
+
NetworkError,
|
|
414
|
+
TimeoutError,
|
|
415
|
+
} from 'lexmount';
|
|
416
|
+
|
|
417
|
+
try {
|
|
418
|
+
await client.sessions.create({
|
|
419
|
+
context: { id: 'ctx_123', mode: 'readWrite' },
|
|
420
|
+
});
|
|
421
|
+
} catch (error) {
|
|
422
|
+
if (error instanceof AuthenticationError) {
|
|
423
|
+
console.error('鉴权失败');
|
|
424
|
+
} else if (error instanceof ContextLockedError) {
|
|
425
|
+
console.error(error.activeSessionId, error.retryAfter);
|
|
426
|
+
} else if (error instanceof TimeoutError || error instanceof NetworkError) {
|
|
427
|
+
console.error('网络或超时问题');
|
|
428
|
+
} else {
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### 日志
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
import { setLogLevel } from 'lexmount';
|
|
438
|
+
|
|
439
|
+
setLogLevel('DEBUG');
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
可用级别:
|
|
443
|
+
|
|
444
|
+
- `DEBUG`
|
|
445
|
+
- `INFO`
|
|
446
|
+
- `WARNING`
|
|
447
|
+
- `ERROR`
|
|
448
|
+
- `CRITICAL`
|
|
449
|
+
- `SILENT`
|
|
450
|
+
|
|
451
|
+
### 自动文档生成
|
|
452
|
+
|
|
453
|
+
公开 API 文档基于源码里的 TSDoc 注释生成。
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
npm run docs:api
|
|
457
|
+
npm run docs:html
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
生成文件会输出到 `generated-docs/`,默认不提交到仓库。
|
|
461
|
+
|
|
462
|
+
### 示例
|
|
463
|
+
|
|
464
|
+
示例脚本位于 [examples](./examples):
|
|
465
|
+
|
|
466
|
+
- `playwright-basic.ts`
|
|
467
|
+
- `session-management.ts`
|
|
468
|
+
- `context-basic.ts`
|
|
469
|
+
- `context-list-get.ts`
|
|
470
|
+
- `context-modes.ts`
|
|
471
|
+
- `context-lock-handling.ts`
|
|
472
|
+
|
|
473
|
+
运行方式:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
cd examples
|
|
477
|
+
npm install
|
|
478
|
+
npm run playwright-basic
|
|
479
|
+
npm run session-management
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### 开发
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
npm run build
|
|
486
|
+
npm run typecheck
|
|
487
|
+
npm test
|
|
488
|
+
npm run docs:api
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### 许可证
|
|
492
|
+
|
|
493
|
+
MIT License
|