craftdriver 0.0.3 → 0.1.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 +67 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/bidi/connection.d.ts +62 -0
- package/dist/lib/bidi/connection.d.ts.map +1 -0
- package/dist/lib/bidi/connection.js +227 -0
- package/dist/lib/bidi/connection.js.map +1 -0
- package/dist/lib/bidi/index.d.ts +76 -0
- package/dist/lib/bidi/index.d.ts.map +1 -0
- package/dist/lib/bidi/index.js +114 -0
- package/dist/lib/bidi/index.js.map +1 -0
- package/dist/lib/bidi/logs.d.ts +104 -0
- package/dist/lib/bidi/logs.d.ts.map +1 -0
- package/dist/lib/bidi/logs.js +273 -0
- package/dist/lib/bidi/logs.js.map +1 -0
- package/dist/lib/bidi/network.d.ts +92 -0
- package/dist/lib/bidi/network.d.ts.map +1 -0
- package/dist/lib/bidi/network.js +259 -0
- package/dist/lib/bidi/network.js.map +1 -0
- package/dist/lib/bidi/storage.d.ts +81 -0
- package/dist/lib/bidi/storage.d.ts.map +1 -0
- package/dist/lib/bidi/storage.js +292 -0
- package/dist/lib/bidi/storage.js.map +1 -0
- package/dist/lib/bidi/types.d.ts +302 -0
- package/dist/lib/bidi/types.d.ts.map +1 -0
- package/dist/lib/bidi/types.js +6 -0
- package/dist/lib/bidi/types.js.map +1 -0
- package/dist/lib/browser.d.ts +142 -0
- package/dist/lib/browser.d.ts.map +1 -1
- package/dist/lib/browser.js +162 -11
- package/dist/lib/browser.js.map +1 -1
- package/dist/lib/driver.d.ts +2 -0
- package/dist/lib/driver.d.ts.map +1 -1
- package/dist/lib/driver.js +9 -1
- package/dist/lib/driver.js.map +1 -1
- package/dist/lib/elementHandle.d.ts +3 -0
- package/dist/lib/elementHandle.d.ts.map +1 -1
- package/dist/lib/elementHandle.js +33 -0
- package/dist/lib/elementHandle.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BiDi Network Interceptor
|
|
3
|
+
* Provides request interception, mocking, and modification capabilities
|
|
4
|
+
*/
|
|
5
|
+
export class NetworkInterceptor {
|
|
6
|
+
connection;
|
|
7
|
+
intercepts = new Map();
|
|
8
|
+
handlers = new Map();
|
|
9
|
+
subscribed = false;
|
|
10
|
+
context;
|
|
11
|
+
constructor(connection, context) {
|
|
12
|
+
this.connection = connection;
|
|
13
|
+
this.context = context;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Initialize network event subscriptions
|
|
17
|
+
*/
|
|
18
|
+
async initialize() {
|
|
19
|
+
if (this.subscribed)
|
|
20
|
+
return;
|
|
21
|
+
// Subscribe to network events
|
|
22
|
+
await this.connection.subscribe([
|
|
23
|
+
'network.beforeRequestSent',
|
|
24
|
+
'network.responseStarted',
|
|
25
|
+
'network.responseCompleted',
|
|
26
|
+
'network.fetchError',
|
|
27
|
+
'network.authRequired',
|
|
28
|
+
]);
|
|
29
|
+
// Handle intercepted requests
|
|
30
|
+
this.connection.on('network.beforeRequestSent', async (params) => {
|
|
31
|
+
await this.handleBeforeRequestSent(params);
|
|
32
|
+
});
|
|
33
|
+
this.subscribed = true;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Add a network intercept for specific URL patterns
|
|
37
|
+
*/
|
|
38
|
+
async intercept(patterns, handler, phases = ['beforeRequestSent']) {
|
|
39
|
+
await this.initialize();
|
|
40
|
+
const urlPatterns = this.normalizePatterns(patterns);
|
|
41
|
+
const result = await this.connection.send('network.addIntercept', {
|
|
42
|
+
phases,
|
|
43
|
+
urlPatterns,
|
|
44
|
+
...(this.context ? { contexts: [this.context] } : {}),
|
|
45
|
+
});
|
|
46
|
+
const interceptId = result.intercept;
|
|
47
|
+
this.intercepts.set(interceptId, {
|
|
48
|
+
id: interceptId,
|
|
49
|
+
patterns: urlPatterns,
|
|
50
|
+
phases,
|
|
51
|
+
handler,
|
|
52
|
+
});
|
|
53
|
+
this.handlers.set(interceptId, handler);
|
|
54
|
+
return interceptId;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Mock all requests matching pattern with a fixed response
|
|
58
|
+
*/
|
|
59
|
+
async mock(pattern, response) {
|
|
60
|
+
const handler = (req) => {
|
|
61
|
+
if (typeof response === 'function') {
|
|
62
|
+
return response(req);
|
|
63
|
+
}
|
|
64
|
+
return response;
|
|
65
|
+
};
|
|
66
|
+
return this.intercept(pattern, handler);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Block all requests matching pattern
|
|
70
|
+
*/
|
|
71
|
+
async block(pattern) {
|
|
72
|
+
return this.intercept(pattern, () => ({
|
|
73
|
+
status: 0,
|
|
74
|
+
body: '',
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Modify request headers for matching patterns
|
|
79
|
+
*/
|
|
80
|
+
async setExtraHeaders(headers, contexts) {
|
|
81
|
+
const headerList = Object.entries(headers).map(([name, value]) => ({
|
|
82
|
+
name,
|
|
83
|
+
value: { type: 'string', value },
|
|
84
|
+
}));
|
|
85
|
+
await this.connection.send('network.setExtraHeaders', {
|
|
86
|
+
headers: headerList,
|
|
87
|
+
...(contexts ? { contexts } : {}),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Continue a blocked request (optionally with modifications)
|
|
92
|
+
*/
|
|
93
|
+
async continueRequest(requestId, options) {
|
|
94
|
+
const params = { request: requestId };
|
|
95
|
+
if (options?.url)
|
|
96
|
+
params.url = options.url;
|
|
97
|
+
if (options?.method)
|
|
98
|
+
params.method = options.method;
|
|
99
|
+
if (options?.headers) {
|
|
100
|
+
params.headers = Object.entries(options.headers).map(([name, value]) => ({
|
|
101
|
+
name,
|
|
102
|
+
value: { type: 'string', value },
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
if (options?.body) {
|
|
106
|
+
params.body = { type: 'string', value: options.body };
|
|
107
|
+
}
|
|
108
|
+
await this.connection.send('network.continueRequest', params);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Provide a custom response for a blocked request
|
|
112
|
+
*/
|
|
113
|
+
async provideResponse(requestId, response) {
|
|
114
|
+
const params = { request: requestId };
|
|
115
|
+
if (response.status !== undefined)
|
|
116
|
+
params.statusCode = response.status;
|
|
117
|
+
if (response.statusText)
|
|
118
|
+
params.reasonPhrase = response.statusText;
|
|
119
|
+
if (response.headers) {
|
|
120
|
+
params.headers = Object.entries(response.headers).map(([name, value]) => ({
|
|
121
|
+
name,
|
|
122
|
+
value: { type: 'string', value },
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
if (response.body !== undefined) {
|
|
126
|
+
let bodyStr;
|
|
127
|
+
let bodyType = 'string';
|
|
128
|
+
if (typeof response.body === 'string') {
|
|
129
|
+
bodyStr = response.body;
|
|
130
|
+
}
|
|
131
|
+
else if (Buffer.isBuffer(response.body)) {
|
|
132
|
+
bodyStr = response.body.toString('base64');
|
|
133
|
+
bodyType = 'base64';
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// Object - serialize as JSON
|
|
137
|
+
bodyStr = JSON.stringify(response.body);
|
|
138
|
+
}
|
|
139
|
+
params.body = { type: bodyType, value: bodyStr };
|
|
140
|
+
}
|
|
141
|
+
await this.connection.send('network.provideResponse', params);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Fail a blocked request
|
|
145
|
+
*/
|
|
146
|
+
async failRequest(requestId) {
|
|
147
|
+
await this.connection.send('network.failRequest', { request: requestId });
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Remove an intercept
|
|
151
|
+
*/
|
|
152
|
+
async removeIntercept(interceptId) {
|
|
153
|
+
await this.connection.send('network.removeIntercept', { intercept: interceptId });
|
|
154
|
+
this.intercepts.delete(interceptId);
|
|
155
|
+
this.handlers.delete(interceptId);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Remove all intercepts
|
|
159
|
+
*/
|
|
160
|
+
async removeAllIntercepts() {
|
|
161
|
+
const ids = [...this.intercepts.keys()];
|
|
162
|
+
for (const id of ids) {
|
|
163
|
+
await this.removeIntercept(id);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Set cache behavior
|
|
168
|
+
*/
|
|
169
|
+
async setCacheBehavior(behavior, contexts) {
|
|
170
|
+
await this.connection.send('network.setCacheBehavior', {
|
|
171
|
+
cacheBehavior: behavior,
|
|
172
|
+
...(contexts ? { contexts } : {}),
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async handleBeforeRequestSent(event) {
|
|
176
|
+
if (!event.isBlocked || !event.intercepts?.length)
|
|
177
|
+
return;
|
|
178
|
+
const requestId = event.request.request;
|
|
179
|
+
// Find matching handler
|
|
180
|
+
for (const interceptId of event.intercepts) {
|
|
181
|
+
const handler = this.handlers.get(interceptId);
|
|
182
|
+
if (!handler)
|
|
183
|
+
continue;
|
|
184
|
+
const interceptedRequest = {
|
|
185
|
+
id: requestId,
|
|
186
|
+
url: event.request.url,
|
|
187
|
+
method: event.request.method,
|
|
188
|
+
headers: this.headersToObject(event.request.headers),
|
|
189
|
+
isBlocked: event.isBlocked,
|
|
190
|
+
context: event.context,
|
|
191
|
+
};
|
|
192
|
+
try {
|
|
193
|
+
const result = await handler(interceptedRequest);
|
|
194
|
+
if (result) {
|
|
195
|
+
// Provide mock response
|
|
196
|
+
await this.provideResponse(requestId, result);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
// Continue with original request
|
|
200
|
+
await this.continueRequest(requestId);
|
|
201
|
+
}
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
console.error('Error in network intercept handler:', err);
|
|
206
|
+
await this.continueRequest(requestId);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// No handler found, continue request
|
|
211
|
+
await this.continueRequest(requestId);
|
|
212
|
+
}
|
|
213
|
+
normalizePatterns(patterns) {
|
|
214
|
+
// Handle single UrlPattern object
|
|
215
|
+
if (typeof patterns === 'object' && !Array.isArray(patterns) && 'type' in patterns) {
|
|
216
|
+
return [patterns];
|
|
217
|
+
}
|
|
218
|
+
const arr = Array.isArray(patterns) ? patterns : [patterns];
|
|
219
|
+
return arr.map((p) => {
|
|
220
|
+
if (typeof p === 'string') {
|
|
221
|
+
// BiDi URL patterns don't support wildcards - they use exact component matching
|
|
222
|
+
// Extract pathname from glob-style patterns for simple prefix matching
|
|
223
|
+
if (p.includes('**') || p.includes('*')) {
|
|
224
|
+
// Extract pathname from glob pattern
|
|
225
|
+
// e.g., "**/api/users" -> pathname: "/api/users"
|
|
226
|
+
// Note: BiDi will only match exact pathnames, not prefixes
|
|
227
|
+
let pathname = p;
|
|
228
|
+
// Remove leading **
|
|
229
|
+
pathname = pathname.replace(/^\*\*/, '');
|
|
230
|
+
// Remove trailing wildcards (can't do prefix matching in BiDi)
|
|
231
|
+
pathname = pathname.replace(/\/?\*\*$/, '');
|
|
232
|
+
pathname = pathname.replace(/\/?\*$/, '');
|
|
233
|
+
// Remove any remaining wildcards
|
|
234
|
+
pathname = pathname.replace(/\*/g, '');
|
|
235
|
+
if (!pathname.startsWith('/')) {
|
|
236
|
+
pathname = '/' + pathname;
|
|
237
|
+
}
|
|
238
|
+
// Clean up double slashes
|
|
239
|
+
pathname = pathname.replace(/\/+/g, '/');
|
|
240
|
+
return {
|
|
241
|
+
type: 'pattern',
|
|
242
|
+
pathname,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
// For full URLs, use UrlPatternString
|
|
246
|
+
return { type: 'string', pattern: p };
|
|
247
|
+
}
|
|
248
|
+
return p;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
headersToObject(headers) {
|
|
252
|
+
const result = {};
|
|
253
|
+
for (const h of headers) {
|
|
254
|
+
result[h.name] = h.value.value;
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../../src/lib/bidi/network.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session State Manager
|
|
3
|
+
* Playwright-style session persistence - save login state, cookies, localStorage
|
|
4
|
+
*/
|
|
5
|
+
import type { BiDiConnection } from './connection.js';
|
|
6
|
+
import type { Driver } from '../driver.js';
|
|
7
|
+
import type { BrowsingContext, NetworkCookie, SessionState, PartialCookie } from './types.js';
|
|
8
|
+
export interface StorageStateOptions {
|
|
9
|
+
/** Include cookies in saved state (default: true) */
|
|
10
|
+
includeCookies?: boolean;
|
|
11
|
+
/** Include localStorage in saved state (default: true) */
|
|
12
|
+
includeLocalStorage?: boolean;
|
|
13
|
+
/** Include sessionStorage in saved state (default: false) */
|
|
14
|
+
includeSessionStorage?: boolean;
|
|
15
|
+
/** Specific origins to capture (default: all) */
|
|
16
|
+
origins?: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare class SessionStateManager {
|
|
19
|
+
private connection;
|
|
20
|
+
private driver;
|
|
21
|
+
private context?;
|
|
22
|
+
constructor(driver: Driver, connection: BiDiConnection | null, context?: BrowsingContext);
|
|
23
|
+
/**
|
|
24
|
+
* Save current session state to a file (Playwright-style)
|
|
25
|
+
* Captures cookies and optionally localStorage/sessionStorage
|
|
26
|
+
*/
|
|
27
|
+
saveState(path: string, options?: StorageStateOptions): Promise<SessionState>;
|
|
28
|
+
/**
|
|
29
|
+
* Load session state from a file
|
|
30
|
+
*/
|
|
31
|
+
loadState(path: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Get current session state
|
|
34
|
+
*/
|
|
35
|
+
getState(options?: StorageStateOptions): Promise<SessionState>;
|
|
36
|
+
/**
|
|
37
|
+
* Set session state (cookies + storage)
|
|
38
|
+
*/
|
|
39
|
+
setState(state: SessionState): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Get all cookies using BiDi or fallback to Classic
|
|
42
|
+
*/
|
|
43
|
+
getCookies(filter?: {
|
|
44
|
+
domain?: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
}): Promise<NetworkCookie[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Set cookies using BiDi or fallback to Classic
|
|
49
|
+
*/
|
|
50
|
+
setCookies(cookies: NetworkCookie[] | PartialCookie[]): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Clear all cookies
|
|
53
|
+
*/
|
|
54
|
+
clearCookies(filter?: {
|
|
55
|
+
domain?: string;
|
|
56
|
+
name?: string;
|
|
57
|
+
}): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Add a single cookie
|
|
60
|
+
*/
|
|
61
|
+
addCookie(cookie: {
|
|
62
|
+
name: string;
|
|
63
|
+
value: string;
|
|
64
|
+
domain?: string;
|
|
65
|
+
path?: string;
|
|
66
|
+
secure?: boolean;
|
|
67
|
+
httpOnly?: boolean;
|
|
68
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
69
|
+
expiry?: number | Date;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
private getCookiesBiDi;
|
|
72
|
+
private getCookiesClassic;
|
|
73
|
+
private setCookiesBiDi;
|
|
74
|
+
private setCookiesClassic;
|
|
75
|
+
private getLocalStorage;
|
|
76
|
+
private getSessionStorage;
|
|
77
|
+
private setLocalStorage;
|
|
78
|
+
private setSessionStorage;
|
|
79
|
+
private getCurrentDomain;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/lib/bidi/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,YAAY,EACZ,aAAa,EAEd,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,0DAA0D;IAC1D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,6DAA6D;IAC7D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAC,CAAkB;gBAEtB,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,eAAe;IAMxF;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IAMvF;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5C;;OAEG;IACG,QAAQ,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC;IA6BxE;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBlD;;OAEG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAOvF;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3E;;OAEG;IACG,YAAY,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9E;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;QACrC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,GAAG,OAAO,CAAC,IAAI,CAAC;YAsBH,cAAc;YAgBd,iBAAiB;YAyCjB,cAAc;YAkCd,iBAAiB;YAmBjB,eAAe;YAuBf,iBAAiB;YAuBjB,eAAe;YAef,iBAAiB;YAcjB,gBAAgB;CAG/B"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session State Manager
|
|
3
|
+
* Playwright-style session persistence - save login state, cookies, localStorage
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs/promises';
|
|
6
|
+
export class SessionStateManager {
|
|
7
|
+
connection;
|
|
8
|
+
driver;
|
|
9
|
+
context;
|
|
10
|
+
constructor(driver, connection, context) {
|
|
11
|
+
this.driver = driver;
|
|
12
|
+
this.connection = connection;
|
|
13
|
+
this.context = context;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Save current session state to a file (Playwright-style)
|
|
17
|
+
* Captures cookies and optionally localStorage/sessionStorage
|
|
18
|
+
*/
|
|
19
|
+
async saveState(path, options = {}) {
|
|
20
|
+
const state = await this.getState(options);
|
|
21
|
+
await fs.writeFile(path, JSON.stringify(state, null, 2), 'utf-8');
|
|
22
|
+
return state;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load session state from a file
|
|
26
|
+
*/
|
|
27
|
+
async loadState(path) {
|
|
28
|
+
const data = await fs.readFile(path, 'utf-8');
|
|
29
|
+
const state = JSON.parse(data);
|
|
30
|
+
await this.setState(state);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get current session state
|
|
34
|
+
*/
|
|
35
|
+
async getState(options = {}) {
|
|
36
|
+
const state = {};
|
|
37
|
+
// Get cookies if requested (default: true)
|
|
38
|
+
if (options.includeCookies !== false) {
|
|
39
|
+
state.cookies = await this.getCookies();
|
|
40
|
+
}
|
|
41
|
+
// Get localStorage if requested (default: true)
|
|
42
|
+
if (options.includeLocalStorage !== false) {
|
|
43
|
+
try {
|
|
44
|
+
state.localStorage = await this.getLocalStorage(options.origins);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// localStorage might not be available
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Get sessionStorage if requested (default: false)
|
|
51
|
+
if (options.includeSessionStorage) {
|
|
52
|
+
try {
|
|
53
|
+
state.sessionStorage = await this.getSessionStorage(options.origins);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// sessionStorage might not be available
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return state;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Set session state (cookies + storage)
|
|
63
|
+
*/
|
|
64
|
+
async setState(state) {
|
|
65
|
+
// Set cookies
|
|
66
|
+
if (state.cookies?.length) {
|
|
67
|
+
await this.setCookies(state.cookies);
|
|
68
|
+
}
|
|
69
|
+
// Set localStorage
|
|
70
|
+
if (state.localStorage) {
|
|
71
|
+
await this.setLocalStorage(state.localStorage);
|
|
72
|
+
}
|
|
73
|
+
// Set sessionStorage
|
|
74
|
+
if (state.sessionStorage) {
|
|
75
|
+
await this.setSessionStorage(state.sessionStorage);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get all cookies using BiDi or fallback to Classic
|
|
80
|
+
*/
|
|
81
|
+
async getCookies(filter) {
|
|
82
|
+
if (this.connection?.isConnected()) {
|
|
83
|
+
return this.getCookiesBiDi(filter);
|
|
84
|
+
}
|
|
85
|
+
return this.getCookiesClassic();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Set cookies using BiDi or fallback to Classic
|
|
89
|
+
*/
|
|
90
|
+
async setCookies(cookies) {
|
|
91
|
+
if (this.connection?.isConnected()) {
|
|
92
|
+
await this.setCookiesBiDi(cookies);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
await this.setCookiesClassic(cookies);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Clear all cookies
|
|
100
|
+
*/
|
|
101
|
+
async clearCookies(filter) {
|
|
102
|
+
if (this.connection?.isConnected()) {
|
|
103
|
+
await this.connection.send('storage.deleteCookies', {
|
|
104
|
+
filter: filter || {},
|
|
105
|
+
...(this.context ? { partition: { type: 'context', context: this.context } } : {}),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Classic WebDriver - delete all cookies
|
|
110
|
+
const cookies = await this.getCookiesClassic();
|
|
111
|
+
for (const cookie of cookies) {
|
|
112
|
+
if (filter?.domain && cookie.domain !== filter.domain)
|
|
113
|
+
continue;
|
|
114
|
+
if (filter?.name && cookie.name !== filter.name)
|
|
115
|
+
continue;
|
|
116
|
+
await this.driver.executeScript(`document.cookie = "${cookie.name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${cookie.domain}"`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Add a single cookie
|
|
122
|
+
*/
|
|
123
|
+
async addCookie(cookie) {
|
|
124
|
+
const expiry = cookie.expiry instanceof Date
|
|
125
|
+
? Math.floor(cookie.expiry.getTime() / 1000)
|
|
126
|
+
: cookie.expiry;
|
|
127
|
+
const partialCookie = {
|
|
128
|
+
name: cookie.name,
|
|
129
|
+
value: { type: 'string', value: cookie.value },
|
|
130
|
+
domain: cookie.domain || (await this.getCurrentDomain()),
|
|
131
|
+
path: cookie.path,
|
|
132
|
+
secure: cookie.secure,
|
|
133
|
+
httpOnly: cookie.httpOnly,
|
|
134
|
+
sameSite: cookie.sameSite?.toLowerCase(),
|
|
135
|
+
expiry,
|
|
136
|
+
};
|
|
137
|
+
await this.setCookies([partialCookie]);
|
|
138
|
+
}
|
|
139
|
+
// === Private Methods ===
|
|
140
|
+
async getCookiesBiDi(filter) {
|
|
141
|
+
const params = {};
|
|
142
|
+
if (filter) {
|
|
143
|
+
params.filter = filter;
|
|
144
|
+
}
|
|
145
|
+
if (this.context) {
|
|
146
|
+
params.partition = { type: 'context', context: this.context };
|
|
147
|
+
}
|
|
148
|
+
const result = await this.connection.send('storage.getCookies', params);
|
|
149
|
+
return result.cookies;
|
|
150
|
+
}
|
|
151
|
+
async getCookiesClassic() {
|
|
152
|
+
const cookies = await this.driver.executeScript(`
|
|
153
|
+
return document.cookie.split(';').map(c => {
|
|
154
|
+
const [name, ...valueParts] = c.trim().split('=');
|
|
155
|
+
return {
|
|
156
|
+
name: name,
|
|
157
|
+
value: valueParts.join('='),
|
|
158
|
+
domain: location.hostname,
|
|
159
|
+
path: '/',
|
|
160
|
+
httpOnly: false,
|
|
161
|
+
secure: location.protocol === 'https:',
|
|
162
|
+
size: c.length,
|
|
163
|
+
sameSite: 'lax'
|
|
164
|
+
};
|
|
165
|
+
}).filter(c => c.name);
|
|
166
|
+
`);
|
|
167
|
+
return (cookies || []).map((c) => ({
|
|
168
|
+
name: c.name,
|
|
169
|
+
value: { type: 'string', value: c.value },
|
|
170
|
+
domain: c.domain,
|
|
171
|
+
path: c.path || '/',
|
|
172
|
+
size: (c.name + c.value).length,
|
|
173
|
+
httpOnly: c.httpOnly ?? false,
|
|
174
|
+
secure: c.secure ?? false,
|
|
175
|
+
sameSite: c.sameSite?.toLowerCase() || 'lax',
|
|
176
|
+
expiry: c.expiry,
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
async setCookiesBiDi(cookies) {
|
|
180
|
+
for (const cookie of cookies) {
|
|
181
|
+
// Both NetworkCookie and PartialCookie now have value as BytesValue
|
|
182
|
+
// Note: sameSite: 'none' requires secure: true, so adjust if needed
|
|
183
|
+
let sameSite = cookie.sameSite;
|
|
184
|
+
let secure = cookie.secure;
|
|
185
|
+
if (sameSite === 'none' && !secure) {
|
|
186
|
+
// Invalid combo - either set secure to true or change sameSite
|
|
187
|
+
sameSite = 'lax'; // Default to lax for non-secure cookies
|
|
188
|
+
}
|
|
189
|
+
const partialCookie = {
|
|
190
|
+
name: cookie.name,
|
|
191
|
+
value: cookie.value,
|
|
192
|
+
domain: cookie.domain,
|
|
193
|
+
path: cookie.path,
|
|
194
|
+
httpOnly: cookie.httpOnly,
|
|
195
|
+
secure: secure,
|
|
196
|
+
sameSite: sameSite,
|
|
197
|
+
expiry: cookie.expiry,
|
|
198
|
+
};
|
|
199
|
+
try {
|
|
200
|
+
await this.connection.send('storage.setCookie', {
|
|
201
|
+
cookie: partialCookie,
|
|
202
|
+
...(this.context ? { partition: { type: 'context', context: this.context } } : {}),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
// Propagate errors - cookie might be rejected for security reasons
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async setCookiesClassic(cookies) {
|
|
212
|
+
for (const cookie of cookies) {
|
|
213
|
+
// Extract string value from BytesValue
|
|
214
|
+
const value = cookie.value.value;
|
|
215
|
+
let cookieStr = `${cookie.name}=${encodeURIComponent(value)}`;
|
|
216
|
+
if (cookie.path)
|
|
217
|
+
cookieStr += `; path=${cookie.path}`;
|
|
218
|
+
if (cookie.domain)
|
|
219
|
+
cookieStr += `; domain=${cookie.domain}`;
|
|
220
|
+
if (cookie.secure)
|
|
221
|
+
cookieStr += '; secure';
|
|
222
|
+
if (cookie.sameSite)
|
|
223
|
+
cookieStr += `; samesite=${cookie.sameSite}`;
|
|
224
|
+
if (cookie.expiry) {
|
|
225
|
+
const date = new Date(cookie.expiry * 1000);
|
|
226
|
+
cookieStr += `; expires=${date.toUTCString()}`;
|
|
227
|
+
}
|
|
228
|
+
await this.driver.executeScript(`document.cookie = ${JSON.stringify(cookieStr)}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async getLocalStorage(origins) {
|
|
232
|
+
const result = {};
|
|
233
|
+
const currentOrigin = await this.driver.executeScript('return location.origin');
|
|
234
|
+
if (!origins || origins.includes(currentOrigin)) {
|
|
235
|
+
const storage = await this.driver.executeScript(`
|
|
236
|
+
const result = {};
|
|
237
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
238
|
+
const key = localStorage.key(i);
|
|
239
|
+
result[key] = localStorage.getItem(key);
|
|
240
|
+
}
|
|
241
|
+
return result;
|
|
242
|
+
`);
|
|
243
|
+
if (storage && Object.keys(storage).length > 0) {
|
|
244
|
+
result[currentOrigin] = storage;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
async getSessionStorage(origins) {
|
|
250
|
+
const result = {};
|
|
251
|
+
const currentOrigin = await this.driver.executeScript('return location.origin');
|
|
252
|
+
if (!origins || origins.includes(currentOrigin)) {
|
|
253
|
+
const storage = await this.driver.executeScript(`
|
|
254
|
+
const result = {};
|
|
255
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
256
|
+
const key = sessionStorage.key(i);
|
|
257
|
+
result[key] = sessionStorage.getItem(key);
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
`);
|
|
261
|
+
if (storage && Object.keys(storage).length > 0) {
|
|
262
|
+
result[currentOrigin] = storage;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
async setLocalStorage(storage) {
|
|
268
|
+
const currentOrigin = await this.driver.executeScript('return location.origin');
|
|
269
|
+
for (const [origin, data] of Object.entries(storage)) {
|
|
270
|
+
if (origin === currentOrigin) {
|
|
271
|
+
for (const [key, value] of Object.entries(data)) {
|
|
272
|
+
await this.driver.executeScript(`localStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)})`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// For other origins, we'd need to navigate there first - complex case
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
async setSessionStorage(storage) {
|
|
279
|
+
const currentOrigin = await this.driver.executeScript('return location.origin');
|
|
280
|
+
for (const [origin, data] of Object.entries(storage)) {
|
|
281
|
+
if (origin === currentOrigin) {
|
|
282
|
+
for (const [key, value] of Object.entries(data)) {
|
|
283
|
+
await this.driver.executeScript(`sessionStorage.setItem(${JSON.stringify(key)}, ${JSON.stringify(value)})`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async getCurrentDomain() {
|
|
289
|
+
return this.driver.executeScript('return location.hostname');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/lib/bidi/storage.ts"],"names":[],"mappings":"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"}
|