@pagecrawl/n8n-nodes-pagecrawl 0.3.2 → 0.3.5
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/nodes/PageCrawl/PageCrawl.node.js +79 -31
- package/dist/nodes/PageCrawl/descriptions/CheckDescription.js +9 -5
- package/dist/nodes/PageCrawl/descriptions/PageDescription.js +36 -20
- package/dist/nodes/PageCrawl/descriptions/ScreenshotDescription.js +9 -5
- package/dist/nodes/PageCrawlTrigger/PageCrawlTrigger.node.js +27 -5
- package/dist/package.json +70 -0
- package/package.json +2 -2
|
@@ -5,6 +5,8 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
5
5
|
const PageDescription_1 = require("./descriptions/PageDescription");
|
|
6
6
|
const CheckDescription_1 = require("./descriptions/CheckDescription");
|
|
7
7
|
const ScreenshotDescription_1 = require("./descriptions/ScreenshotDescription");
|
|
8
|
+
const package_json_1 = require("../../package.json");
|
|
9
|
+
const API_CLIENT_HEADER = { 'X-Api-Client': `n8n/${package_json_1.version}` };
|
|
8
10
|
class PageCrawl {
|
|
9
11
|
constructor() {
|
|
10
12
|
this.description = {
|
|
@@ -31,6 +33,7 @@ class PageCrawl {
|
|
|
31
33
|
headers: {
|
|
32
34
|
Accept: 'application/json',
|
|
33
35
|
'Content-Type': 'application/json',
|
|
36
|
+
...API_CLIENT_HEADER,
|
|
34
37
|
},
|
|
35
38
|
},
|
|
36
39
|
properties: [
|
|
@@ -62,9 +65,9 @@ class PageCrawl {
|
|
|
62
65
|
displayName: 'Workspace',
|
|
63
66
|
name: 'workspace',
|
|
64
67
|
type: 'resourceLocator',
|
|
65
|
-
required:
|
|
68
|
+
required: true,
|
|
66
69
|
default: { mode: 'list', value: '' },
|
|
67
|
-
description: 'Select workspace
|
|
70
|
+
description: 'Select workspace to use for this operation',
|
|
68
71
|
modes: [
|
|
69
72
|
{
|
|
70
73
|
displayName: 'From List',
|
|
@@ -99,6 +102,7 @@ class PageCrawl {
|
|
|
99
102
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
100
103
|
method: 'GET',
|
|
101
104
|
url: `${baseUrl}/api/user`,
|
|
105
|
+
headers: API_CLIENT_HEADER,
|
|
102
106
|
json: true,
|
|
103
107
|
});
|
|
104
108
|
// Get available locations from user account
|
|
@@ -156,6 +160,7 @@ class PageCrawl {
|
|
|
156
160
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
157
161
|
method: 'GET',
|
|
158
162
|
url: `${baseUrl}/api/user`,
|
|
163
|
+
headers: API_CLIENT_HEADER,
|
|
159
164
|
json: true,
|
|
160
165
|
});
|
|
161
166
|
// Get available frequencies from user account
|
|
@@ -177,6 +182,7 @@ class PageCrawl {
|
|
|
177
182
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
178
183
|
method: 'GET',
|
|
179
184
|
url: `${baseUrl}/api/user`,
|
|
185
|
+
headers: API_CLIENT_HEADER,
|
|
180
186
|
json: true,
|
|
181
187
|
});
|
|
182
188
|
// Get available devices from user account
|
|
@@ -215,6 +221,7 @@ class PageCrawl {
|
|
|
215
221
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
216
222
|
method: 'GET',
|
|
217
223
|
url: `${baseUrl}/api/workspaces/${workspaceId}/ai/available-models`,
|
|
224
|
+
headers: API_CLIENT_HEADER,
|
|
218
225
|
json: true,
|
|
219
226
|
});
|
|
220
227
|
// Get available AI models
|
|
@@ -239,9 +246,17 @@ class PageCrawl {
|
|
|
239
246
|
listSearch: {
|
|
240
247
|
async pageSearch(filter) {
|
|
241
248
|
const baseUrl = 'https://pagecrawl.io';
|
|
249
|
+
// Get workspace ID - return empty if not selected
|
|
250
|
+
const workspaceLocator = this.getNodeParameter('workspace', 0, {});
|
|
251
|
+
const workspaceId = workspaceLocator?.value || '';
|
|
252
|
+
if (!workspaceId) {
|
|
253
|
+
return { results: [] };
|
|
254
|
+
}
|
|
242
255
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
243
256
|
method: 'GET',
|
|
244
257
|
url: `${baseUrl}/api/pages`,
|
|
258
|
+
qs: { workspace_id: workspaceId },
|
|
259
|
+
headers: API_CLIENT_HEADER,
|
|
245
260
|
json: true,
|
|
246
261
|
});
|
|
247
262
|
const pages = response.data || response;
|
|
@@ -260,10 +275,18 @@ class PageCrawl {
|
|
|
260
275
|
},
|
|
261
276
|
async templateSearch(filter) {
|
|
262
277
|
const baseUrl = 'https://pagecrawl.io';
|
|
278
|
+
// Get workspace ID - return empty if not selected
|
|
279
|
+
const workspaceLocator = this.getNodeParameter('workspace', 0, {});
|
|
280
|
+
const workspaceId = workspaceLocator?.value || '';
|
|
281
|
+
if (!workspaceId) {
|
|
282
|
+
return { results: [] };
|
|
283
|
+
}
|
|
263
284
|
try {
|
|
264
285
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
265
286
|
method: 'GET',
|
|
266
287
|
url: `${baseUrl}/api/templates`,
|
|
288
|
+
qs: { workspace_id: workspaceId },
|
|
289
|
+
headers: API_CLIENT_HEADER,
|
|
267
290
|
json: true,
|
|
268
291
|
});
|
|
269
292
|
// Handle various response formats
|
|
@@ -292,6 +315,7 @@ class PageCrawl {
|
|
|
292
315
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
293
316
|
method: 'GET',
|
|
294
317
|
url: `${baseUrl}/api/user`,
|
|
318
|
+
headers: API_CLIENT_HEADER,
|
|
295
319
|
json: true,
|
|
296
320
|
});
|
|
297
321
|
// Extract workspaces from user response (may be nested under user)
|
|
@@ -316,11 +340,18 @@ class PageCrawl {
|
|
|
316
340
|
},
|
|
317
341
|
async folderSearch(filter) {
|
|
318
342
|
const baseUrl = 'https://pagecrawl.io';
|
|
343
|
+
// Get workspace ID - return empty if not selected
|
|
344
|
+
const workspaceLocator = this.getNodeParameter('workspace', 0, {});
|
|
345
|
+
const workspaceId = workspaceLocator?.value || '';
|
|
346
|
+
if (!workspaceId) {
|
|
347
|
+
return { results: [] };
|
|
348
|
+
}
|
|
319
349
|
try {
|
|
320
350
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
321
351
|
method: 'GET',
|
|
322
352
|
url: `${baseUrl}/api/folders`,
|
|
323
|
-
qs: { all: true },
|
|
353
|
+
qs: { all: true, workspace_id: workspaceId },
|
|
354
|
+
headers: API_CLIENT_HEADER,
|
|
324
355
|
json: true,
|
|
325
356
|
});
|
|
326
357
|
// Handle various response formats
|
|
@@ -355,10 +386,18 @@ class PageCrawl {
|
|
|
355
386
|
},
|
|
356
387
|
async authSearch(filter) {
|
|
357
388
|
const baseUrl = 'https://pagecrawl.io';
|
|
389
|
+
// Get workspace ID - return empty if not selected
|
|
390
|
+
const workspaceLocator = this.getNodeParameter('workspace', 0, {});
|
|
391
|
+
const workspaceId = workspaceLocator?.value || '';
|
|
392
|
+
if (!workspaceId) {
|
|
393
|
+
return { results: [] };
|
|
394
|
+
}
|
|
358
395
|
try {
|
|
359
396
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
360
397
|
method: 'GET',
|
|
361
398
|
url: `${baseUrl}/api/auths`,
|
|
399
|
+
qs: { workspace_id: workspaceId },
|
|
400
|
+
headers: API_CLIENT_HEADER,
|
|
362
401
|
json: true,
|
|
363
402
|
});
|
|
364
403
|
// Handle various response formats
|
|
@@ -404,27 +443,14 @@ class PageCrawl {
|
|
|
404
443
|
}
|
|
405
444
|
return [];
|
|
406
445
|
};
|
|
407
|
-
// Helper to get workspace ID
|
|
408
|
-
const getWorkspaceId =
|
|
446
|
+
// Helper to get workspace ID from the required workspace field
|
|
447
|
+
const getWorkspaceId = (index) => {
|
|
409
448
|
const workspaceLocator = this.getNodeParameter('workspace', index, {});
|
|
410
449
|
const workspaceId = workspaceLocator?.value || '';
|
|
411
|
-
if (workspaceId) {
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
// Fetch workspaces and auto-select if only one
|
|
415
|
-
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
416
|
-
method: 'GET',
|
|
417
|
-
url: `${baseUrl}/api/user`,
|
|
418
|
-
json: true,
|
|
419
|
-
});
|
|
420
|
-
const workspaces = response.workspaces || response.user?.workspaces || [];
|
|
421
|
-
if (workspaces.length === 1) {
|
|
422
|
-
return String(workspaces[0].id);
|
|
450
|
+
if (!workspaceId) {
|
|
451
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Workspace is required', { itemIndex: index });
|
|
423
452
|
}
|
|
424
|
-
|
|
425
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No workspaces found', { itemIndex: index });
|
|
426
|
-
}
|
|
427
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Please select a workspace - multiple workspaces available', { itemIndex: index });
|
|
453
|
+
return workspaceId;
|
|
428
454
|
};
|
|
429
455
|
for (let i = 0; i < items.length; i++) {
|
|
430
456
|
const resource = this.getNodeParameter('resource', i);
|
|
@@ -435,8 +461,9 @@ class PageCrawl {
|
|
|
435
461
|
if (resource === 'page') {
|
|
436
462
|
if (operation === 'get') {
|
|
437
463
|
const pageId = getPageId(i);
|
|
464
|
+
const workspaceId = getWorkspaceId(i);
|
|
438
465
|
const options = this.getNodeParameter('options', i);
|
|
439
|
-
const qs = {};
|
|
466
|
+
const qs = { workspace_id: workspaceId };
|
|
440
467
|
if (options.simple) {
|
|
441
468
|
qs.simple = 1;
|
|
442
469
|
}
|
|
@@ -447,14 +474,16 @@ class PageCrawl {
|
|
|
447
474
|
method: 'GET',
|
|
448
475
|
url: `${baseUrl}/api/pages/${pageId}`,
|
|
449
476
|
qs,
|
|
477
|
+
headers: API_CLIENT_HEADER,
|
|
450
478
|
json: true,
|
|
451
479
|
});
|
|
452
480
|
}
|
|
453
481
|
else if (operation === 'createSimple') {
|
|
454
482
|
const url = this.getNodeParameter('url', i);
|
|
455
483
|
const name = this.getNodeParameter('name', i, '');
|
|
484
|
+
const workspaceId = getWorkspaceId(i);
|
|
456
485
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
457
|
-
const body = { url };
|
|
486
|
+
const body = { url, workspace_id: workspaceId };
|
|
458
487
|
if (name) {
|
|
459
488
|
body.name = name;
|
|
460
489
|
}
|
|
@@ -471,6 +500,7 @@ class PageCrawl {
|
|
|
471
500
|
method: 'POST',
|
|
472
501
|
url: `${baseUrl}/api/track-simple`,
|
|
473
502
|
body,
|
|
503
|
+
headers: API_CLIENT_HEADER,
|
|
474
504
|
json: true,
|
|
475
505
|
});
|
|
476
506
|
}
|
|
@@ -533,9 +563,9 @@ class PageCrawl {
|
|
|
533
563
|
delete body.template_id;
|
|
534
564
|
if (!body.auth_id || body.auth_id === 0)
|
|
535
565
|
delete body.auth_id;
|
|
536
|
-
//
|
|
566
|
+
// Use selected workspace
|
|
537
567
|
if (!body.workspace_id) {
|
|
538
|
-
body.workspace_id =
|
|
568
|
+
body.workspace_id = getWorkspaceId(i);
|
|
539
569
|
}
|
|
540
570
|
// Transform fixedCollection fields to arrays
|
|
541
571
|
if (body.actions && typeof body.actions === 'object') {
|
|
@@ -576,14 +606,17 @@ class PageCrawl {
|
|
|
576
606
|
method: 'POST',
|
|
577
607
|
url: `${baseUrl}/api/pages`,
|
|
578
608
|
body,
|
|
609
|
+
headers: API_CLIENT_HEADER,
|
|
579
610
|
json: true,
|
|
580
611
|
});
|
|
581
612
|
}
|
|
582
613
|
else if (operation === 'update') {
|
|
583
614
|
const pageId = getPageId(i);
|
|
615
|
+
const workspaceId = getWorkspaceId(i);
|
|
584
616
|
const updateFields = this.getNodeParameter('updateFields', i);
|
|
585
617
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
586
618
|
const body = { ...updateFields, ...additionalFields };
|
|
619
|
+
const qs = { workspace_id: workspaceId };
|
|
587
620
|
// Convert tags from comma-separated string to array
|
|
588
621
|
if (typeof body.tags === 'string' && body.tags) {
|
|
589
622
|
body.tags = body.tags.split(',').map((tag) => tag.trim()).filter(Boolean);
|
|
@@ -657,23 +690,29 @@ class PageCrawl {
|
|
|
657
690
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
658
691
|
method: 'PUT',
|
|
659
692
|
url: `${baseUrl}/api/pages/${pageId}`,
|
|
693
|
+
qs,
|
|
660
694
|
body,
|
|
695
|
+
headers: API_CLIENT_HEADER,
|
|
661
696
|
json: true,
|
|
662
697
|
});
|
|
663
698
|
}
|
|
664
699
|
else if (operation === 'delete') {
|
|
665
700
|
const pageId = getPageId(i);
|
|
701
|
+
const workspaceId = getWorkspaceId(i);
|
|
666
702
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
667
703
|
method: 'DELETE',
|
|
668
704
|
url: `${baseUrl}/api/pages/${pageId}`,
|
|
705
|
+
qs: { workspace_id: workspaceId },
|
|
706
|
+
headers: API_CLIENT_HEADER,
|
|
669
707
|
json: true,
|
|
670
708
|
});
|
|
671
709
|
responseData = { success: true, deleted: pageId };
|
|
672
710
|
}
|
|
673
711
|
else if (operation === 'runCheckNow') {
|
|
674
712
|
const pageId = getPageId(i);
|
|
713
|
+
const workspaceId = getWorkspaceId(i);
|
|
675
714
|
const options = this.getNodeParameter('runCheckOptions', i);
|
|
676
|
-
const qs = {};
|
|
715
|
+
const qs = { workspace_id: workspaceId };
|
|
677
716
|
if (options.skip_first_notification) {
|
|
678
717
|
qs.skip_first_notification = 1;
|
|
679
718
|
}
|
|
@@ -681,6 +720,7 @@ class PageCrawl {
|
|
|
681
720
|
method: 'PUT',
|
|
682
721
|
url: `${baseUrl}/api/pages/${pageId}/check`,
|
|
683
722
|
qs,
|
|
723
|
+
headers: API_CLIENT_HEADER,
|
|
684
724
|
json: true,
|
|
685
725
|
});
|
|
686
726
|
responseData = { success: true, message: 'Check triggered', pageId };
|
|
@@ -688,20 +728,20 @@ class PageCrawl {
|
|
|
688
728
|
}
|
|
689
729
|
else if (resource === 'check') {
|
|
690
730
|
const pageId = getPageId(i);
|
|
731
|
+
const workspaceId = getWorkspaceId(i);
|
|
691
732
|
if (operation === 'getHistory') {
|
|
692
733
|
const options = this.getNodeParameter('options', i);
|
|
693
|
-
const qs = {};
|
|
734
|
+
const qs = { workspace_id: workspaceId };
|
|
694
735
|
// Default to simple mode unless advanced is enabled
|
|
695
736
|
if (!options.advanced) {
|
|
696
737
|
qs.simple = 1;
|
|
697
738
|
}
|
|
698
|
-
|
|
699
|
-
qs.take = options.take;
|
|
700
|
-
}
|
|
739
|
+
qs.take = options.take ?? 2;
|
|
701
740
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
702
741
|
method: 'GET',
|
|
703
742
|
url: `${baseUrl}/api/pages/${pageId}/history`,
|
|
704
743
|
qs,
|
|
744
|
+
headers: API_CLIENT_HEADER,
|
|
705
745
|
json: true,
|
|
706
746
|
});
|
|
707
747
|
}
|
|
@@ -710,6 +750,8 @@ class PageCrawl {
|
|
|
710
750
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
711
751
|
method: 'GET',
|
|
712
752
|
url: `${baseUrl}/api/pages/${pageId}/checks/${checkId}/diff.png`,
|
|
753
|
+
qs: { workspace_id: workspaceId },
|
|
754
|
+
headers: API_CLIENT_HEADER,
|
|
713
755
|
encoding: 'arraybuffer',
|
|
714
756
|
});
|
|
715
757
|
const binaryData = await this.helpers.prepareBinaryData(response, `diff-${pageId}-${checkId}.png`, 'image/png');
|
|
@@ -722,7 +764,9 @@ class PageCrawl {
|
|
|
722
764
|
const htmlContent = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
723
765
|
method: 'GET',
|
|
724
766
|
url: `${baseUrl}/api/pages/${pageId}/checks/${checkId}/diff.html`,
|
|
767
|
+
qs: { workspace_id: workspaceId },
|
|
725
768
|
headers: {
|
|
769
|
+
...API_CLIENT_HEADER,
|
|
726
770
|
Accept: 'text/html',
|
|
727
771
|
},
|
|
728
772
|
});
|
|
@@ -737,7 +781,9 @@ class PageCrawl {
|
|
|
737
781
|
const markdownContent = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
738
782
|
method: 'GET',
|
|
739
783
|
url: `${baseUrl}/api/pages/${pageId}/checks/${checkId}/diff.markdown`,
|
|
784
|
+
qs: { workspace_id: workspaceId },
|
|
740
785
|
headers: {
|
|
786
|
+
...API_CLIENT_HEADER,
|
|
741
787
|
Accept: 'text/markdown',
|
|
742
788
|
},
|
|
743
789
|
});
|
|
@@ -750,6 +796,7 @@ class PageCrawl {
|
|
|
750
796
|
}
|
|
751
797
|
else if (resource === 'screenshot') {
|
|
752
798
|
const pageId = getPageId(i);
|
|
799
|
+
const workspaceId = getWorkspaceId(i);
|
|
753
800
|
const checkId = this.getNodeParameter('checkId', i, 'latest');
|
|
754
801
|
let endpoint = '';
|
|
755
802
|
if (operation === 'getScreenshot') {
|
|
@@ -759,7 +806,7 @@ class PageCrawl {
|
|
|
759
806
|
endpoint = `/pages/${pageId}/checks/${checkId}/diff`;
|
|
760
807
|
}
|
|
761
808
|
const previous = operation === 'getScreenshot' ? this.getNodeParameter('previous', i, false) : false;
|
|
762
|
-
const qs = {};
|
|
809
|
+
const qs = { workspace_id: workspaceId };
|
|
763
810
|
if (previous) {
|
|
764
811
|
qs.previous = 1;
|
|
765
812
|
}
|
|
@@ -767,6 +814,7 @@ class PageCrawl {
|
|
|
767
814
|
method: 'GET',
|
|
768
815
|
url: `${baseUrl}/api${endpoint}`,
|
|
769
816
|
qs,
|
|
817
|
+
headers: API_CLIENT_HEADER,
|
|
770
818
|
encoding: 'arraybuffer',
|
|
771
819
|
});
|
|
772
820
|
const binaryData = await this.helpers.prepareBinaryData(response, `screenshot-${pageId}.png`, 'image/png');
|
|
@@ -68,16 +68,20 @@ exports.checkFields = [
|
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
|
-
displayName: 'By
|
|
72
|
-
name: '
|
|
71
|
+
displayName: 'By URL',
|
|
72
|
+
name: 'url',
|
|
73
73
|
type: 'string',
|
|
74
|
-
placeholder: 'e.g.
|
|
74
|
+
placeholder: 'e.g. https://pagecrawl.io/app/pages/example-domain',
|
|
75
|
+
extractValue: {
|
|
76
|
+
type: 'regex',
|
|
77
|
+
regex: 'https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/([a-z0-9_-]+)',
|
|
78
|
+
},
|
|
75
79
|
validation: [
|
|
76
80
|
{
|
|
77
81
|
type: 'regex',
|
|
78
82
|
properties: {
|
|
79
|
-
regex: '^[a-z0-
|
|
80
|
-
errorMessage: '
|
|
83
|
+
regex: '^https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/[a-z0-9_-]+$',
|
|
84
|
+
errorMessage: 'Must be a valid PageCrawl page URL (e.g. https://pagecrawl.io/app/pages/my-page)',
|
|
81
85
|
},
|
|
82
86
|
},
|
|
83
87
|
],
|
|
@@ -28,10 +28,10 @@ exports.pageOperations = [
|
|
|
28
28
|
action: 'Create an advanced page',
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
|
-
name: '
|
|
32
|
-
value: '
|
|
33
|
-
description: '
|
|
34
|
-
action: '
|
|
31
|
+
name: 'Run Check Now',
|
|
32
|
+
value: 'runCheckNow',
|
|
33
|
+
description: 'Trigger an immediate check for a page',
|
|
34
|
+
action: 'Run check now',
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
name: 'Get',
|
|
@@ -39,18 +39,18 @@ exports.pageOperations = [
|
|
|
39
39
|
description: 'Get a tracked page configuration',
|
|
40
40
|
action: 'Get a page',
|
|
41
41
|
},
|
|
42
|
-
{
|
|
43
|
-
name: 'Run Check Now',
|
|
44
|
-
value: 'runCheckNow',
|
|
45
|
-
description: 'Trigger an immediate check for a page',
|
|
46
|
-
action: 'Run check now',
|
|
47
|
-
},
|
|
48
42
|
{
|
|
49
43
|
name: 'Update',
|
|
50
44
|
value: 'update',
|
|
51
45
|
description: 'Update a tracked page',
|
|
52
46
|
action: 'Update a page',
|
|
53
47
|
},
|
|
48
|
+
{
|
|
49
|
+
name: 'Delete',
|
|
50
|
+
value: 'delete',
|
|
51
|
+
description: 'Delete a tracked page',
|
|
52
|
+
action: 'Delete a page',
|
|
53
|
+
},
|
|
54
54
|
],
|
|
55
55
|
default: 'get',
|
|
56
56
|
},
|
|
@@ -83,16 +83,20 @@ exports.pageFields = [
|
|
|
83
83
|
},
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
|
-
displayName: 'By
|
|
87
|
-
name: '
|
|
86
|
+
displayName: 'By URL',
|
|
87
|
+
name: 'url',
|
|
88
88
|
type: 'string',
|
|
89
|
-
placeholder: 'e.g.
|
|
89
|
+
placeholder: 'e.g. https://pagecrawl.io/app/pages/example-domain',
|
|
90
|
+
extractValue: {
|
|
91
|
+
type: 'regex',
|
|
92
|
+
regex: 'https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/([a-z0-9_-]+)',
|
|
93
|
+
},
|
|
90
94
|
validation: [
|
|
91
95
|
{
|
|
92
96
|
type: 'regex',
|
|
93
97
|
properties: {
|
|
94
|
-
regex: '^[a-z0-
|
|
95
|
-
errorMessage: '
|
|
98
|
+
regex: '^https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/[a-z0-9_-]+$',
|
|
99
|
+
errorMessage: 'Must be a valid PageCrawl page URL (e.g. https://pagecrawl.io/app/pages/my-page)',
|
|
96
100
|
},
|
|
97
101
|
},
|
|
98
102
|
],
|
|
@@ -183,6 +187,19 @@ exports.pageFields = [
|
|
|
183
187
|
placeholder: 'https://example.com',
|
|
184
188
|
description: 'The URL to track',
|
|
185
189
|
},
|
|
190
|
+
{
|
|
191
|
+
displayName: 'Title',
|
|
192
|
+
name: 'name',
|
|
193
|
+
type: 'string',
|
|
194
|
+
displayOptions: {
|
|
195
|
+
show: {
|
|
196
|
+
resource: ['page'],
|
|
197
|
+
operation: ['createSimple'],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
default: '',
|
|
201
|
+
description: 'Optional title for this page (defaults to page title if empty)',
|
|
202
|
+
},
|
|
186
203
|
{
|
|
187
204
|
displayName: 'Tracking Type',
|
|
188
205
|
name: 'trackingType',
|
|
@@ -355,10 +372,9 @@ exports.pageFields = [
|
|
|
355
372
|
description: 'The URL to track',
|
|
356
373
|
},
|
|
357
374
|
{
|
|
358
|
-
displayName: '
|
|
375
|
+
displayName: 'Title',
|
|
359
376
|
name: 'name',
|
|
360
377
|
type: 'string',
|
|
361
|
-
required: true,
|
|
362
378
|
displayOptions: {
|
|
363
379
|
show: {
|
|
364
380
|
resource: ['page'],
|
|
@@ -366,7 +382,7 @@ exports.pageFields = [
|
|
|
366
382
|
},
|
|
367
383
|
},
|
|
368
384
|
default: '',
|
|
369
|
-
description: '
|
|
385
|
+
description: 'Optional title for this page (defaults to page title if empty)',
|
|
370
386
|
},
|
|
371
387
|
{
|
|
372
388
|
displayName: 'Tracked Elements',
|
|
@@ -1094,11 +1110,11 @@ exports.pageFields = [
|
|
|
1094
1110
|
description: 'How often to check for changes',
|
|
1095
1111
|
},
|
|
1096
1112
|
{
|
|
1097
|
-
displayName: '
|
|
1113
|
+
displayName: 'Title',
|
|
1098
1114
|
name: 'name',
|
|
1099
1115
|
type: 'string',
|
|
1100
1116
|
default: '',
|
|
1101
|
-
description: '
|
|
1117
|
+
description: 'Title for this page',
|
|
1102
1118
|
},
|
|
1103
1119
|
{
|
|
1104
1120
|
displayName: 'URL',
|
|
@@ -56,16 +56,20 @@ exports.screenshotFields = [
|
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
|
-
displayName: 'By
|
|
60
|
-
name: '
|
|
59
|
+
displayName: 'By URL',
|
|
60
|
+
name: 'url',
|
|
61
61
|
type: 'string',
|
|
62
|
-
placeholder: 'e.g.
|
|
62
|
+
placeholder: 'e.g. https://pagecrawl.io/app/pages/example-domain',
|
|
63
|
+
extractValue: {
|
|
64
|
+
type: 'regex',
|
|
65
|
+
regex: 'https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/([a-z0-9_-]+)',
|
|
66
|
+
},
|
|
63
67
|
validation: [
|
|
64
68
|
{
|
|
65
69
|
type: 'regex',
|
|
66
70
|
properties: {
|
|
67
|
-
regex: '^[a-z0-
|
|
68
|
-
errorMessage: '
|
|
71
|
+
regex: '^https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/[a-z0-9_-]+$',
|
|
72
|
+
errorMessage: 'Must be a valid PageCrawl page URL (e.g. https://pagecrawl.io/app/pages/my-page)',
|
|
69
73
|
},
|
|
70
74
|
},
|
|
71
75
|
],
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PageCrawlTrigger = void 0;
|
|
4
4
|
const types_1 = require("../PageCrawl/types");
|
|
5
|
+
const package_json_1 = require("../../package.json");
|
|
6
|
+
const API_CLIENT_HEADER = { 'X-Api-Client': `n8n/${package_json_1.version}` };
|
|
5
7
|
class PageCrawlTrigger {
|
|
6
8
|
constructor() {
|
|
7
9
|
this.description = {
|
|
@@ -74,16 +76,20 @@ class PageCrawlTrigger {
|
|
|
74
76
|
},
|
|
75
77
|
},
|
|
76
78
|
{
|
|
77
|
-
displayName: 'By
|
|
78
|
-
name: '
|
|
79
|
+
displayName: 'By URL',
|
|
80
|
+
name: 'url',
|
|
79
81
|
type: 'string',
|
|
80
|
-
placeholder: 'e.g.
|
|
82
|
+
placeholder: 'e.g. https://pagecrawl.io/app/pages/example-domain',
|
|
83
|
+
extractValue: {
|
|
84
|
+
type: 'regex',
|
|
85
|
+
regex: 'https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/([a-z0-9_-]+)',
|
|
86
|
+
},
|
|
81
87
|
validation: [
|
|
82
88
|
{
|
|
83
89
|
type: 'regex',
|
|
84
90
|
properties: {
|
|
85
|
-
regex: '^[a-z0-
|
|
86
|
-
errorMessage: '
|
|
91
|
+
regex: '^https:\\/\\/pagecrawl\\.io\\/app\\/pages\\/[a-z0-9_-]+$',
|
|
92
|
+
errorMessage: 'Must be a valid PageCrawl page URL (e.g. https://pagecrawl.io/app/pages/my-page)',
|
|
87
93
|
},
|
|
88
94
|
},
|
|
89
95
|
],
|
|
@@ -146,6 +152,7 @@ class PageCrawlTrigger {
|
|
|
146
152
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
147
153
|
method: 'GET',
|
|
148
154
|
url: `${baseUrl}/api/user`,
|
|
155
|
+
headers: API_CLIENT_HEADER,
|
|
149
156
|
json: true,
|
|
150
157
|
});
|
|
151
158
|
// Extract workspaces from user response (may be nested under user)
|
|
@@ -169,9 +176,17 @@ class PageCrawlTrigger {
|
|
|
169
176
|
},
|
|
170
177
|
async pageSearch(filter) {
|
|
171
178
|
const baseUrl = 'https://pagecrawl.io';
|
|
179
|
+
// Get workspace ID - return empty if not selected
|
|
180
|
+
const workspaceLocator = this.getNodeParameter('workspace', 0, {});
|
|
181
|
+
const workspaceId = workspaceLocator?.value || '';
|
|
182
|
+
if (!workspaceId) {
|
|
183
|
+
return { results: [] };
|
|
184
|
+
}
|
|
172
185
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
173
186
|
method: 'GET',
|
|
174
187
|
url: `${baseUrl}/api/pages`,
|
|
188
|
+
qs: { workspace_id: workspaceId },
|
|
189
|
+
headers: API_CLIENT_HEADER,
|
|
175
190
|
json: true,
|
|
176
191
|
});
|
|
177
192
|
const pages = response.data || response;
|
|
@@ -196,6 +211,8 @@ class PageCrawlTrigger {
|
|
|
196
211
|
const webhookData = this.getWorkflowStaticData('node');
|
|
197
212
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
198
213
|
const baseUrl = 'https://pagecrawl.io';
|
|
214
|
+
const workspaceLocator = this.getNodeParameter('workspace', { mode: 'list', value: '' });
|
|
215
|
+
const workspaceId = workspaceLocator.value || '';
|
|
199
216
|
if (!webhookData.webhookId) {
|
|
200
217
|
return false;
|
|
201
218
|
}
|
|
@@ -203,6 +220,8 @@ class PageCrawlTrigger {
|
|
|
203
220
|
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
204
221
|
method: 'GET',
|
|
205
222
|
url: `${baseUrl}/api/hooks`,
|
|
223
|
+
qs: workspaceId ? { workspace_id: workspaceId } : {},
|
|
224
|
+
headers: API_CLIENT_HEADER,
|
|
206
225
|
json: true,
|
|
207
226
|
});
|
|
208
227
|
const existingWebhook = response.find((webhook) => webhook.id === webhookData.webhookId);
|
|
@@ -254,6 +273,7 @@ class PageCrawlTrigger {
|
|
|
254
273
|
method: 'POST',
|
|
255
274
|
url: `${baseUrl}/api/hooks`,
|
|
256
275
|
body,
|
|
276
|
+
headers: API_CLIENT_HEADER,
|
|
257
277
|
json: true,
|
|
258
278
|
});
|
|
259
279
|
if (!response.id) {
|
|
@@ -266,6 +286,7 @@ class PageCrawlTrigger {
|
|
|
266
286
|
await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
267
287
|
method: 'PUT',
|
|
268
288
|
url: `${baseUrl}/api/hooks/${response.id}/test`,
|
|
289
|
+
headers: API_CLIENT_HEADER,
|
|
269
290
|
json: true,
|
|
270
291
|
});
|
|
271
292
|
}
|
|
@@ -291,6 +312,7 @@ class PageCrawlTrigger {
|
|
|
291
312
|
await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
292
313
|
method: 'DELETE',
|
|
293
314
|
url: `${baseUrl}/api/hooks/${webhookData.webhookId}`,
|
|
315
|
+
headers: API_CLIENT_HEADER,
|
|
294
316
|
json: true,
|
|
295
317
|
});
|
|
296
318
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pagecrawl/n8n-nodes-pagecrawl",
|
|
3
|
+
"version": "0.3.4",
|
|
4
|
+
"description": "n8n node for PageCrawl.io - Website monitoring and change detection",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n",
|
|
7
|
+
"n8n-community-node-package",
|
|
8
|
+
"website-monitoring",
|
|
9
|
+
"change-detection",
|
|
10
|
+
"web-scraping",
|
|
11
|
+
"pagecrawl",
|
|
12
|
+
"automation"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://pagecrawl.io",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "PageCrawl.io",
|
|
18
|
+
"email": "support@pagecrawl.io"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/pagecrawl/n8n-nodes-pagecrawl.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/pagecrawl/n8n-nodes-pagecrawl/issues"
|
|
26
|
+
},
|
|
27
|
+
"main": "index.js",
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsc && cp nodes/PageCrawl/pagecrawl.svg dist/nodes/PageCrawl/ && cp nodes/PageCrawlTrigger/pagecrawl.svg dist/nodes/PageCrawlTrigger/",
|
|
30
|
+
"dev": "npm run build && npx n8n start",
|
|
31
|
+
"dev:build": "npm run build",
|
|
32
|
+
"n8n:start": "npx n8n start",
|
|
33
|
+
"lint": "eslint nodes credentials --ext .ts",
|
|
34
|
+
"lint:fix": "eslint nodes credentials --ext .ts --fix",
|
|
35
|
+
"link": "npm run build && npm link",
|
|
36
|
+
"test": "jest --testPathIgnorePatterns=integration",
|
|
37
|
+
"test:integration": "jest --testPathPattern=integration --testTimeout=60000"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
42
|
+
"n8n": {
|
|
43
|
+
"n8nNodesApiVersion": 1,
|
|
44
|
+
"credentials": [
|
|
45
|
+
"dist/credentials/PageCrawlApi.credentials.js"
|
|
46
|
+
],
|
|
47
|
+
"nodes": [
|
|
48
|
+
"dist/nodes/PageCrawl/PageCrawl.node.js",
|
|
49
|
+
"dist/nodes/PageCrawlTrigger/PageCrawlTrigger.node.js"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
56
|
+
"@typescript-eslint/parser": "^7.0.0",
|
|
57
|
+
"axios": "^1.6.0",
|
|
58
|
+
"dotenv": "^17.2.3",
|
|
59
|
+
"eslint": "^8.56.0",
|
|
60
|
+
"eslint-plugin-n8n-nodes-base": "^1.16.0",
|
|
61
|
+
"jest": "^29.7.0",
|
|
62
|
+
"n8n": "^2.2.0",
|
|
63
|
+
"n8n-workflow": "^2.2.2",
|
|
64
|
+
"ts-jest": "^29.4.6",
|
|
65
|
+
"typescript": "^5.0.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
68
|
+
"n8n-workflow": ">=1.0.0"
|
|
69
|
+
}
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagecrawl/n8n-nodes-pagecrawl",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"description": "n8n node for PageCrawl.io - Website monitoring and change detection",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"eslint-plugin-n8n-nodes-base": "^1.16.0",
|
|
61
61
|
"jest": "^29.7.0",
|
|
62
62
|
"n8n": "^2.2.0",
|
|
63
|
-
"n8n-workflow": "
|
|
63
|
+
"n8n-workflow": "^2.2.2",
|
|
64
64
|
"ts-jest": "^29.4.6",
|
|
65
65
|
"typescript": "^5.0.0"
|
|
66
66
|
},
|