@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 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 = (logger11, name) => {
264
- if (logger11 && typeof logger11[name] === "function") {
265
- return logger11[name].bind(logger11);
263
+ var resolveLogMethod = (logger12, name) => {
264
+ if (logger12 && typeof logger12[name] === "function") {
265
+ return logger12[name].bind(logger12);
266
266
  }
267
- if (name === "warning" && logger11 && typeof logger11.warn === "function") {
268
- return logger11.warn.bind(logger11);
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 = (logger11) => {
274
- defaultLogger = logger11;
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 logger11 = resolveLogger(explicitLogger);
302
- const logFn = resolveLogMethod(logger11, methodName);
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: (logger11) => setDefaultLogger(logger11),
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: (logger11) => {
3104
- if (logger11) return createTemplateLogger(createBaseLogger("", logger11));
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 DEFAULT_TIMEOUT_MS = 30 * 1e3;
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: context.mutationCount || 0,
3259
+ mutationCount,
3233
3260
  html,
3234
3261
  text,
3235
- mutationNodes: Array.isArray(context.mutationNodes) ? context.mutationNodes : []
3262
+ mutationNodes
3236
3263
  });
3237
3264
  }
3238
3265
  }
3239
3266
  });
3240
3267
  return {
3241
3268
  stop: async () => {
3242
- return await monitor.stop();
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=30000]
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) return;
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
  }