n8n-nodes-nvk-browser 1.0.113 → 1.0.115

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.
@@ -1,8 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.nvkBrowserFields = void 0;
4
+ const CreateProfile_description_1 = require("../ProfileManagement/CreateProfile/CreateProfile.description");
5
+ const DeleteProfile_description_1 = require("../ProfileManagement/DeleteProfile/DeleteProfile.description");
6
+ const StartProfile_description_1 = require("../ProfileManagement/StartProfile/StartProfile.description");
7
+ const StopProfile_description_1 = require("../ProfileManagement/StopProfile/StopProfile.description");
8
+ const MoveAndClick_description_1 = require("../PageInteraction/MoveAndClick/MoveAndClick.description");
9
+ const RunJavaScript_description_1 = require("../PageInteraction/RunJavaScript/RunJavaScript.description");
10
+ const GetNetworkResponse_description_1 = require("../PageInteraction/GetNetworkResponse/GetNetworkResponse.description");
11
+ const BrowserHttpRequest_description_1 = require("../PageInteraction/BrowserHttpRequest/BrowserHttpRequest.description");
12
+ // Update displayOptions for all fields to use new resource/operation values
13
+ const updateDisplayOptions = (fields, resource, operation) => {
14
+ return fields.map(field => ({
15
+ ...field,
16
+ displayOptions: {
17
+ show: {
18
+ resource: [resource],
19
+ operation: [operation],
20
+ },
21
+ },
22
+ }));
23
+ };
4
24
  exports.nvkBrowserFields = [
5
- // ===== Resource =====
6
25
  {
7
26
  displayName: 'Resource',
8
27
  name: 'resource',
@@ -19,18 +38,13 @@ exports.nvkBrowserFields = [
19
38
  },
20
39
  ],
21
40
  default: 'profileManagement',
41
+ description: 'Select a resource',
22
42
  },
