@ceki/n8n-nodes-ceki 0.2.8 → 0.2.9

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.
@@ -120,53 +120,17 @@ var CekiClient = class {
120
120
  this._sendRaw({ type: "resume", session_id: sessionId });
121
121
  return this._awaitResume(sessionId);
122
122
  }
123
- /** Close the WS connection — session stays alive in grace.
124
- * Waits for the close handshake so the relay processes the close
125
- * before a new connection with the same renterId is established
126
- * (avoids the close-handler race condition).
127
- */
128
- async disconnect() {
123
+ /** Close the WS connection — session stays alive in grace. */
124
+ disconnect() {
129
125
  this._closed = true;
130
126
  this._activeSessions.clear();
131
127
  this._pendingRents.clear();
132
128
  this._pendingResumes.clear();
133
- if (!this._ws) return;
134
- const ws = this._ws;
135
- if (ws.readyState === WebSocket.CLOSED) {
136
- this._ws = null;
137
- return;
138
- }
139
- if (ws.readyState === WebSocket.CLOSING) {
140
- await new Promise((r) => {
141
- ws.onclose = () => {
142
- this._connected = false;
143
- r();
144
- };
145
- });
146
- this._ws = null;
147
- return;
148
- }
149
- await new Promise((r) => {
150
- const t = setTimeout(() => {
151
- r();
152
- }, 5e3);
153
- ws.onclose = () => {
154
- this._connected = false;
155
- clearTimeout(t);
156
- r();
157
- };
158
- try {
159
- ws.close();
160
- } catch {
161
- clearTimeout(t);
162
- r();
163
- }
164
- });
165
- this._ws = null;
129
+ this._closeWs();
166
130
  }
167
131
  /** Close everything. */
168
- async close() {
169
- await this.disconnect();
132
+ close() {
133
+ this.disconnect();
170
134
  }
171
135
  // ── private ────────────────────────────────────────────────
172
136
  _awaitRent(key, scheduleId, timeoutMs) {
@@ -256,33 +220,13 @@ var CekiClient = class {
256
220
  _onMatch(msg) {
257
221
  const scheduleId = Number(msg.schedule_id ?? 0);
258
222
  const eventId = msg.event_id ? String(msg.event_id) : null;
259
- const sessionId = String(msg.session_id ?? "");
260
- if (sessionId && this._ws?.readyState === WebSocket.OPEN) {
261
- try {
262
- this._ws.send(JSON.stringify({ type: "match_ack", session_id: sessionId }));
263
- } catch {
264
- }
265
- }
266
223
  let pending = this._pendingRents.get(`event:${eventId}`);
267
224
  if (!pending) pending = this._pendingRents.get(`rent:${scheduleId}`);
268
225
  if (pending) {
269
226
  this._pendingRents.delete(`event:${eventId}`);
270
227
  this._pendingRents.delete(`rent:${scheduleId}`);
271
228
  pending.resolve({
272
- session_id: sessionId,
273
- schedule_id: scheduleId,
274
- event_id: eventId,
275
- chat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,
276
- provider_user_id: msg.provider_user_id != null ? Number(msg.provider_user_id) : null,
277
- browser_info: msg.browser_info ?? {}
278
- });
279
- return;
280
- }
281
- const resumePending = sessionId ? this._pendingResumes.get(sessionId) : null;
282
- if (resumePending) {
283
- this._pendingResumes.delete(sessionId);
284
- resumePending.resolve({
285
- session_id: sessionId,
229
+ session_id: String(msg.session_id ?? ""),
286
230
  schedule_id: scheduleId,
287
231
  event_id: eventId,
288
232
  chat_topic_id: msg.chat_topic_id ? String(msg.chat_topic_id) : null,
@@ -325,9 +269,9 @@ var CekiClient = class {
325
269
  const browser = this._activeSessions.get(sessionId);
326
270
  if (!browser) return;
327
271
  const id = Number(msg.id ?? 0);
328
- const pending = browser._pendingCdp.get(id);
272
+ const pending = this._pendingCdp.get(id);
329
273
  if (!pending) return;
330
- browser._pendingCdp.delete(id);
274
+ this._pendingCdp.delete(id);
331
275
  if (msg.error) {
332
276
  pending.reject(new Error(String(msg.error.message ?? "CDP error")));
333
277
  } else {
@@ -370,9 +314,9 @@ var CekiBrowser = class {
370
314
  async navigate(url, timeoutMs) {
371
315
  await this.send("Page.navigate", { url }, timeoutMs);
372
316
  }
373
- async click(x2, y2) {
374
- await this.send("Input.dispatchMouseEvent", { type: "mousePressed", x: x2, y: y2, button: "left", clickCount: 1 });
375
- await this.send("Input.dispatchMouseEvent", { type: "mouseReleased", x: x2, y: y2, button: "left", clickCount: 1 });
317
+ async click(x, y) {
318
+ await this.send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount: 1 });
319
+ await this.send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount: 1 });
376
320
  }
377
321
  async type(text) {
378
322
  await this.send("Ceki.typeText", { text });
@@ -447,7 +391,7 @@ var BrowserCeki = class {
447
391
  icon: "file:ceki.png",
448
392
  group: ["transform"],
449
393
  version: 1,
450
- subtitle: '={{ "Ceki: " + $parameter.operation }}',
394
+ subtitle: '={{ "Ceki: " + $operation }}',
451
395
  description: "Rent a real human browser and control it: rent, navigate, click, type, screenshot, solve captchas, and more",
452
396
  defaults: { name: "Browser Ceki" },
453
397
  inputs: ["main"],
@@ -490,7 +434,7 @@ var BrowserCeki = class {
490
434
  type: "string",
491
435
  default: "",
492
436
  placeholder: "RU, EE, US\u2026",
493
- displayOptions: { show: { operation: ["search"] } }
437
+ displayOptions: { show: { operation: ["rent", "search"] } }
494
438
  },
495
439
  {
496
440
  displayName: "Max $/min",
@@ -498,14 +442,14 @@ var BrowserCeki = class {
498
442
  type: "number",
499
443
  typeOptions: { numberPrecision: 4 },
500
444
  default: 0.02,
501
- displayOptions: { show: { operation: ["search"] } }
445
+ displayOptions: { show: { operation: ["rent", "search"] } }
502
446
  },
503
447
  {
504
448
  displayName: "Min rating",
505
449
  name: "minRating",
506
450
  type: "number",
507
451
  default: 0,
508
- displayOptions: { show: { operation: ["search"] } }
452
+ displayOptions: { show: { operation: ["rent"] } }
509
453
  },
510
454
  {
511
455
  displayName: "Profile mode",
@@ -666,39 +610,28 @@ var BrowserCeki = class {
666
610
  for (let i = 0; i < items.length; i++) {
667
611
  const op = this.getNodeParameter("operation", i);
668
612
  const client = new CekiClient(token);
613
+ await client.connect();
669
614
  let browser;
670
- let needFullClose = false;
671
615
  try {
672
- await client.connect();
673
616
  if (op === "rent") {
674
- try {
675
- const sid2 = await resolveSid(i, client);
676
- const mode = this.getNodeParameter("mode", i);
677
- browser = await client.rent(sid2, { mode });
678
- out.push({
679
- json: { session_id: browser.sessionId, schedule_id: sid2, mode }
680
- });
681
- } catch (e) {
682
- throw new Error(`Rent failed: ${e.message}`);
683
- } finally {
684
- await client.disconnect();
685
- }
617
+ const sid2 = await resolveSid(i, client);
618
+ const mode = this.getNodeParameter("mode", i);
619
+ browser = await client.rent(sid2, { mode });
620
+ out.push({
621
+ json: { session_id: browser.sessionId, schedule_id: sid2, mode }
622
+ });
623
+ await client.disconnect();
686
624
  continue;
687
625
  }
688
626
  if (op === "search") {
689
- try {
690
- const geo = this.getNodeParameter("geo", i);
691
- const maxPrice = this.getNodeParameter("maxPrice", i);
692
- const list = await client.search({
693
- geo: geo || void 0,
694
- max_price_per_min: maxPrice
695
- });
696
- out.push({ json: { browsers: list, count: list.length } });
697
- } catch (e) {
698
- throw new Error(`Search failed: ${e.message}`);
699
- } finally {
700
- await client.disconnect();
701
- }
627
+ const geo = this.getNodeParameter("geo", i);
628
+ const maxPrice = this.getNodeParameter("maxPrice", i);
629
+ const list = await client.search({
630
+ geo: geo || void 0,
631
+ max_price_per_min: maxPrice
632
+ });
633
+ out.push({ json: { browsers: list, count: list.length } });
634
+ await client.disconnect();
702
635
  continue;
703
636
  }
704
637
  if (op === "full") {
@@ -707,11 +640,7 @@ var BrowserCeki = class {
707
640
  if (demoMode) {
708
641
  sid2 = 99999;
709
642
  } else {
710
- try {
711
- sid2 = await resolveSid(i, client);
712
- } catch (e) {
713
- throw new Error(`Full: resolve schedule failed: ${e.message}`);
714
- }
643
+ sid2 = await resolveSid(i, client);
715
644
  }
716
645
  const mode = this.getNodeParameter("mode", i);
717
646
  const url = this.getNodeParameter("url", i);
@@ -724,18 +653,14 @@ var BrowserCeki = class {
724
653
  const demoPng = Buffer.from("iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAIAAAD9V4nPAAAnuElEQVR4nO3ceVxU9f748feZhU0RxRUTXEEWFXG3Rc3MJb3mUlrueivzVvebVre+38ql7d5bqZmZlZV4UUvLUtPUUtOKUAREBRVkEVQQxQ2UdWbO74+p+XGZAWlBqs/r+ddhOJ/lHHrw6sCIFhDQRQAAUJWhrjcAAEBdIoQAAKURQgCA0gghAEBphBAAoDRCCABQGiEEACiNEAIAlEYIAQBKI4QAAKURQgCA0gghAEBphBAAoDRCCABQGiEEACiNEAIAlEYIAQBKI4QAAKURQgCA0gghAEBphBAAoDRCCABQGiEEACiNEAIAlEYIAQBKI4QAAKURQgCA0gghAEBphBAAoDRCCABQGiEEACjNVKuzD1odeyXtiGiaybN+2rpl5+P31upydq3uGOs/eJyl5Jq1pOjoey+VXDjr8rSBkdG7p93i+LC+f/tGId1PfbXe8Yp987ouBpPp9K7PcvZsqvWtAwBuuNoNoc1SfmD+X0XEu3XHiKeX3IAQNu7St8Wtw/Y/P8VWVtok4tZOj7wY98KDNRl49VT61VPpFV9xbN7o7hnx9JvW0uK8mK9qZdMAgLpTuyF0KMxO1a1WERkYGX0udldB5vG8mK/CZi0wenhZS4qSl8/rueDD+JdmFp/P7f7sO9dyMo+v/LdvWI9Wg+69nJp40+2jRddT175RkJYcPOMZ94ZNNJM5NWrhlbSkihNmb1srIm3+MvXE2jdtZaUikn/w+2a9BmpGk8nDy3mgnZuPb4/n3zu85Omrp9IrPSM6WEuLU1cvDp7+9MXD+1xuIG//Tt/QHic3RzYMjmjYsWv2to+ytka5N2xS8QJLL+ffmFsNAPhZblAIfTv1Oh75qogYzObc6O0XDv3Q+e//PBu9LefbLS37jQiaPCc/MbpRSPeS/C/FoHm36SgijUK65yd+HzT5ie8fG+7u26zt6Ada9B2Svf2jKyeOeDTxi3h6ScxT4ypOaF+ovn/7wpPHHeseffcFEQmaPMd5oIgYTOYuj796PPLVSs+CzgqzUr1a+Lucx2B2O73z0/RP3um3bNv+Zyelfby010urs7ZGBU15ouIFHln6f7/9bQUA/Gq1G0KDydxz/gcGs1uD9p0uJu0/H79Xt9kuHt4nIr5hPZOXzxORszFfBU58PPmd+c173VGYlVqYedy7dUeTZ71GId1Pff2pb6denR596dSO9UlvPdtv+VdeLfztMxvdPTWDQbfZHBP+tKSLt/80Dr/ZeaCIhPz1/3K/23oxKfa6F6IZjTaLxfU8ul6QnqzbbDZLeUH6UV23Gd09nC/wF99DAECtukG/I6wfENjrhUgR0a1WXbeJiIhW8cyLyQcCJ/y9YVD4peMHrWWljUJ7GMxuZVcuJC17vlFI99bDJ/ndOkwzGuNf/putvFTTDA2DI+wxqzChiEhRbpZ3m45XThwREdG0Tn97MWnZcy4HGszm+gEdROTM7s+veyE+HTpfzT7h3TbYeR6bpfzHg/KyijupdIEAgN+nG/TPJ8oLLxflnar4ysXk2OZ97hSR5n3uvJh8wFZWWnb5QrPed1xOSbx8/GDrEVMuHo0zedXvueDDy6mHjiz9vyYRt11OSWzWa6CINIm4pe3ov7pc6NSOdR3ue9RgdhORFjcPtR+4HGgrL499bqpHs5at7hhb/ebN9RoETXz85OaVNdlAVRd4/XsEAKgLN+JHo7qui8jR916s+KnUqEVhsxa0GnSPtbQ4eflcEclPjL7pjrHlhZevnDjcKKRb2rq3LEVXz8d/2/uV1ZpmyNjw3rkD34TOnOs/+F7dak1+d4HLFc/+sMPLr3Wff31cVnCprODisfdfFpGUyNdcDtR125Elz/R+eXVhVkrFd9D89+bFYDJlbvrwYnJc0dnT191ANRcIAPgd0gICutT1HgAAqDP8ZRkAgNIIIQBAaYQQAKA0QggAUBohBAAojRACAJRGCAEASiOEAAClEUIAgNIIIQBAaYQQAKA0QggAUBohBAAojRACAJRGCAEASiOEAAClEUIAgNIIIQBAaYQQAKA0QggAUBohBAAojRACAJRGCAEASiOEAAClEUIAgNIIIQBAaYQQAKA0QggAUBohBAAojRACAJRGCAEASiOEAAClEUIAgNIIIQBAaYQQAKA0QggAUBohBAAojRACAJRGCAEASiOEAAClEUIAgNIIIQBAaYQQAKC0Wg3hypXLP/305Q0b3l+1atn48Q9169YlJKRbevrJTz9d9cknpfv3i8gvvZzde++9lJZ2UtM0o9HYpUuHL7/8+meN+vTTl1esWKppmtFo7NSp/aefrvq5o/r163P11BlZ5Omnn7pwoXDkyDsNBkPFl2JiYtLTs0SkbdsAg8GQnX1m6tR7R49+8LqjFiyYn5iYLCMmCdf3AAAPyElEQVT3f+DAwZ07v922bZeI3HZbnyeffFi3nU40Xb165dy5Tw4ePBiP7wDwc1MHhFA87LbbQ0S6du3YteufFi58d+3az444+QcPHszNPZeami4izZo1iYlJEBGTyZiTU/rrrwz86QoCAr7//vvffOVeImI0Gnx8GtTWcgAQd7/fI5mYxZEjaUVFRX369GjSpLGIZGZmP/XUI4sXz69mQu2+l+Cdd17+4IM14h7Q6MmXl2/fvnvMmIfsL3333cHMzFMiYjabd+3aLyJ9+nR7660PIiIi3n33lYiIro88cn1iYlJqapr9Fy+/vDgp6Yj9OCkpafbsGfv2JYjIV1/tFZEBA/rExe1v0KC+yWTy8HAvKCgUkccee3DWrKfsyz3++IMi0qCB99tvf/TCC88dOJB4332jHn10prgH/Pe//3z44T/X1h0DgD+EWguhplmGDbvdYrHk5+cnJma4uzfw8/Np1KjhnXf+yc/PR9O0s2fP7tuX4HJCl0+EmzZ9euzYsT17Ymy21/Ly/n/s3XlYU9f+B/BvQhISloAsYVEQkEURQVktiB2XqlZbq+217VufttV6az989T219vq01k5r62Wq1qXa1qcWByqj4gIqyCqLIIggEFaBsCRk+f3hO0eHSSAO1Pm9nn9w8n3OPfckhPNhOZyT3KNHj/v2HQgIGDppUo2mnT6deetbSssriouVpjxNT09PTq0fPHhQe7rOzs78+PHe+/btv+22oICA4e7u7pGRkUql0sPDY+TIQBERXl5eUVExIuLo6CgizZqeys7ONQwVEe3adTwtTbspIi2tFhEx5M+f//f48eOEQhYA1F/nhXDRok9///3wypU/CgiY/PLLi0TELyRkSk5Orqj0PDwmy5YtHjly+px5HzUOV3shiUSiUqk2bvzH2bMXZkyYOG3aLBMTE01XZpc4ObV6ltMq/2xHtNtaW5vv2rXX1ta2Z8+e8+cvs7GxUSgU+/cfMTE28etlL6bt5ua2Y8f/REQlMo/M/K2ZmeXvvycfO3a8cUumUHe2TwBwczQ2m6VnV4lCoaisVFdXV1dUKCsrKysrq66vN1lfX2dpaSkibHhYLJZd3ctXk9lsnnYlEon8/PiPH3761Km/Nm36JiPjT2dn53379nfu3HnFiu91e2ZmntX9WCajjUQiSUhI1Oo4IiLo9/0EADdMo4tD165dPX/+YlpaRufOnboSEYnI2bMXvbw8e/XqXlhY+OOPO/r27T158qiGhgalUq26du3atWtX/fz6i0hBQcHly5ddXbkmJib3W6+2trbW1lYREYvFEhNbc3MLEWlublapVA0NDY6Ojvt+P5iVlTU7a9Z8G5v2IpKZmUlEXl4eIpKRkVlaWhYSMsXFxcXUtJmpqamHh4etrZ2RkVGXLl3u2Z6ISOXlVxoaGkRkyZJFmzZtNzMza2hoyM09EBAQoC1n+fLQo0eP7927f8uWLZ6eHkQ0YMCAsLCf0tLSfH199+7df/nyFXNz82++Wd+5c+dbLgcA0Ag0R8R4RE+dmmAiY+gbG3Xr1iUl5aj2o5GRkY2NjYODQ3Z29syZ0/LzC+7ZZkZG5pQpE4cOHaJSqRITkxYsSFBVVUVExOubmNUq5fj4CT4+3hER4Q0NDUlJqUuWLPrii4QR6voeHh5hYWG9e/e6fPny1q3fh4VN++yzz42MjD5b99nmzVu3bv3e27uXiLBYLBMTk6NHj3355ZezZ88SEXd3d19fXz4/tKio6OjRY8OG+R0/frK6unrlyuX/+9/eF198MTl5v7Oz8/bte955562oqCiNxiI+ft6GDT8FBAR4e/M8PT26des2fHhAXV1dWlraLbf0pkIhRESjocLCQh42bPhvv+3p3bv3lStX0tJ03+Tq1r9//3feeaewsKhXr16pqWmXLl3Ky8srKioODQ01MTHZtu37xMRES0tLLy/PoUOH6o6h4XoBoAVojiAxHu8wGnXLls0/+eQjfWO7dOn0zz93d8nYGB4Z6ddfd/zzn1+o1dd5Y8IMe/bFf/MaBoPh4eFeWVl5C5cdHh5uYmLKMNzevb+amJhIpdJvv/0vEURF3b1hww+TJ0/64Ydt8fGJs2d/lpCQEBcXN3PmTO0SdXVqR0en0NApInL48JH169dv377d39+/qurql1+upN/XEQBoeYxuWSAo/t6nT5+JiopydnY+ePBQWlp6u38X7gMA6hYhBFjx8bELFizm8XhE9MEH78+dG3NnVwEAf1t4RwgAIH/7NQIAALcDIQQAkEIIIQCEEDI+QggAIYQAEEIIACCEEABC2BwYAAAQEEIACCGEABBCAAAJIQQAkEIIASCEAABCCCEEgBACQEL3WAUAAAKEEABCCAEghBAAQggBIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghhAAAAYQQAEIIASCEEABACCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYQAEEIIACGEAABCCCEEgBBCAAghBIAQQgAIIQQAIYQAEEIIACGEABBCAAAJIYSIEHHBggXdunWLiYk5f/78naxl27aYb7/9loho+vTp77//PpPJvPWl2rVr19DQoE8tk8l0d3d//PHHXVxc9KkNAODe1CofER48ePDChQsODg4LFy5kMpmXL1/esGGDnZ3dmjVrbq2Wy5cvE5GLi4s+NenU4Ovr26NHjxMnsg4ePKBPbQAA96zWO0d44cIFNze3119/3c/Pj8ViiUhVVdXjjz9eU1NzC7Xs2LFDJpMJBILy8nJ9yiouLq6srGQymT/99FN2djYAADzaWohIJBIJBAJPT0+VStXS9Rw9elStVs+ZM8fCwkJfQQsWLJgxY4aentovvvhi586d58+f15mZmZk5atQoJycnIpJKpXFxcRqNZtu2bZ07dx40aJBIJNq3b19AQMDly5f3798/bNgwgUDwzTffFBcXBwcHp6SkHDhwYP/+/U5OTmZmZl999VVNTU1wcPCiRYuOHDkSFhZ25MiRFStWhIeHZ2dnL1y4sLq6ms/n9+7de9WqVVwut6GhIT4+Pjo6+rXXXhs9evTZs2d//PHHV1555Y6+OQCAv52ndl+/fi0iREQajcbGxmbHjh3Dhg2rqKj44IMPrK2te/XqtXv3bn1Keuihhw4dOpScnNyrVy99jpiYmOjoaGMjYy6XS0RqtVomkxUWFkokEg8PDyaTmZ6evmfPHoFAIJPJJk+e/Oabb1706Lx9+/b//Oc/iYmJpqamubm5Fy9efPPNN9euXbtq1ar58+f37dv3wIEDNBpNqVQyGAwiyszMnDx5cnFxsZWVVbdu3XJzc4nowIEDOTk5n376KRGpVKq8vLyvvvoqLy/v1KlTq1evjo+PLy4ufvbZZ8vLy+/0+wMA+FtonTlCgUCwb98+lUp19uzZTz75pKamJi4ubsCAAUePHvXy8rp06VJJSYk+Jen2b7e3txcIBLrDWCwWhUIpKSkRCARyuVx3RG1tbXV1tbW1NRFxuVwigUKhMBiMoqKiX3755ZVXXhGLxUS0cePGkSNHOjk5tWvXTluf7nP0/2tqarKzs4lo0qRJGzZsMDY2Xrt2bUBAQHFxMRG5uLgcPnxYLpcvXrz4mWee+fbbb2NjY59//vnBgwc3e4sAAOQ+Yjx9glZUVJSUlBw6dOjSpUv9+vXbt2/fDz/8sH///nfffTcqKqpVq1bTp09vrsl+v5WUlJCSkkJEFRUVUqlUJBIZGRkRUUlJCZfL7dq1K4vFcnFx6dq1K5PJ7NKlS2RkZEBAQFhYGBFJpdLNmze//vrra9euzcnJISLd5f+oOTY2NjU1NSYmJjg4+NixY9bW1hqN5tChQ2PGjPH3928wclxM0w1VqVTJyclvv/22bqG2trZFRUVarbdv3/7UU0+1adOGz+f37duXiGJjY6dOnerp6Xnul1NiYuL3338/efJkR0fHxYsXS6XSbdu2LViwYP78+Z6enn/X7xAAQJ9a70+EYrH4448/NjU1Xbt27fvvv9+7d28Oh+Po6FhUVDRq1Kh169bNmDGD7jN9+PDhDz74gIjuueee9957j8/nazSaUaNGhYWFZWZmzps3LzQ09KWXXiIiFovl5+dnbGzcr1+/rKysRx99VKVSzZgxo7y83MTE5JNPPqHT6UQkFAr9/f3Nzc1XrlzZ0NBw/PjxHj16+Pv7u7u7d+/e3d3d3cPD49y5c2KxuLKy8urVq05OTn369MnPzzczM7ty5YqTk9PAgQOzsrKISLdHmZmZ06dPnzZtmi7DlpaW48ePz8jI+Pbbb0ePHl1cXMxisQICAi5cuMDn8zMyMhob3oxGI51O1+01NjbGZDKnTp168ODB2bNnr1mzpn///hkZGT/99NPo0aPPnz/f3I2j0WhEwwMIAO5VGIIiIiIajebi4pKbm7ty5crQ0NCffvpp9uzZb7/9dlhYmFgsXrlyJYVCeeyxx0JCQmbMmJGRkXHp0iXlj+G/MAAAHONJREFU2RIrK6u//OUvCoVCIpE8/vjjfD6/oqIiLCzMwcGBx+MRUZ8+fVasWBEYGDh+/Phr1649/vjjp0+fjo+P79mzZ3h4eFJSkpmZ2e7duxmN/xD1b7/9xmazg4KCRowY8cILL0yfPj0lJaW2tnbz5s3du3fXarVpaWm1tbVcLvfw4cOPPPLIBx98sGvXLi6XK5FIUlJS0tLSOnToUFZWNnTo0H//+99ExOFw4uLiampqJkyYUFZWRkT5+flisVgsFj/xxBMCgaChoeHy5csSicTc3DwsLIzFYhERjUYrKChISkqaM2eOp6cnnU4nIpVK1bt3706dOq1bt27dunWEH90D4N6GjggR0aRJk4hIqVSKRCIzM7OysjI3NzeJREJEubm5EyZMGDRo0Jtvvvn+++8vX768Xbt2Tz75ZHh4+IIFC2g0mkgk6tmzJ5vNzs/Pd3Fxqa2tbdu2rVar7d+/v6en57Rp0/h8PhHJ5XI7O7sFCxY4Ojq+9NJL5ubm9vb2QqHwkUceOX/+fEFBQW5u7vr162NjY3Uvs99fOp3OZDJ79uzZqVOn4uJiCwuLxx9/nMlkHjp0qLi4WFcGl8utqanp0KGDQqFISUnR1WFkZGRnZ3fgwIH58+enpKQIpjI++eQTIpLL5ZWVlVu2bCktLS0rK0tOTlYsXRIeHi4SiYiopqbmo48+2rlzZ0ZGBofD6dKli5+fX0lJyTfffLN48eIuXbpIpVI+n9+tWzerxq48AACPAouI8IKK6Nq1a9euXXUqeOeddxYvXvzYY4+dP39eX2k7O7vk5OTOnTsfOXJk+/btCxYsIKINGzZ88skn48eP7y9on5aWNn/+fN3QefPmHTp0KDU1dc6cOc2VT6fTN2/e/NJLL+krGwAAPu05Qh5PKBaLjx071rFjx/bt2xORQqGQy+UCgaC6urq6unrz5s1E5O7u3rdv3+rq6ps3b2q12o4dO546dUokEu3bt8/KyuqTTz4hIk9PzwcffLC+vh7vhQCAFqd9R4iUBn+LKBQKCoWSlJSk0Whqa2vPnDlTVlZ26NChkJAQlUp18+bN5OTk3NxcLpd769GlS5dSqVQ6nd69e/cXX3zR19f3ypUrmzZtKioq6tOnT3x8PIPBICYGAAC8IzxtsFmssLCwgIAAHo8nkUguXLiQnZ1tZ2e3cuXKqVOfpv+PYzQajUb70/8vFyIqKiqKjIycMmVKbW1tRUVFbm6uWq32xv8LBQB4tGkUwtmzZxMTE/FPCQHgd/7OS5QAAEA3Vqs/ESEAAIDeEEIAABmEEABABiEEAJBBCAEAZBBCAAAZhBAAQKaNTQfcbwIAQAhCCAAghiEEABBDCAEAxBBCAIBbhhACAOT/xDcAAMB/hj8RAgDI/H+J3gYgOqnyVQAAAABJRU5ErkJggg==", "base64");
725
654
  binary = await this.helpers.prepareBinaryData(demoPng, "screenshot.png", "image/png");
726
655
  } else {
727
- try {
728
- browser = await client.rent(sid2, { mode });
729
- session_id = browser.sessionId;
730
- await browser.navigate(url);
731
- await sleep(ms);
732
- const shot = await browser.screenshot({ format: "png", fullPage: true });
733
- const data = shot.toString("base64");
734
- binary = await this.helpers.prepareBinaryData(Buffer.from(data, "base64"), "screenshot.png", "image/png");
735
- await browser.close();
736
- } catch (e) {
737
- throw new Error(`Full op failed at step "${browser?.sessionId ? "navigate/screenshot" : "rent"}": ${e.message}`);
738
- }
656
+ browser = await client.rent(sid2, { mode });
657
+ session_id = browser.sessionId;
658
+ await browser.navigate(url);
659
+ await sleep(ms);
660
+ const shot = await browser.screenshot({ format: "png", fullPage: true });
661
+ const data = shot.toString("base64");
662
+ binary = await this.helpers.prepareBinaryData(Buffer.from(data, "base64"), "screenshot.png", "image/png");
663
+ await browser.close();
739
664
  }
740
665
  out.push({
741
666
  json: {
@@ -748,86 +673,57 @@ var BrowserCeki = class {
748
673
  binary: { data: binary }
749
674
  });
750
675
  } finally {
751
- await client.close().catch(() => {
752
- });
676
+ await client.close();
753
677
  }
754
678
  continue;
755
679
  }
756
680
  const sessionId = this.getNodeParameter("sessionId", i);
757
- try {
758
- browser = await client.resume(sessionId);
759
- } catch (e) {
760
- throw new Error(`Resume session "${sessionId}" failed: ${e.message}. Session may have expired or still be in grace.`);
761
- }
681
+ browser = await client.resume(sessionId);
762
682
  const sid = browser.sessionId;
763
683
  switch (op) {
764
684
  case "navigate": {
765
- try {
766
- const url = this.getNodeParameter("url", i);
767
- await browser.navigate(url);
768
- out.push({ json: { session_id: sid, url } });
769
- } catch (e) {
770
- throw new Error(`Navigate failed: ${e.message}`);
771
- }
685
+ const url = this.getNodeParameter("url", i);
686
+ await browser.navigate(url);
687
+ out.push({ json: { session_id: sid, url } });
772
688
  break;
773
689
  }
774
690
  case "click": {
775
- try {
776
- const x2 = this.getNodeParameter("x", i);
777
- const y2 = this.getNodeParameter("y", i);
778
- await browser.click(x2, y2);
779
- out.push({ json: { session_id: sid, clicked: [x2, y2] } });
780
- } catch (e) {
781
- throw new Error(`Click at (${x},${y}) failed: ${e.message}`);
782
- }
691
+ const x = this.getNodeParameter("x", i);
692
+ const y = this.getNodeParameter("y", i);
693
+ await browser.click(x, y);
694
+ out.push({ json: { session_id: sid, clicked: [x, y] } });
783
695
  break;
784
696
  }
785
697
  case "type": {
786
- try {
787
- const text = this.getNodeParameter("text", i);
788
- await browser.type(text);
789
- out.push({ json: { session_id: sid, typed: text } });
790
- } catch (e) {
791
- throw new Error(`Type failed: ${e.message}`);
792
- }
698
+ const text = this.getNodeParameter("text", i);
699
+ await browser.type(text);
700
+ out.push({ json: { session_id: sid, typed: text } });
793
701
  break;
794
702
  }
795
703
  case "scroll": {
796
- try {
797
- const deltaY = this.getNodeParameter("deltaY", i);
798
- await browser.scroll(deltaY);
799
- out.push({ json: { session_id: sid, scrolled: deltaY } });
800
- } catch (e) {
801
- throw new Error(`Scroll failed: ${e.message}`);
802
- }
704
+ const deltaY = this.getNodeParameter("deltaY", i);
705
+ await browser.scroll(deltaY);
706
+ out.push({ json: { session_id: sid, scrolled: deltaY } });
803
707
  break;
804
708
  }
805
709
  case "screenshot": {
806
- try {
807
- const format = this.getNodeParameter("format", i);
808
- const fullPage = this.getNodeParameter("fullPage", i);
809
- const shot = await browser.screenshot({ format, fullPage });
810
- const data = format === "base64" ? shot.data : shot.toString("base64");
811
- const binary = await this.helpers.prepareBinaryData(
812
- Buffer.from(data, "base64"),
813
- "screenshot.png",
814
- "image/png"
815
- );
816
- out.push({ json: { session_id: sid }, binary: { data: binary } });
817
- } catch (e) {
818
- throw new Error(`Screenshot failed: ${e.message}`);
819
- }
710
+ const format = this.getNodeParameter("format", i);
711
+ const fullPage = this.getNodeParameter("fullPage", i);
712
+ const shot = await browser.screenshot({ format, fullPage });
713
+ const data = format === "base64" ? shot.data : shot.toString("base64");
714
+ const binary = await this.helpers.prepareBinaryData(
715
+ Buffer.from(data, "base64"),
716
+ "screenshot.png",
717
+ "image/png"
718
+ );
719
+ out.push({ json: { session_id: sid }, binary: { data: binary } });
820
720
  break;
821
721
  }
822
722
  case "snapshot": {
823
- try {
824
- const snap = await browser.snapshot();
825
- out.push({
826
- json: { session_id: sid, screenshot: snap.screenshot }
827
- });
828
- } catch (e) {
829
- throw new Error(`Snapshot failed: ${e.message}`);
830
- }
723
+ const snap = await browser.snapshot();
724
+ out.push({
725
+ json: { session_id: sid, screenshot: snap.screenshot }
726
+ });
831
727
  break;
832
728
  }
833
729
  case "wait": {
@@ -864,79 +760,30 @@ var BrowserCeki = class {
864
760
  break;
865
761
  }
866
762
  case "upload": {
867
- try {
868
- const selector = this.getNodeParameter("selector", i);
869
- const bpn = this.getNodeParameter("binaryPropertyName", i);
870
- const bin = items[i].binary?.[bpn];
871
- if (!bin) throw new Error(`Binary property "${bpn}" not found on input`);
872
- const stream = await this.helpers.getBinaryStream(bin.id);
873
- const chunks = [];
874
- for await (const c of stream) chunks.push(c);
875
- const buf = Buffer.concat(chunks);
876
- const res = await browser.upload(selector, buf);
877
- out.push({ json: { session_id: sid, uploaded: res } });
878
- } catch (e) {
879
- throw new Error(`Upload failed: ${e.message}`);
880
- }
763
+ const selector = this.getNodeParameter("selector", i);
764
+ const bpn = this.getNodeParameter("binaryPropertyName", i);
765
+ const bin = items[i].binary?.[bpn];
766
+ if (!bin) throw new Error(`Binary property "${bpn}" not found on input`);
767
+ const stream = await this.helpers.getBinaryStream(bin.id);
768
+ const chunks = [];
769
+ for await (const c of stream) chunks.push(c);
770
+ const buf = Buffer.concat(chunks);
771
+ const res = await browser.upload(selector, buf);
772
+ out.push({ json: { session_id: sid, uploaded: res } });
881
773
  break;
882
774
  }
883
775
  case "close": {
884
- try {
885
- await browser.close().catch(() => {
886
- });
887
- } catch {
888
- }
889
- await new Promise((resolve) => {
890
- const stopWs = new WebSocket("wss://browser.ceki.me/ws/agent", [`bearer.${token}`]);
891
- const abortTimer = AbortSignal.timeout(1e4);
892
- const onTimer = () => {
893
- try {
894
- stopWs.close();
895
- } catch {
896
- }
897
- resolve();
898
- };
899
- abortTimer.addEventListener("abort", onTimer, { once: true });
900
- stopWs.onopen = () => {
901
- stopWs.send(JSON.stringify({ type: "stop", session_id: sessionId, reason: "n8n close" }));
902
- };
903
- stopWs.onmessage = (ev) => {
904
- try {
905
- const msg = JSON.parse(ev.data);
906
- if (msg.type === "session_ended") {
907
- abortTimer.removeEventListener("abort", onTimer);
908
- try {
909
- stopWs.close();
910
- } catch {
911
- }
912
- resolve();
913
- }
914
- } catch {
915
- }
916
- };
917
- stopWs.onerror = () => {
918
- abortTimer.removeEventListener("abort", onTimer);
919
- resolve();
920
- };
921
- stopWs.onclose = () => {
922
- abortTimer.removeEventListener("abort", onTimer);
923
- resolve();
924
- };
925
- });
776
+ await browser.close();
926
777
  out.push({ json: { closed: true, session_id: sessionId } });
927
778
  break;
928
779
  }
929
780
  }
930
- needFullClose = op === "close";
931
- } finally {
932
- try {
933
- if (needFullClose) {
934
- await client.close();
935
- } else {
936
- await client.disconnect();
937
- }
938
- } catch {
781
+ if (op === "close") {
782
+ await client.close();
783
+ } else {
784
+ await client.disconnect();
939
785
  }
786
+ } finally {
940
787
  }
941
788
  }
942
789
  return [out];