@skrillex1224/playwright-toolkit 2.1.120 → 2.1.121
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/dist/index.cjs +118 -25
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +118 -25
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -260,18 +260,18 @@ var fallbackLog = {
|
|
|
260
260
|
error: (...args) => console.error(...args),
|
|
261
261
|
debug: (...args) => console.debug ? console.debug(...args) : console.log(...args)
|
|
262
262
|
};
|
|
263
|
-
var resolveLogMethod = (
|
|
264
|
-
if (
|
|
265
|
-
return
|
|
263
|
+
var resolveLogMethod = (logger12, name) => {
|
|
264
|
+
if (logger12 && typeof logger12[name] === "function") {
|
|
265
|
+
return logger12[name].bind(logger12);
|
|
266
266
|
}
|
|
267
|
-
if (name === "warning" &&
|
|
268
|
-
return
|
|
267
|
+
if (name === "warning" && logger12 && typeof logger12.warn === "function") {
|
|
268
|
+
return logger12.warn.bind(logger12);
|
|
269
269
|
}
|
|
270
270
|
return fallbackLog[name];
|
|
271
271
|
};
|
|
272
272
|
var defaultLogger = null;
|
|
273
|
-
var setDefaultLogger = (
|
|
274
|
-
defaultLogger =
|
|
273
|
+
var setDefaultLogger = (logger12) => {
|
|
274
|
+
defaultLogger = logger12;
|
|
275
275
|
};
|
|
276
276
|
var resolveLogger = (explicitLogger) => {
|
|
277
277
|
if (explicitLogger && typeof explicitLogger.info === "function") {
|
|
@@ -298,8 +298,8 @@ var colorize = (text, color) => {
|
|
|
298
298
|
var createBaseLogger = (prefix = "", explicitLogger) => {
|
|
299
299
|
const name = prefix ? String(prefix) : "";
|
|
300
300
|
const dispatch = (methodName, icon, message, color) => {
|
|
301
|
-
const
|
|
302
|
-
const logFn = resolveLogMethod(
|
|
301
|
+
const logger12 = resolveLogger(explicitLogger);
|
|
302
|
+
const logFn = resolveLogMethod(logger12, methodName);
|
|
303
303
|
const timestamp = colorize(`[${formatTimestamp()}]`, ANSI.gray);
|
|
304
304
|
const line = formatLine(name, icon, message);
|
|
305
305
|
const coloredLine = colorize(line, color);
|
|
@@ -3092,7 +3092,7 @@ var createTemplateLogger = (baseLogger = createBaseLogger()) => {
|
|
|
3092
3092
|
};
|
|
3093
3093
|
var getDefaultBaseLogger = () => createBaseLogger("");
|
|
3094
3094
|
var Logger = {
|
|
3095
|
-
setLogger: (
|
|
3095
|
+
setLogger: (logger12) => setDefaultLogger(logger12),
|
|
3096
3096
|
info: (message) => getDefaultBaseLogger().info(message),
|
|
3097
3097
|
success: (message) => getDefaultBaseLogger().success(message),
|
|
3098
3098
|
warning: (message) => getDefaultBaseLogger().warning(message),
|
|
@@ -3100,18 +3100,36 @@ var Logger = {
|
|
|
3100
3100
|
error: (message) => getDefaultBaseLogger().error(message),
|
|
3101
3101
|
debug: (message) => getDefaultBaseLogger().debug(message),
|
|
3102
3102
|
start: (message) => getDefaultBaseLogger().start(message),
|
|
3103
|
-
useTemplate: (
|
|
3104
|
-
if (
|
|
3103
|
+
useTemplate: (logger12) => {
|
|
3104
|
+
if (logger12) return createTemplateLogger(createBaseLogger("", logger12));
|
|
3105
3105
|
return createTemplateLogger();
|
|
3106
3106
|
}
|
|
3107
3107
|
};
|
|
3108
3108
|
|
|
3109
3109
|
// src/share.js
|
|
3110
3110
|
var import_delay3 = __toESM(require("delay"), 1);
|
|
3111
|
-
var
|
|
3111
|
+
var logger11 = createInternalLogger("Share");
|
|
3112
|
+
var DEFAULT_TIMEOUT_MS = 50 * 1e3;
|
|
3112
3113
|
var DEFAULT_PAYLOAD_SNAPSHOT_MAX_LEN = 500;
|
|
3113
3114
|
var DEFAULT_POLL_INTERVAL_MS = 120;
|
|
3114
3115
|
var normalizePrefix = (value) => String(value || "").trim();
|
|
3116
|
+
var toSnapshot = (value, maxLen) => {
|
|
3117
|
+
const text = String(value || "");
|
|
3118
|
+
if (!text) return "";
|
|
3119
|
+
return text.replace(/\s+/g, " ").trim().slice(0, maxLen);
|
|
3120
|
+
};
|
|
3121
|
+
var toInline = (value, maxLen = 200) => {
|
|
3122
|
+
const text = String(value || "");
|
|
3123
|
+
if (!text) return "";
|
|
3124
|
+
return text.replace(/\s+/g, " ").trim().slice(0, maxLen);
|
|
3125
|
+
};
|
|
3126
|
+
var toJsonInline = (value, maxLen = 260) => {
|
|
3127
|
+
try {
|
|
3128
|
+
return toInline(JSON.stringify(value), maxLen);
|
|
3129
|
+
} catch {
|
|
3130
|
+
return "[\u4E0D\u53EF\u5E8F\u5217\u5316]";
|
|
3131
|
+
}
|
|
3132
|
+
};
|
|
3115
3133
|
var normalizeXurl = (value) => {
|
|
3116
3134
|
if (!Array.isArray(value)) return [];
|
|
3117
3135
|
const normalizeMatcherList = (input) => {
|
|
@@ -3167,11 +3185,6 @@ var normalizeShare = (share) => {
|
|
|
3167
3185
|
xurl: normalizeXurl(source.xurl)
|
|
3168
3186
|
};
|
|
3169
3187
|
};
|
|
3170
|
-
var toSnapshot = (value, maxLen) => {
|
|
3171
|
-
const text = String(value || "");
|
|
3172
|
-
if (!text) return "";
|
|
3173
|
-
return text.replace(/\s+/g, " ").trim().slice(0, maxLen);
|
|
3174
|
-
};
|
|
3175
3188
|
var getByPathSegments = (source, pathSegments) => {
|
|
3176
3189
|
if (!Array.isArray(pathSegments) || pathSegments.length === 0) return void 0;
|
|
3177
3190
|
let current = source;
|
|
@@ -3213,33 +3226,49 @@ var createDomShareMonitor = async (page, options = {}) => {
|
|
|
3213
3226
|
const selectors = options.selectors ?? "html";
|
|
3214
3227
|
const mode = options.mode ?? Mutation.Mode.All;
|
|
3215
3228
|
const onMatch = typeof options.onMatch === "function" ? options.onMatch : null;
|
|
3229
|
+
const onTelemetry = typeof options.onTelemetry === "function" ? options.onTelemetry : null;
|
|
3216
3230
|
let matched = false;
|
|
3231
|
+
logger11.info(`DOM \u76D1\u542C\u51C6\u5907\u6302\u8F7D: selectors=${toJsonInline(selectors, 120)}, mode=${mode}`);
|
|
3217
3232
|
const monitor = await Mutation.useMonitor(page, selectors, {
|
|
3218
3233
|
mode,
|
|
3219
3234
|
onMutation: (context = {}) => {
|
|
3220
3235
|
if (matched) return;
|
|
3236
|
+
const mutationCount = Number(context.mutationCount || 0);
|
|
3237
|
+
const mutationNodes = Array.isArray(context.mutationNodes) ? context.mutationNodes : [];
|
|
3221
3238
|
const html = String(context.html || "");
|
|
3222
3239
|
const text = String(context.text || "");
|
|
3223
3240
|
const rawDom = `${html}
|
|
3224
3241
|
${text}`;
|
|
3242
|
+
if (onTelemetry) {
|
|
3243
|
+
onTelemetry({
|
|
3244
|
+
mutationCount,
|
|
3245
|
+
mutationNodesCount: mutationNodes.length
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
if (mutationCount <= 5 || mutationCount % 50 === 0) {
|
|
3249
|
+
logger11.info(`DOM \u53D8\u5316\u5DF2\u6355\u83B7: mutationCount=${mutationCount}, mutationNodes=${mutationNodes.length}`);
|
|
3250
|
+
}
|
|
3225
3251
|
const [candidate] = Utils.parseLinks(rawDom, { prefix }) || [];
|
|
3226
3252
|
if (!candidate) return;
|
|
3227
3253
|
matched = true;
|
|
3254
|
+
logger11.success("captureLink.domHit", `DOM \u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: mutationCount=${mutationCount}, link=${candidate}`);
|
|
3228
3255
|
if (onMatch) {
|
|
3229
3256
|
onMatch({
|
|
3230
3257
|
link: candidate,
|
|
3231
3258
|
rawDom,
|
|
3232
|
-
mutationCount
|
|
3259
|
+
mutationCount,
|
|
3233
3260
|
html,
|
|
3234
3261
|
text,
|
|
3235
|
-
mutationNodes
|
|
3262
|
+
mutationNodes
|
|
3236
3263
|
});
|
|
3237
3264
|
}
|
|
3238
3265
|
}
|
|
3239
3266
|
});
|
|
3240
3267
|
return {
|
|
3241
3268
|
stop: async () => {
|
|
3242
|
-
|
|
3269
|
+
const result = await monitor.stop();
|
|
3270
|
+
logger11.info(`DOM \u76D1\u542C\u5DF2\u505C\u6B62: totalMutations=${result?.totalMutations || 0}`);
|
|
3271
|
+
return result;
|
|
3243
3272
|
}
|
|
3244
3273
|
};
|
|
3245
3274
|
};
|
|
@@ -3252,7 +3281,7 @@ var Share = {
|
|
|
3252
3281
|
* @param {import('playwright').Page} page
|
|
3253
3282
|
* @param {Object} [options]
|
|
3254
3283
|
* @param {{ mode?: 'dom' | 'response', prefix: string, xurl?: Array<string | string[]> }} options.share
|
|
3255
|
-
* @param {number} [options.timeoutMs=
|
|
3284
|
+
* @param {number} [options.timeoutMs=50000]
|
|
3256
3285
|
* @param {number} [options.payloadSnapshotMaxLen=500]
|
|
3257
3286
|
* @param {string | string[]} [options.domSelectors='html']
|
|
3258
3287
|
* @param {'added' | 'changed' | 'all'} [options.domMode='all']
|
|
@@ -3278,6 +3307,18 @@ var Share = {
|
|
|
3278
3307
|
if (share.mode === "response" && apiMatchers.length === 0) {
|
|
3279
3308
|
throw new Error("Share.captureLink requires share.xurl[0] api matcher when mode=response");
|
|
3280
3309
|
}
|
|
3310
|
+
logger11.start("captureLink", `mode=${share.mode}, timeoutMs=${timeoutMs}, prefix=${share.prefix}`);
|
|
3311
|
+
logger11.info(`captureLink \u914D\u7F6E: xurl=${toJsonInline(share.xurl)}, domMode=${domMode}, domSelectors=${toJsonInline(domSelectors, 120)}`);
|
|
3312
|
+
const stats = {
|
|
3313
|
+
actionTimedOut: false,
|
|
3314
|
+
domMutationCount: 0,
|
|
3315
|
+
domMutationNodes: 0,
|
|
3316
|
+
responseObserved: 0,
|
|
3317
|
+
responseMatched: 0,
|
|
3318
|
+
responseResolved: 0,
|
|
3319
|
+
lastMatchedUrl: "",
|
|
3320
|
+
responseSampleUrls: []
|
|
3321
|
+
};
|
|
3281
3322
|
const candidates = {
|
|
3282
3323
|
dom: null,
|
|
3283
3324
|
response: null
|
|
@@ -3292,6 +3333,7 @@ var Share = {
|
|
|
3292
3333
|
link: validated,
|
|
3293
3334
|
payloadText: String(payloadText || "")
|
|
3294
3335
|
};
|
|
3336
|
+
logger11.info(`\u5019\u9009\u94FE\u63A5\u5DF2\u786E\u8BA4: source=${source}, link=${validated}`);
|
|
3295
3337
|
return true;
|
|
3296
3338
|
};
|
|
3297
3339
|
const resolveResponseCandidate = (responseText) => {
|
|
@@ -3325,39 +3367,65 @@ var Share = {
|
|
|
3325
3367
|
domMonitor = null;
|
|
3326
3368
|
try {
|
|
3327
3369
|
await monitor.stop();
|
|
3328
|
-
} catch {
|
|
3370
|
+
} catch (error) {
|
|
3371
|
+
logger11.warning(`\u505C\u6B62 DOM \u76D1\u542C\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`);
|
|
3329
3372
|
}
|
|
3330
3373
|
};
|
|
3331
3374
|
const onResponse = async (response) => {
|
|
3332
3375
|
if (share.mode !== "response") return;
|
|
3333
3376
|
if (candidates.response?.link) return;
|
|
3377
|
+
stats.responseObserved += 1;
|
|
3334
3378
|
try {
|
|
3335
3379
|
const url = String(response.url() || "");
|
|
3380
|
+
if (url && stats.responseSampleUrls.length < 8 && !stats.responseSampleUrls.includes(url)) {
|
|
3381
|
+
stats.responseSampleUrls.push(url);
|
|
3382
|
+
}
|
|
3383
|
+
if (stats.responseObserved <= 5) {
|
|
3384
|
+
logger11.info(`\u63A5\u53E3\u54CD\u5E94\u91C7\u6837(${stats.responseObserved}): ${url}`);
|
|
3385
|
+
}
|
|
3336
3386
|
if (!apiMatchers.some((matcher) => url.includes(matcher))) return;
|
|
3387
|
+
stats.responseMatched += 1;
|
|
3388
|
+
stats.lastMatchedUrl = url;
|
|
3389
|
+
logger11.info(`\u63A5\u53E3\u547D\u4E2D\u5339\u914D(${stats.responseMatched}): ${url}`);
|
|
3337
3390
|
const text = await response.text();
|
|
3338
3391
|
const hit = resolveResponseCandidate(text);
|
|
3339
|
-
if (!hit?.link)
|
|
3392
|
+
if (!hit?.link) {
|
|
3393
|
+
if (stats.responseMatched <= 3) {
|
|
3394
|
+
logger11.info(`\u63A5\u53E3\u89E3\u6790\u5B8C\u6210\u4F46\u672A\u63D0\u53D6\u5230\u5206\u4EAB\u94FE\u63A5: payloadSize=${text.length}`);
|
|
3395
|
+
}
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3398
|
+
stats.responseResolved += 1;
|
|
3399
|
+
logger11.success("captureLink.responseHit", `\u63A5\u53E3\u547D\u4E2D\u5206\u4EAB\u94FE\u63A5: url=${url}, link=${hit.link}`);
|
|
3340
3400
|
setCandidate("response", hit.link, hit.payloadText);
|
|
3341
|
-
} catch {
|
|
3401
|
+
} catch (error) {
|
|
3402
|
+
logger11.warning(`\u63A5\u53E3\u54CD\u5E94\u5904\u7406\u5F02\u5E38: ${error instanceof Error ? error.message : String(error)}`);
|
|
3342
3403
|
}
|
|
3343
3404
|
};
|
|
3344
3405
|
if (share.mode === "dom") {
|
|
3406
|
+
logger11.info("\u5F53\u524D\u4E3A DOM \u6A21\u5F0F\uFF0C\u4EC5\u542F\u7528 DOM \u76D1\u542C");
|
|
3345
3407
|
domMonitor = await createDomShareMonitor(page, {
|
|
3346
3408
|
prefix: share.prefix,
|
|
3347
3409
|
selectors: domSelectors,
|
|
3348
3410
|
mode: domMode,
|
|
3411
|
+
onTelemetry: ({ mutationCount, mutationNodesCount }) => {
|
|
3412
|
+
stats.domMutationCount = mutationCount;
|
|
3413
|
+
stats.domMutationNodes = mutationNodesCount;
|
|
3414
|
+
},
|
|
3349
3415
|
onMatch: ({ link, rawDom }) => {
|
|
3350
3416
|
setCandidate("dom", link, rawDom);
|
|
3351
3417
|
}
|
|
3352
3418
|
});
|
|
3353
3419
|
}
|
|
3354
3420
|
if (share.mode === "response") {
|
|
3421
|
+
logger11.info(`\u5F53\u524D\u4E3A\u63A5\u53E3\u6A21\u5F0F\uFF0C\u6302\u8F7D response \u76D1\u542C: apiMatchers=${toJsonInline(apiMatchers, 160)}`);
|
|
3355
3422
|
page.on("response", onResponse);
|
|
3356
3423
|
}
|
|
3357
3424
|
const deadline = Date.now() + timeoutMs;
|
|
3358
3425
|
const getRemainingMs = () => Math.max(0, deadline - Date.now());
|
|
3359
3426
|
try {
|
|
3360
3427
|
const actionTimeout = getRemainingMs();
|
|
3428
|
+
logger11.start("captureLink.performActions", `\u6267\u884C\u52A8\u4F5C\u9884\u7B97=${actionTimeout}ms`);
|
|
3361
3429
|
if (actionTimeout > 0) {
|
|
3362
3430
|
let timer = null;
|
|
3363
3431
|
let actionError = null;
|
|
@@ -3371,12 +3439,21 @@ var Share = {
|
|
|
3371
3439
|
const actionResult = await Promise.race([actionPromise, timeoutPromise]);
|
|
3372
3440
|
if (timer) clearTimeout(timer);
|
|
3373
3441
|
if (actionResult === "__ACTION_ERROR__") {
|
|
3442
|
+
logger11.fail("captureLink.performActions", actionError);
|
|
3374
3443
|
throw actionError;
|
|
3375
3444
|
}
|
|
3445
|
+
if (actionResult === "__ACTION_TIMEOUT__") {
|
|
3446
|
+
stats.actionTimedOut = true;
|
|
3447
|
+
logger11.warning(`performActions \u5DF2\u8D85\u65F6 (${actionTimeout}ms)\uFF0C\u52A8\u4F5C\u53EF\u80FD\u4ECD\u5728\u5F02\u6B65\u6267\u884C`);
|
|
3448
|
+
} else {
|
|
3449
|
+
logger11.success("captureLink.performActions", "\u6267\u884C\u52A8\u4F5C\u5B8C\u6210");
|
|
3450
|
+
}
|
|
3376
3451
|
}
|
|
3452
|
+
let nextProgressLogTs = Date.now() + 3e3;
|
|
3377
3453
|
while (true) {
|
|
3378
3454
|
const selected = share.mode === "dom" ? candidates.dom : candidates.response;
|
|
3379
3455
|
if (selected?.link) {
|
|
3456
|
+
logger11.success("captureLink", `\u6355\u83B7\u6210\u529F: source=${share.mode}, link=${selected.link}`);
|
|
3380
3457
|
return {
|
|
3381
3458
|
link: selected.link,
|
|
3382
3459
|
payloadText: selected.payloadText,
|
|
@@ -3386,8 +3463,23 @@ var Share = {
|
|
|
3386
3463
|
}
|
|
3387
3464
|
const remaining = getRemainingMs();
|
|
3388
3465
|
if (remaining <= 0) break;
|
|
3466
|
+
const now = Date.now();
|
|
3467
|
+
if (now >= nextProgressLogTs) {
|
|
3468
|
+
logger11.info(
|
|
3469
|
+
`captureLink \u7B49\u5F85\u4E2D: remaining=${remaining}ms, domMutationCount=${stats.domMutationCount}, responseMatched=${stats.responseMatched}`
|
|
3470
|
+
);
|
|
3471
|
+
nextProgressLogTs = now + 5e3;
|
|
3472
|
+
}
|
|
3389
3473
|
await (0, import_delay3.default)(Math.max(0, Math.min(DEFAULT_POLL_INTERVAL_MS, remaining)));
|
|
3390
3474
|
}
|
|
3475
|
+
if (share.mode === "response" && stats.responseMatched === 0) {
|
|
3476
|
+
logger11.warning(
|
|
3477
|
+
`\u63A5\u53E3\u76D1\u542C\u672A\u547D\u4E2D: apiMatchers=${toJsonInline(apiMatchers, 220)}, \u54CD\u5E94\u6837\u672CURLs=${toJsonInline(stats.responseSampleUrls, 420)}`
|
|
3478
|
+
);
|
|
3479
|
+
}
|
|
3480
|
+
logger11.warning(
|
|
3481
|
+
`captureLink \u8D85\u65F6\u672A\u62FF\u5230\u94FE\u63A5: mode=${share.mode}, actionTimedOut=${stats.actionTimedOut}, domMutationCount=${stats.domMutationCount}, responseObserved=${stats.responseObserved}, responseMatched=${stats.responseMatched}, lastMatchedUrl=${stats.lastMatchedUrl || "none"}`
|
|
3482
|
+
);
|
|
3391
3483
|
return {
|
|
3392
3484
|
link: null,
|
|
3393
3485
|
payloadText: "",
|
|
@@ -3397,6 +3489,7 @@ var Share = {
|
|
|
3397
3489
|
} finally {
|
|
3398
3490
|
if (share.mode === "response") {
|
|
3399
3491
|
page.off("response", onResponse);
|
|
3492
|
+
logger11.info("response \u76D1\u542C\u5DF2\u5378\u8F7D");
|
|
3400
3493
|
}
|
|
3401
3494
|
await stopDomMonitor();
|
|
3402
3495
|
}
|