23
- // ===== Operation =====
24
43
  {
25
44
  displayName: 'Operation',
26
45
  name: 'operation',
27
46
  type: 'options',
28
47
  noDataExpression: true,
29
- displayOptions: {
30
- show: {
31
- resource: ['profileManagement'],
32
- },
33
- },
34
48
  options: [
35
49
  {
36
50
  name: 'Create Profile',
@@ -58,20 +72,20 @@ exports.nvkBrowserFields = [
58
72
  },
59
73
  ],
60
74
  default: 'createProfile',
75
+ displayOptions: {
76
+ show: {
77
+ resource: ['profileManagement'],
78
+ },
79
+ },
61
80
  },
62
81
  {
63
82
  displayName: 'Operation',
64
83
  name: 'operation',
65
84
  type: 'options',
66
85
  noDataExpression: true,
67
- displayOptions: {
68
- show: {
69
- resource: ['pageInteraction'],
70
- },
71
- },
72
86
  options: [
73
87
  {
74
- name: 'Move And Click',
88
+ name: 'Move and Click',
75
89
  value: 'moveAndClick',
76
90
  description: 'Move mouse and click on an element',
77
91
  action: 'Move and click',
@@ -79,919 +93,37 @@ exports.nvkBrowserFields = [
79
93
  {
80
94
  name: 'Run JavaScript',
81
95
  value: 'runJavaScript',
82
- description: 'Execute JavaScript code',
96
+ description: 'Execute JavaScript code in the browser',
83
97
  action: 'Run JavaScript',
84
98
  },
85
99
  {
86
100
  name: 'Get Network Response',
87
101
  value: 'getNetworkResponse',
88
- description: 'Get network response from browser',
102
+ description: 'Capture network request responses',
89
103
  action: 'Get network response',
90
104
  },
91
105
  {
92
106
  name: 'Browser HTTP Request',
93
107
  value: 'browserHttpRequest',
94
- description: 'Make HTTP request using browser cookies and headers',
108
+ description: 'Make HTTP requests using browser cookies',
95
109
  action: 'Make HTTP request',
96
110
  },
97
111
  ],
98
112
  default: 'moveAndClick',
99
- },
100
- // ===== Profile Management: Create Profile =====
101
- {
102
- displayName: 'Profile Name',
103
- name: 'profileName',
104
- type: 'string',
105
- required: true,
106
- default: '',
107
- description: 'Name of the profile to create',
108
- displayOptions: {
109
- show: {
110
- resource: ['profileManagement'],
111
- operation: ['createProfile'],
112
- },
113
- },
114
- },
115
- {
116
- displayName: 'Proxy',
117
- name: 'proxy',
118
- type: 'string',
119
- default: '',
120
- placeholder: 'http:127.0.0.1:8080:user:pass hoặc socks5:127.0.0.1:1080:user:pass',
121
- description: 'Proxy format: http://myip:port:user:pass or socks5://myip:port:user:pass (hoặc không có ://)',
122
- displayOptions: {
123
- show: {
124
- resource: ['profileManagement'],
125
- operation: ['createProfile'],
126
- },
127
- },
128
- },
129
- {
130
- displayName: 'Note',
131
- name: 'note',
132
- type: 'string',
133
- default: '',
134
- description: 'Optional note for this profile',
135
- displayOptions: {
136
- show: {
137
- resource: ['profileManagement'],
138
- operation: ['createProfile'],
139
- },
140
- },
141
- },
142
- {
143
- displayName: 'Extensions',
144
- name: 'extensions',
145
- type: 'string',
146
- typeOptions: {
147
- rows: 4,
148
- },
149
- default: '',
150
- placeholder: 'Nhập ID extension Chrome Store hoặc đường dẫn tới extension local, mỗi extension một dòng',
151
- description: 'Enter Chrome Store extension ID or path to local extension, one extension per line',
152
- displayOptions: {
153
- show: {
154
- resource: ['profileManagement'],
155
- operation: ['createProfile'],
156
- },
157
- },
158
- },
159
- // ===== Profile Management: Delete Profile =====
160
- {
161
- displayName: 'Profile ID',
162
- name: 'profileId',
163
- type: 'string',
164
- required: true,
165
- default: '',
166
- description: 'ID of the profile to delete',
167
- displayOptions: {
168
- show: {
169
- resource: ['profileManagement'],
170
- operation: ['deleteProfile'],
171
- },
172
- },
173
- },
174
- // ===== Profile Management: Start Profile =====
175
- {
176
- displayName: 'Profile ID',
177
- name: 'profileId',
178
- type: 'string',
179
- required: true,
180
- default: '',
181
- description: 'ID of the profile to start',
182
- displayOptions: {
183
- show: {
184
- resource: ['profileManagement'],
185
- operation: ['startProfile'],
186
- },
187
- },
188
- },
189
- {
190
- displayName: 'Window Scale',
191
- name: 'winScale',
192
- type: 'number',
193
- typeOptions: {
194
- minValue: 0.5,
195
- maxValue: 3,
196
- numberStepSize: 0.1,
197
- },
198
- default: 1,
199
- description: 'Window scale factor',
200
- displayOptions: {
201
- show: {
202
- resource: ['profileManagement'],
203
- operation: ['startProfile'],
204
- },
205
- },
206
- },
207
- {
208
- displayName: 'Window Position',
209
- name: 'winPosition',
210
- type: 'fixedCollection',
211
- typeOptions: {
212
- multipleValues: false,
213
- },
214
- default: {},
215
- description: 'Window position on screen',
216
- displayOptions: {
217
- show: {
218
- resource: ['profileManagement'],
219
- operation: ['startProfile'],
220
- },
221
- },
222
- options: [
223
- {
224
- name: 'position',
225
- displayName: 'Position',
226
- values: [
227
- {
228
- displayName: 'X',
229
- name: 'x',
230
- type: 'number',
231
- default: 0,
232
- },
233
- {
234
- displayName: 'Y',
235
- name: 'y',
236
- type: 'number',
237
- default: 0,
238
- },
239
- ],
240
- },
241
- ],
242
- },
243
- {
244
- displayName: 'Window Size',
245
- name: 'winSize',
246
- type: 'fixedCollection',
247
- typeOptions: {
248
- multipleValues: false,
249
- },
250
- default: {},
251
- description: 'Window size',
252
- displayOptions: {
253
- show: {
254
- resource: ['profileManagement'],
255
- operation: ['startProfile'],
256
- },
257
- },
258
- options: [
259
- {
260
- name: 'size',
261
- displayName: 'Size',
262
- values: [
263
- {
264
- displayName: 'Width',
265
- name: 'width',
266
- type: 'number',
267
- default: 1280,
268
- },
269
- {
270
- displayName: 'Height',
271
- name: 'height',
272
- type: 'number',
273
- default: 720,
274
- },
275
- ],
276
- },
277
- ],
278
- },
279
- {
280
- displayName: 'Headless Mode',
281
- name: 'headless',
282
- type: 'boolean',
283
- default: false,
284
- description: 'Run browser in headless mode',
285
- displayOptions: {
286
- show: {
287
- resource: ['profileManagement'],
288
- operation: ['startProfile'],
289
- },
290
- },
291
- },
292
- // ===== Profile Management: Stop Profile =====
293
- {
294
- displayName: 'Profile ID',
295
- name: 'profileId',
296
- type: 'string',
297
- required: true,
298
- default: '',
299
- description: 'ID of the profile to stop',
300
- displayOptions: {
301
- show: {
302
- resource: ['profileManagement'],
303
- operation: ['stopProfile'],
304
- },
305
- },
306
- },
307
- // ===== Page Interaction: Move And Click =====
308
- {
309
- displayName: 'Profile ID',
310
- name: 'profileId',
311
- type: 'string',
312
- required: true,
313
- default: '',
314
- description: 'ID of the running profile',
315
- displayOptions: {
316
- show: {
317
- resource: ['pageInteraction'],
318
- operation: ['moveAndClick'],
319
- },
320
- },
321
- },
322
- {
323
- displayName: 'Selector',
324
- name: 'selector',
325
- type: 'string',
326
- required: true,
327
- default: '',
328
- description: 'For Puppeteer: CSS selector, XPath (with >XPATH> prefix), or paste the full Puppeteer code from Chrome Recorder (export as "Puppeteer"). The node will automatically detect and execute .click() or .fill() actions from Locator.race() blocks. Examples: "textarea", ">XPATH>/html/body/div", or full code with puppeteer.Locator.race([...]).click()/.fill(). For Javascript: CSS selector only. Note: The node only executes click/fill actions, not goto() or other navigation actions.',
329
- typeOptions: {
330
- rows: 4,
331
- },
332
- displayOptions: {
333
- show: {
334
- resource: ['pageInteraction'],
335
- operation: ['moveAndClick'],
336
- },
337
- },
338
- },
339
- {
340
- displayName: 'Timeout (Milliseconds)',
341
- name: 'timeout',
342
- type: 'number',
343
- default: 30000,
344
- description: 'Timeout in milliseconds for waiting for the element',
345
- displayOptions: {
346
- show: {
347
- resource: ['pageInteraction'],
348
- operation: ['moveAndClick'],
349
- },
350
- },
351
- },
352
- {
353
- displayName: 'Click Method',
354
- name: 'clickMethod',
355
- type: 'options',
356
- options: [
357
- {
358
- name: 'Use Puppeteer',
359
- value: 'puppeteer',
360
- },
361
- {
362
- name: 'Use Javascript Click',
363
- value: 'javascript',
364
- },
365
- ],
366
- default: 'puppeteer',
367
- description: 'Method to use for clicking',
368
- displayOptions: {
369
- show: {
370
- resource: ['pageInteraction'],
371
- operation: ['moveAndClick'],
372
- },
373
- },
374
- },
375
- {
376
- displayName: 'Wait For Click (Milliseconds)',
377
- name: 'waitForClick',
378
- type: 'number',
379
- default: 500,
380
- description: 'Wait time before clicking in milliseconds',
381
- displayOptions: {
382
- show: {
383
- resource: ['pageInteraction'],
384
- operation: ['moveAndClick'],
385
- clickMethod: ['puppeteer'],
386
- },
387
- },
388
- },
389
- {
390
- displayName: 'Button',
391
- name: 'button',
392
- type: 'options',
393
- options: [
394
- {
395
- name: 'Left',
396
- value: 'left',
397
- },
398
- {
399
- name: 'Right',
400
- value: 'right',
401
- },
402
- {
403
- name: 'Middle',
404
- value: 'middle',
405
- },
406
- ],
407
- default: 'left',
408
- description: 'Mouse button to use',
409
- displayOptions: {
410
- show: {
411
- resource: ['pageInteraction'],
412
- operation: ['moveAndClick'],
413
- clickMethod: ['puppeteer'],
414
- },
415
- },
416
- },
417
- {
418
- displayName: 'Click Count',
419
- name: 'clickCount',
420
- type: 'number',
421
- default: 1,
422
- typeOptions: {
423
- minValue: 1,
424
- },
425
- description: 'Number of times to click',
426
- displayOptions: {
427
- show: {
428
- resource: ['pageInteraction'],
429
- operation: ['moveAndClick'],
430
- clickMethod: ['puppeteer'],
431
- },
432
- },
433
- },
434
- {
435
- displayName: 'Tab Index',
436
- name: 'tabIndex',
437
- type: 'number',
438
- default: 0,
439
- description: 'Index of the tab to interact with (0 = first tab)',
440
- displayOptions: {
441
- show: {
442
- resource: ['pageInteraction'],
443
- operation: ['moveAndClick'],
444
- },
445
- },
446
- },
447
- {
448
- displayName: 'Auto Start Profile',
449
- name: 'autoStart',
450
- type: 'boolean',
451
- default: false,
452
- description: 'Automatically start the profile if it is not running',
453
- displayOptions: {
454
- show: {
455
- resource: ['pageInteraction'],
456
- operation: ['moveAndClick'],
457
- },
458
- },
459
- },
460
- {
461
- displayName: 'Use Binary File from n8n',
462
- name: 'useBinaryFile',
463
- type: 'boolean',
464
- default: false,
465
- description: 'Use binary file from n8n instead of file path in fill action',
466
- displayOptions: {
467
- show: {
468
- resource: ['pageInteraction'],
469
- operation: ['moveAndClick'],
470
- clickMethod: ['puppeteer'],
471
- },
472
- },
473
- },
474
- {
475
- displayName: 'Binary Property Name',
476
- name: 'binaryPropertyName',
477
- type: 'string',
478
- default: 'data',
479
- description: 'Name of the binary property containing the file to upload',
480
- displayOptions: {
481
- show: {
482
- resource: ['pageInteraction'],
483
- operation: ['moveAndClick'],
484
- clickMethod: ['puppeteer'],
485
- useBinaryFile: [true],
486
- },
487
- },
488
- },
489
- // ===== Page Interaction: Run JavaScript =====
490
- {
491
- displayName: 'Profile ID',
492
- name: 'profileId',
493
- type: 'string',
494
- required: true,
495
- default: '',
496
- description: 'ID of the running profile',
497
- displayOptions: {
498
- show: {
499
- resource: ['pageInteraction'],
500
- operation: ['runJavaScript'],
501
- },
502
- },
503
- },
504
- {
505
- displayName: 'Tab Index',
506
- name: 'tabIndex',
507
- type: 'number',
508
- default: 0,
509
- description: 'Index of the tab to run JavaScript on (0 = first tab)',
510
- displayOptions: {
511
- show: {
512
- resource: ['pageInteraction'],
513
- operation: ['runJavaScript'],
514
- },
515
- },
516
- },
517
- {
518
- displayName: 'JavaScript Code',
519
- name: 'javascriptCode',
520
- type: 'string',
521
- typeOptions: {
522
- rows: 10,
523
- },
524
- required: true,
525
- default: '',
526
- description: 'JavaScript code to execute. If code uses Puppeteer API (page.goto, page.click, etc.), it will run in Node.js context with page object available. Otherwise, it runs in browser context.',
527
- displayOptions: {
528
- show: {
529
- resource: ['pageInteraction'],
530
- operation: ['runJavaScript'],
531
- },
532
- },
533
- },
534
- {
535
- displayName: 'Auto Start Profile',
536
- name: 'autoStart',
537
- type: 'boolean',
538
- default: false,
539
- description: 'Automatically start the profile if it is not running',
540
- displayOptions: {
541
- show: {
542
- resource: ['pageInteraction'],
543
- operation: ['runJavaScript'],
544
- },
545
- },
546
- },
547
- // ===== Page Interaction: Get Network Response =====
548
- {
549
- displayName: 'Profile ID',
550
- name: 'profileId',
551
- type: 'string',
552
- required: true,
553
- default: '',
554
- description: 'ID of the running profile',
555
- displayOptions: {
556
- show: {
557
- resource: ['pageInteraction'],
558
- operation: ['getNetworkResponse'],
559
- },
560
- },
561
- },
562
- {
563
- displayName: 'Request Name or URL',
564
- name: 'requestFilter',
565
- type: 'string',
566
- required: true,
567
- default: '',
568
- description: 'Name of the request (e.g., "create") or URL pattern to match. Can be partial match.',
569
- displayOptions: {
570
- show: {
571
- resource: ['pageInteraction'],
572
- operation: ['getNetworkResponse'],
573
- },
574
- },
575
- },
576
- {
577
- displayName: 'Match Type',
578
- name: 'matchType',
579
- type: 'options',
580
- options: [
581
- {
582
- name: 'Contains',
583
- value: 'contains',
584
- description: 'Request name or URL contains the filter text',
585
- },
586
- {
587
- name: 'Exact',
588
- value: 'exact',
589
- description: 'Request name or URL exactly matches the filter text',
590
- },
591
- {
592
- name: 'Starts With',
593
- value: 'startsWith',
594
- description: 'Request name or URL starts with the filter text',
595
- },
596
- {
597
- name: 'Ends With',
598
- value: 'endsWith',
599
- description: 'Request name or URL ends with the filter text',
600
- },
601
- {
602
- name: 'Regex',
603
- value: 'regex',
604
- description: 'Request name or URL matches the regex pattern',
605
- },
606
- ],
607
- default: 'contains',
608
- description: 'How to match the request',
609
- displayOptions: {
610
- show: {
611
- resource: ['pageInteraction'],
612
- operation: ['getNetworkResponse'],
613
- },
614
- },
615
- },
616
- {
617
- displayName: 'Timeout (Milliseconds)',
618
- name: 'timeout',
619
- type: 'number',
620
- default: 30000,
621
- description: 'Maximum time to wait for the request to appear (in milliseconds)',
622
- displayOptions: {
623
- show: {
624
- resource: ['pageInteraction'],
625
- operation: ['getNetworkResponse'],
626
- },
627
- },
628
- },
629
- {
630
- displayName: 'Wait For Request',
631
- name: 'waitForRequest',
632
- type: 'boolean',
633
- default: true,
634
- description: 'Wait for the request to appear if it has not been made yet',
635
- displayOptions: {
636
- show: {
637
- resource: ['pageInteraction'],
638
- operation: ['getNetworkResponse'],
639
- },
640
- },
641
- },
642
- {
643
- displayName: 'Tab Index',
644
- name: 'tabIndex',
645
- type: 'number',
646
- default: 0,
647
- description: 'Index of the tab to monitor (0 = first tab)',
648
- displayOptions: {
649
- show: {
650
- resource: ['pageInteraction'],
651
- operation: ['getNetworkResponse'],
652
- },
653
- },
654
- },
655
- {
656
- displayName: 'Auto Start Profile',
657
- name: 'autoStart',
658
- type: 'boolean',
659
- default: false,
660
- description: 'Automatically start the profile if it is not running',
661
- displayOptions: {
662
- show: {
663
- resource: ['pageInteraction'],
664
- operation: ['getNetworkResponse'],
665
- },
666
- },
667
- },
668
- // ===== Page Interaction: Browser HTTP Request =====
669
- {
670
- displayName: 'Profile ID',
671
- name: 'profileId',
672
- type: 'string',
673
- required: true,
674
- default: '',
675
- description: 'ID of the running profile to use for cookies and headers',
676
- displayOptions: {
677
- show: {
678
- resource: ['pageInteraction'],
679
- operation: ['browserHttpRequest'],
680
- },
681
- },
682
- },
683
- {
684
- displayName: 'Method',
685
- name: 'method',
686
- type: 'options',
687
- options: [
688
- {
689
- name: 'GET',
690
- value: 'GET',
691
- },
692
- {
693
- name: 'POST',
694
- value: 'POST',
695
- },
696
- ],
697
- default: 'GET',
698
- description: 'HTTP method to use',
699
- displayOptions: {
700
- show: {
701
- resource: ['pageInteraction'],
702
- operation: ['browserHttpRequest'],
703
- },
704
- },
705
- },
706
- {
707
- displayName: 'URL',
708
- name: 'url',
709
- type: 'string',
710
- required: true,
711
- default: '',
712
- description: 'The URL to make the request to',
713
- displayOptions: {
714
- show: {
715
- resource: ['pageInteraction'],
716
- operation: ['browserHttpRequest'],
717
- },
718
- },
719
- },
720
- {
721
- displayName: 'Send Body',
722
- name: 'sendBody',
723
- type: 'boolean',
724
- default: false,
725
- description: 'Whether to send a body in the request',
726
- displayOptions: {
727
- show: {
728
- resource: ['pageInteraction'],
729
- operation: ['browserHttpRequest'],
730
- method: ['POST'],
731
- },
732
- },
733
- },
734
- {
735
- displayName: 'Body Content Type',
736
- name: 'bodyContentType',
737
- type: 'options',
738
- options: [
739
- {
740
- name: 'JSON',
741
- value: 'json',
742
- },
743
- {
744
- name: 'Raw',
745
- value: 'raw',
746
- },
747
- {
748
- name: 'Form Data',
749
- value: 'formData',
750
- },
751
- {
752
- name: 'n8n Binary File',
753
- value: 'binary',
754
- },
755
- ],
756
- default: 'json',
757
- description: 'Content type of the body',
758
- displayOptions: {
759
- show: {
760
- resource: ['pageInteraction'],
761
- operation: ['browserHttpRequest'],
762
- method: ['POST'],
763
- sendBody: [true],
764
- },
765
- },
766
- },
767
- {
768
- displayName: 'JSON Body',
769
- name: 'jsonBody',
770
- type: 'string',
771
- typeOptions: {
772
- rows: 4,
773
- },
774
- default: '',
775
- description: 'JSON body to send',
776
- displayOptions: {
777
- show: {
778
- resource: ['pageInteraction'],
779
- operation: ['browserHttpRequest'],
780
- method: ['POST'],
781
- sendBody: [true],
782
- bodyContentType: ['json'],
783
- },
784
- },
785
- },
786
- {
787
- displayName: 'Raw Body',
788
- name: 'rawBody',
789
- type: 'string',
790
- typeOptions: {
791
- rows: 4,
792
- },
793
- default: '',
794
- description: 'Raw body to send',
795
- displayOptions: {
796
- show: {
797
- resource: ['pageInteraction'],
798
- operation: ['browserHttpRequest'],
799
- method: ['POST'],
800
- sendBody: [true],
801
- bodyContentType: ['raw'],
802
- },
803
- },
804
- },
805
- {
806
- displayName: 'Input Data Field Name',
807
- name: 'binaryPropertyName',
808
- type: 'string',
809
- default: 'data',
810
- description: 'The name of the binary property which contains the data for the file to be uploaded',
811
- displayOptions: {
812
- show: {
813
- resource: ['pageInteraction'],
814
- operation: ['browserHttpRequest'],
815
- method: ['POST'],
816
- sendBody: [true],
817
- bodyContentType: ['binary'],
818
- },
819
- },
820
- },
821
- {
822
- displayName: 'Form Data',
823
- name: 'formData',
824
- type: 'fixedCollection',
825
- typeOptions: {
826
- multipleValues: true,
827
- },
828
- default: {},
829
- description: 'Form data to send',
830
- displayOptions: {
831
- show: {
832
- resource: ['pageInteraction'],
833
- operation: ['browserHttpRequest'],
834
- method: ['POST'],
835
- sendBody: [true],
836
- bodyContentType: ['formData'],
837
- },
838
- },
839
- options: [
840
- {
841
- displayName: 'Parameter',
842
- name: 'parameter',
843
- values: [
844
- {
845
- displayName: 'Parameter Type',
846
- name: 'parameterType',
847
- type: 'options',
848
- options: [
849
- {
850
- name: 'Form Data',
851
- value: 'formData',
852
- },
853
- {
854
- name: 'n8n Binary File',
855
- value: 'binary',
856
- },
857
- ],
858
- default: 'formData',
859
- description: 'Type of parameter',
860
- },
861
- {
862
- displayName: 'Name',
863
- name: 'name',
864
- type: 'string',
865
- default: '',
866
- displayOptions: {
867
- show: {
868
- parameterType: ['formData', 'binary'],
869
- },
870
- },
871
- },
872
- {
873
- displayName: 'Value',
874
- name: 'value',
875
- type: 'string',
876
- default: '',
877
- displayOptions: {
878
- show: {
879
- parameterType: ['formData'],
880
- },
881
- },
882
- },
883
- {
884
- displayName: 'Input Data Field Name',
885
- name: 'binaryPropertyName',
886
- type: 'string',
887
- default: 'data',
888
- description: 'The name of the binary property which contains the data for the file to be uploaded',
889
- displayOptions: {
890
- show: {
891
- parameterType: ['binary'],
892
- },
893
- },
894
- },
895
- ],
896
- },
897
- ],
898
- },
899
- {
900
- displayName: 'Query Parameters',
901
- name: 'queryParameters',
902
- type: 'fixedCollection',
903
- typeOptions: {
904
- multipleValues: true,
905
- },
906
- default: {},
907
- description: 'Query parameters to send',
908
- displayOptions: {
909
- show: {
910
- resource: ['pageInteraction'],
911
- operation: ['browserHttpRequest'],
912
- },
913
- },
914
- options: [
915
- {
916
- displayName: 'Parameter',
917
- name: 'parameter',
918
- values: [
919
- {
920
- displayName: 'Name',
921
- name: 'name',
922
- type: 'string',
923
- default: '',
924
- },
925
- {
926
- displayName: 'Value',
927
- name: 'value',
928
- type: 'string',
929
- default: '',
930
- },
931
- ],
932
- },
933
- ],
934
- },
935
- {
936
- displayName: 'Additional Headers',
937
- name: 'additionalHeaders',
938
- type: 'fixedCollection',
939
- typeOptions: {
940
- multipleValues: true,
941
- },
942
- default: {},
943
- description: 'Additional headers to send (will be merged with browser headers)',
944
- displayOptions: {
945
- show: {
946
- resource: ['pageInteraction'],
947
- operation: ['browserHttpRequest'],
948
- },
949
- },
950
- options: [
951
- {
952
- displayName: 'Header',
953
- name: 'header',
954
- values: [
955
- {
956
- displayName: 'Name',
957
- name: 'name',
958
- type: 'string',
959
- default: '',
960
- },
961
- {
962
- displayName: 'Value',
963
- name: 'value',
964
- type: 'string',
965
- default: '',
966
- },
967
- ],
968
- },
969
- ],
970
- },
971
- {
972
- displayName: 'Tab Index',
973
- name: 'tabIndex',
974
- type: 'number',
975
- default: 0,
976
- description: 'Index of the tab to get cookies and headers from (0 = first tab)',
977
- displayOptions: {
978
- show: {
979
- resource: ['pageInteraction'],
980
- operation: ['browserHttpRequest'],
981
- },
982
- },
983
- },
984
- {
985
- displayName: 'Auto Start Profile',
986
- name: 'autoStart',
987
- type: 'boolean',
988
- default: false,
989
- description: 'Automatically start the profile if it is not running',
990
113
  displayOptions: {
991
114
  show: {
992
115
  resource: ['pageInteraction'],
993
- operation: ['browserHttpRequest'],
994
116
  },
995
117
  },
996
118
  },
119
+ // Profile Management Fields
120
+ ...updateDisplayOptions(CreateProfile_description_1.createProfileFields, 'profileManagement', 'createProfile'),
121
+ ...updateDisplayOptions(DeleteProfile_description_1.deleteProfileFields, 'profileManagement', 'deleteProfile'),
122
+ ...updateDisplayOptions(StartProfile_description_1.startProfileFields, 'profileManagement', 'startProfile'),
123
+ ...updateDisplayOptions(StopProfile_description_1.stopProfileFields, 'profileManagement', 'stopProfile'),
124
+ // Page Interaction Fields
125
+ ...updateDisplayOptions(MoveAndClick_description_1.moveAndClickFields, 'pageInteraction', 'moveAndClick'),
126
+ ...updateDisplayOptions(RunJavaScript_description_1.runJavaScriptFields, 'pageInteraction', 'runJavaScript'),
127
+ ...updateDisplayOptions(GetNetworkResponse_description_1.getNetworkResponseFields, 'pageInteraction', 'getNetworkResponse'),
128
+ ...updateDisplayOptions(BrowserHttpRequest_description_1.browserHttpRequestFields, 'pageInteraction', 'browserHttpRequest'),
997
129
  ];
@@ -30,6 +30,7 @@ exports.NvkBrowser = void 0;
30
30
  const BrowserManager_1 = require("../../utils/BrowserManager");
31
31
  const ProfileManager_1 = require("../../utils/ProfileManager");
32
32
  const ExtensionHandler_1 = require("../../utils/ExtensionHandler");
33
+ const ProxyHandler_1 = require("../../utils/ProxyHandler");
33
34
  const NvkBrowser_description_1 = require("./NvkBrowser.description");
34
35
  const path = __importStar(require("path"));
35
36
  const fs = __importStar(require("fs"));
@@ -85,6 +86,9 @@ class NvkBrowser {
85
86
  case 'stopProfile':
86
87
  await executeStopProfile.call(this, i, browserManager, returnData);
87
88
  break;
89
+ case 'updateProfile':
90
+ await executeUpdateProfile.call(this, i, profileManager, returnData);
91
+ break;
88
92
  default:
89
93
  throw new Error(`Unknown operation: ${operation}`);
90
94
  }
@@ -412,6 +416,7 @@ async function executeStartProfile(i, browserManager, returnData) {
412
416
  const winPosition = this.getNodeParameter('winPosition', i);
413
417
  const winSize = this.getNodeParameter('winSize', i);
414
418
  const headless = this.getNodeParameter('headless', i);
419
+ const initialUrl = this.getNodeParameter('initialUrl', i);
415
420
  const windowConfig = {};
416
421
  if (winScale !== undefined) {
417
422
  windowConfig.scale = winScale;
@@ -432,12 +437,27 @@ async function executeStartProfile(i, browserManager, returnData) {
432
437
  windowConfig.headless = headless;
433
438
  }
434
439
  const instance = await browserManager.startProfile(profileId, windowConfig);
440
+ // Navigate to URL nếu có
441
+ if (initialUrl && initialUrl.trim() !== '') {
442
+ try {
443
+ const page = await browserManager.getPage(profileId, 0);
444
+ if (page) {
445
+ await page.goto(initialUrl.trim(), { waitUntil: 'networkidle2' });
446
+ console.log(`[NvkBrowser] Navigated to ${initialUrl}`);
447
+ }
448
+ }
449
+ catch (navError) {
450
+ console.error(`[NvkBrowser] Error navigating to ${initialUrl}:`, navError);
451
+ // Không throw error, chỉ log vì profile đã start thành công
452
+ }
453
+ }
435
454
  returnData.push({
436
455
  json: {
437
456
  success: true,
438
457
  profileId: instance.profileId,
439
458
  debugPort: instance.debugPort,
440
459
  message: 'Profile started successfully',
460
+ initialUrl: initialUrl && initialUrl.trim() !== '' ? initialUrl.trim() : undefined,
441
461
  },
442
462
  });
443
463
  }
@@ -452,6 +472,130 @@ async function executeStopProfile(i, browserManager, returnData) {
452
472
  },
453
473
  });
454
474
  }
475
+ async function executeUpdateProfile(i, profileManager, returnData) {
476
+ const profileId = this.getNodeParameter('profileId', i);
477
+ // Kiểm tra profile có tồn tại không
478
+ const existingProfile = profileManager.getProfile(profileId);
479
+ if (!existingProfile) {
480
+ throw new Error(`Profile with ID ${profileId} not found`);
481
+ }
482
+ // Lấy các giá trị cần cập nhật (chỉ lấy nếu có giá trị)
483
+ const updates = {};
484
+ const profileName = this.getNodeParameter('profileName', i);
485
+ if (profileName !== undefined && profileName !== '') {
486
+ updates.name = profileName;
487
+ }
488
+ const proxy = this.getNodeParameter('proxy', i);
489
+ if (proxy !== undefined && proxy !== '') {
490
+ updates.proxy = proxy;
491
+ }
492
+ else if (proxy === '') {
493
+ // Cho phép xóa proxy bằng cách truyền chuỗi rỗng
494
+ updates.proxy = undefined;
495
+ }
496
+ const note = this.getNodeParameter('note', i);
497
+ if (note !== undefined && note !== '') {
498
+ updates.note = note;
499
+ }
500
+ else if (note === '') {
501
+ // Cho phép xóa note bằng cách truyền chuỗi rỗng
502
+ updates.note = undefined;
503
+ }
504
+ const extensionsInput = this.getNodeParameter('extensions', i);
505
+ if (extensionsInput !== undefined && extensionsInput !== '') {
506
+ updates.extensions = ExtensionHandler_1.ExtensionHandler.parseExtensions(extensionsInput);
507
+ }
508
+ // Cập nhật profile
509
+ const updatedProfile = profileManager.updateProfile(profileId, updates);
510
+ if (!updatedProfile) {
511
+ throw new Error(`Failed to update profile ${profileId}`);
512
+ }
513
+ // Xử lý proxy authentication nếu có proxy mới
514
+ if (updates.proxy !== undefined && updates.proxy) {
515
+ console.log(`[NvkBrowser] Processing proxy: ${updates.proxy}`);
516
+ const proxyConfig = ProxyHandler_1.ProxyHandler.parseProxyString(updates.proxy);
517
+ if (proxyConfig) {
518
+ console.log(`[NvkBrowser] Parsed proxy config successfully:`, {
519
+ type: proxyConfig.type,
520
+ host: proxyConfig.host,
521
+ port: proxyConfig.port,
522
+ username: proxyConfig.username || 'N/A',
523
+ password: proxyConfig.password ? '***' : 'N/A',
524
+ });
525
+ const profilePath = profileManager.getProfilePath(profileId);
526
+ console.log(`[NvkBrowser] Profile path: ${profilePath}`);
527
+ console.log(`[NvkBrowser] Calling saveProxyAuthToProfile...`);
528
+ try {
529
+ ProxyHandler_1.ProxyHandler.saveProxyAuthToProfile(profilePath, proxyConfig);
530
+ console.log(`[NvkBrowser] saveProxyAuthToProfile completed successfully`);
531
+ }
532
+ catch (saveError) {
533
+ console.error(`[NvkBrowser] ERROR in saveProxyAuthToProfile:`, saveError);
534
+ throw new Error(`Failed to save proxy authentication: ${saveError instanceof Error ? saveError.message : String(saveError)}`);
535
+ }
536
+ // Validation: Đọc lại file Preferences để verify
537
+ const prefsPath = path.join(profilePath, 'Default', 'Preferences');
538
+ if (fs.existsSync(prefsPath)) {
539
+ try {
540
+ const verifyContent = fs.readFileSync(prefsPath, 'utf-8');
541
+ const verifyPrefs = JSON.parse(verifyContent);
542
+ // Verify proxy_config
543
+ if (!verifyPrefs.proxy_config || !verifyPrefs.proxy_config.server) {
544
+ console.error(`[NvkBrowser] VALIDATION FAILED: proxy_config not found in Preferences`);
545
+ }
546
+ else {
547
+ console.log(`[NvkBrowser] ✓ Validation passed: proxy_config.server = ${verifyPrefs.proxy_config.server}`);
548
+ }
549
+ // Verify gologin.proxy
550
+ if (!verifyPrefs.gologin || !verifyPrefs.gologin.proxy) {
551
+ console.error(`[NvkBrowser] VALIDATION FAILED: gologin.proxy not found in Preferences`);
552
+ }
553
+ else {
554
+ const hasUsername = !!verifyPrefs.gologin.proxy.username;
555
+ const hasPassword = !!verifyPrefs.gologin.proxy.password;
556
+ if (proxyConfig.username && !hasUsername) {
557
+ console.error(`[NvkBrowser] VALIDATION FAILED: username not saved in gologin.proxy`);
558
+ }
559
+ if (proxyConfig.password && !hasPassword) {
560
+ console.error(`[NvkBrowser] VALIDATION FAILED: password not saved in gologin.proxy`);
561
+ }
562
+ if ((!proxyConfig.username || hasUsername) && (!proxyConfig.password || hasPassword)) {
563
+ console.log(`[NvkBrowser] ✓ Validation passed: gologin.proxy has required fields`);
564
+ }
565
+ }
566
+ }
567
+ catch (verifyError) {
568
+ console.error(`[NvkBrowser] VALIDATION ERROR: Failed to verify Preferences file: ${verifyError instanceof Error ? verifyError.message : String(verifyError)}`);
569
+ }
570
+ }
571
+ else {
572
+ console.error(`[NvkBrowser] VALIDATION FAILED: Preferences file does not exist at ${prefsPath}`);
573
+ }
574
+ }
575
+ else {
576
+ console.error(`[NvkBrowser] ERROR: Failed to parse proxy string: ${updates.proxy}`);
577
+ }
578
+ }
579
+ else if (updates.proxy === undefined && existingProfile.proxy) {
580
+ // Nếu proxy bị xóa (undefined), cần xử lý xóa proxy config
581
+ console.log(`[NvkBrowser] Proxy removed, cleaning up proxy configuration`);
582
+ // Có thể cần thêm logic để xóa proxy config khỏi Preferences nếu cần
583
+ }
584
+ returnData.push({
585
+ json: {
586
+ success: true,
587
+ profile: {
588
+ id: updatedProfile.id,
589
+ name: updatedProfile.name,
590
+ proxy: updatedProfile.proxy,
591
+ note: updatedProfile.note,
592
+ extensions: updatedProfile.extensions,
593
+ createdAt: updatedProfile.createdAt,
594
+ updatedAt: updatedProfile.updatedAt,
595
+ },
596
+ },
597
+ });
598
+ }
455
599
  async function executeMoveAndClick(i, browserManager, returnData) {
456
600
  const profileId = this.getNodeParameter('profileId', i);
457
601
  const selector = this.getNodeParameter('selector', i);
@@ -988,10 +1132,11 @@ async function executeMoveAndClick(i, browserManager, returnData) {
988
1132
  if (waitForClick > 0) {
989
1133
  await page.waitForTimeout(waitForClick);
990
1134
  }
991
- await page.click(selectorTrimmed, {
1135
+ const clickOptions = {
992
1136
  button: button,
993
1137
  clickCount: clickCount,
994
- });
1138
+ };
1139
+ await page.click(selectorTrimmed, clickOptions);
995
1140
  }
996
1141
  }
997
1142
  }
@@ -1011,12 +1156,12 @@ async function executeMoveAndClick(i, browserManager, returnData) {
1011
1156
  action: actionType || 'click',
1012
1157
  };
1013
1158
  if (executedActionsInfo && executedActionsInfo.length > 0) {
1014
- const allSuccess = executedActionsInfo.every(a => a.success);
1159
+ const allSuccess = executedActionsInfo.every((a) => a.success);
1015
1160
  returnJson.success = allSuccess;
1016
1161
  returnJson.message = `Executed ${executedActionsInfo.length} action(s)`;
1017
1162
  returnJson.actions = executedActionsInfo;
1018
1163
  returnJson.totalActions = executedActionsInfo.length;
1019
- returnJson.successfulActions = executedActionsInfo.filter(a => a.success).length;
1164
+ returnJson.successfulActions = executedActionsInfo.filter((a) => a.success).length;
1020
1165
  }
1021
1166
  else {
1022
1167
  returnJson.message = actionType === 'fill' ? 'Fill performed successfully' : 'Click performed successfully';
@@ -1241,7 +1386,7 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
1241
1386
  throw new Error(`Could not get page for profile ${profileId}`);
1242
1387
  }
1243
1388
  const cookies = await page.cookies();
1244
- const cookieString = cookies.map(cookie => `${cookie.name}=${cookie.value}`).join('; ');
1389
+ const cookieString = cookies.map((cookie) => `${cookie.name}=${cookie.value}`).join('; ');
1245
1390
  const userAgent = await page.evaluate(() => navigator.userAgent);
1246
1391
  const browserHeaders = {
1247
1392
  'User-Agent': userAgent,
@@ -1327,7 +1472,7 @@ async function executeBrowserHttpRequest(i, browserManager, returnData) {
1327
1472
  else if (bodyContentType === 'formData') {
1328
1473
  const formDataParam = this.getNodeParameter('formData', i);
1329
1474
  if (formDataParam?.parameter) {
1330
- const hasBinary = formDataParam.parameter.some(p => p.parameterType === 'binary');
1475
+ const hasBinary = formDataParam.parameter.some((p) => p.parameterType === 'binary');
1331
1476
  if (hasBinary) {
1332
1477
  // Handle FormData with binary files
1333
1478
  const formDataItems = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-nvk-browser",
3
- "version": "1.0.113",
3
+ "version": "1.0.115",
4
4
  "description": "n8n nodes for managing Chrome browser profiles and page interactions with Puppeteer automation",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",