@pagecrawl/n8n-nodes-pagecrawl 0.1.1 → 0.1.2
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/credentials/PageCrawlApi.credentials.js +2 -20
- package/dist/nodes/PageCrawl/PageCrawl.node.d.ts +6 -1
- package/dist/nodes/PageCrawl/PageCrawl.node.js +38 -9
- package/dist/nodes/PageCrawl/descriptions/CheckDescription.js +45 -4
- package/dist/nodes/PageCrawl/descriptions/PageDescription.js +134 -17
- package/dist/nodes/PageCrawl/descriptions/ScreenshotDescription.js +45 -4
- package/dist/nodes/PageCrawl/types.js +0 -1
- package/dist/nodes/PageCrawlTrigger/PageCrawlTrigger.node.d.ts +6 -1
- package/dist/nodes/PageCrawlTrigger/PageCrawlTrigger.node.js +78 -14
- package/package.json +1 -1
|
@@ -16,15 +16,7 @@ class PageCrawlApi {
|
|
|
16
16
|
},
|
|
17
17
|
default: '',
|
|
18
18
|
required: true,
|
|
19
|
-
description: 'Your PageCrawl.io API token. API access requires a paid plan.
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
displayName: 'Base URL',
|
|
23
|
-
name: 'baseUrl',
|
|
24
|
-
type: 'string',
|
|
25
|
-
default: 'https://pagecrawl.io',
|
|
26
|
-
description: 'The base URL for the PageCrawl.io API',
|
|
27
|
-
hint: 'Use https://pagecrawl.io for production',
|
|
19
|
+
description: 'Your PageCrawl.io API token. API access requires a paid plan. Find your token at Settings > API.',
|
|
28
20
|
},
|
|
29
21
|
];
|
|
30
22
|
this.authenticate = {
|
|
@@ -37,20 +29,10 @@ class PageCrawlApi {
|
|
|
37
29
|
};
|
|
38
30
|
this.test = {
|
|
39
31
|
request: {
|
|
40
|
-
baseURL: '
|
|
32
|
+
baseURL: 'https://pagecrawl.io',
|
|
41
33
|
url: '/api/user',
|
|
42
34
|
method: 'GET',
|
|
43
35
|
},
|
|
44
|
-
rules: [
|
|
45
|
-
{
|
|
46
|
-
type: 'responseSuccessBody',
|
|
47
|
-
properties: {
|
|
48
|
-
key: 'id',
|
|
49
|
-
value: undefined,
|
|
50
|
-
message: 'Authentication successful',
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
],
|
|
54
36
|
};
|
|
55
37
|
}
|
|
56
38
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow';
|
|
2
2
|
export declare class PageCrawl implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
listSearch: {
|
|
6
|
+
pageSearch(this: ILoadOptionsFunctions, filter?: string): Promise<INodeListSearchResult>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
4
9
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
10
|
}
|
|
@@ -28,7 +28,7 @@ class PageCrawl {
|
|
|
28
28
|
},
|
|
29
29
|
],
|
|
30
30
|
requestDefaults: {
|
|
31
|
-
baseURL: '
|
|
31
|
+
baseURL: 'https://pagecrawl.io/api',
|
|
32
32
|
headers: {
|
|
33
33
|
Accept: 'application/json',
|
|
34
34
|
'Content-Type': 'application/json',
|
|
@@ -74,12 +74,41 @@ class PageCrawl {
|
|
|
74
74
|
...WebhookDescription_1.webhookFields,
|
|
75
75
|
],
|
|
76
76
|
};
|
|
77
|
+
this.methods = {
|
|
78
|
+
listSearch: {
|
|
79
|
+
async pageSearch(filter) {
|
|
80
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
81
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
82
|
+
method: 'GET',
|
|
83
|
+
url: `${baseUrl}/api/pages`,
|
|
84
|
+
json: true,
|
|
85
|
+
});
|
|
86
|
+
const pages = response.data || response;
|
|
87
|
+
let results = pages.map((page) => ({
|
|
88
|
+
name: page.name || page.url,
|
|
89
|
+
value: page.slug,
|
|
90
|
+
url: `https://pagecrawl.io/app/pages/${page.slug}`,
|
|
91
|
+
}));
|
|
92
|
+
// Filter results if search term provided
|
|
93
|
+
if (filter) {
|
|
94
|
+
const filterLower = filter.toLowerCase();
|
|
95
|
+
results = results.filter((page) => page.name.toLowerCase().includes(filterLower) ||
|
|
96
|
+
page.value.toLowerCase().includes(filterLower));
|
|
97
|
+
}
|
|
98
|
+
return { results };
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
77
102
|
}
|
|
78
103
|
async execute() {
|
|
79
104
|
const items = this.getInputData();
|
|
80
105
|
const returnData = [];
|
|
81
|
-
const
|
|
82
|
-
|
|
106
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
107
|
+
// Helper to extract value from resourceLocator
|
|
108
|
+
const getPageId = (index) => {
|
|
109
|
+
const pageLocator = this.getNodeParameter('pageId', index);
|
|
110
|
+
return pageLocator.value || '';
|
|
111
|
+
};
|
|
83
112
|
for (let i = 0; i < items.length; i++) {
|
|
84
113
|
const resource = this.getNodeParameter('resource', i);
|
|
85
114
|
const operation = this.getNodeParameter('operation', i);
|
|
@@ -115,7 +144,7 @@ class PageCrawl {
|
|
|
115
144
|
}
|
|
116
145
|
}
|
|
117
146
|
else if (operation === 'get') {
|
|
118
|
-
const pageId =
|
|
147
|
+
const pageId = getPageId(i);
|
|
119
148
|
const options = this.getNodeParameter('options', i);
|
|
120
149
|
const qs = {};
|
|
121
150
|
if (options.simple) {
|
|
@@ -209,7 +238,7 @@ class PageCrawl {
|
|
|
209
238
|
});
|
|
210
239
|
}
|
|
211
240
|
else if (operation === 'update') {
|
|
212
|
-
const pageId =
|
|
241
|
+
const pageId = getPageId(i);
|
|
213
242
|
const updateFields = this.getNodeParameter('updateFields', i);
|
|
214
243
|
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
215
244
|
const body = { ...updateFields, ...additionalFields };
|
|
@@ -265,7 +294,7 @@ class PageCrawl {
|
|
|
265
294
|
});
|
|
266
295
|
}
|
|
267
296
|
else if (operation === 'delete') {
|
|
268
|
-
const pageId =
|
|
297
|
+
const pageId = getPageId(i);
|
|
269
298
|
responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
270
299
|
method: 'DELETE',
|
|
271
300
|
url: `${baseUrl}/api/pages/${pageId}`,
|
|
@@ -274,7 +303,7 @@ class PageCrawl {
|
|
|
274
303
|
responseData = { success: true, deleted: pageId };
|
|
275
304
|
}
|
|
276
305
|
else if (operation === 'runCheckNow') {
|
|
277
|
-
const pageId =
|
|
306
|
+
const pageId = getPageId(i);
|
|
278
307
|
const options = this.getNodeParameter('runCheckOptions', i);
|
|
279
308
|
const qs = {};
|
|
280
309
|
if (options.skip_first_notification) {
|
|
@@ -290,7 +319,7 @@ class PageCrawl {
|
|
|
290
319
|
}
|
|
291
320
|
}
|
|
292
321
|
else if (resource === 'check') {
|
|
293
|
-
const pageId =
|
|
322
|
+
const pageId = getPageId(i);
|
|
294
323
|
if (operation === 'getHistory') {
|
|
295
324
|
const options = this.getNodeParameter('options', i);
|
|
296
325
|
const qs = {};
|
|
@@ -351,7 +380,7 @@ class PageCrawl {
|
|
|
351
380
|
}
|
|
352
381
|
}
|
|
353
382
|
else if (resource === 'screenshot') {
|
|
354
|
-
const pageId =
|
|
383
|
+
const pageId = getPageId(i);
|
|
355
384
|
let endpoint = '';
|
|
356
385
|
if (operation === 'getLatest') {
|
|
357
386
|
endpoint = `/pages/${pageId}/checks/latest/screenshot`;
|
|
@@ -46,17 +46,58 @@ exports.checkFields = [
|
|
|
46
46
|
// check:getHistory
|
|
47
47
|
// ========================================
|
|
48
48
|
{
|
|
49
|
-
displayName: 'Page
|
|
49
|
+
displayName: 'Page',
|
|
50
50
|
name: 'pageId',
|
|
51
|
-
type: '
|
|
51
|
+
type: 'resourceLocator',
|
|
52
52
|
required: true,
|
|
53
53
|
displayOptions: {
|
|
54
54
|
show: {
|
|
55
55
|
resource: ['check'],
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
|
-
default: '',
|
|
59
|
-
description: '
|
|
58
|
+
default: { mode: 'list', value: '' },
|
|
59
|
+
description: 'Select a page or enter slug/ID. <a href="https://pagecrawl.io/app/pages" target="_blank">View pages</a>.',
|
|
60
|
+
modes: [
|
|
61
|
+
{
|
|
62
|
+
displayName: 'From List',
|
|
63
|
+
name: 'list',
|
|
64
|
+
type: 'list',
|
|
65
|
+
typeOptions: {
|
|
66
|
+
searchListMethod: 'pageSearch',
|
|
67
|
+
searchable: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
displayName: 'By Slug',
|
|
72
|
+
name: 'slug',
|
|
73
|
+
type: 'string',
|
|
74
|
+
placeholder: 'e.g. my-page-name',
|
|
75
|
+
validation: [
|
|
76
|
+
{
|
|
77
|
+
type: 'regex',
|
|
78
|
+
properties: {
|
|
79
|
+
regex: '^[a-z0-9-]+$',
|
|
80
|
+
errorMessage: 'Slug must contain only lowercase letters, numbers, and hyphens',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
displayName: 'By ID',
|
|
87
|
+
name: 'id',
|
|
88
|
+
type: 'string',
|
|
89
|
+
placeholder: 'e.g. 12345',
|
|
90
|
+
validation: [
|
|
91
|
+
{
|
|
92
|
+
type: 'regex',
|
|
93
|
+
properties: {
|
|
94
|
+
regex: '^[0-9]+$',
|
|
95
|
+
errorMessage: 'ID must be a number',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
60
101
|
},
|
|
61
102
|
{
|
|
62
103
|
displayName: 'Options',
|
|
@@ -15,15 +15,15 @@ exports.pageOperations = [
|
|
|
15
15
|
options: [
|
|
16
16
|
{
|
|
17
17
|
name: 'Create',
|
|
18
|
-
value: '
|
|
19
|
-
description: 'Create a new tracked page',
|
|
18
|
+
value: 'createSimple',
|
|
19
|
+
description: 'Create a new tracked page with guided options',
|
|
20
20
|
action: 'Create a page',
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
name: 'Create
|
|
24
|
-
value: '
|
|
25
|
-
description: 'Create a page with
|
|
26
|
-
action: 'Create
|
|
23
|
+
name: 'Create (Advanced)',
|
|
24
|
+
value: 'create',
|
|
25
|
+
description: 'Create a page with full configuration options',
|
|
26
|
+
action: 'Create an advanced page',
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
name: 'Delete',
|
|
@@ -133,9 +133,9 @@ exports.pageFields = [
|
|
|
133
133
|
// page:get
|
|
134
134
|
// ========================================
|
|
135
135
|
{
|
|
136
|
-
displayName: 'Page
|
|
136
|
+
displayName: 'Page',
|
|
137
137
|
name: 'pageId',
|
|
138
|
-
type: '
|
|
138
|
+
type: 'resourceLocator',
|
|
139
139
|
required: true,
|
|
140
140
|
displayOptions: {
|
|
141
141
|
show: {
|
|
@@ -143,8 +143,49 @@ exports.pageFields = [
|
|
|
143
143
|
operation: ['get', 'update', 'delete', 'runCheckNow'],
|
|
144
144
|
},
|
|
145
145
|
},
|
|
146
|
-
default: '',
|
|
147
|
-
description: '
|
|
146
|
+
default: { mode: 'list', value: '' },
|
|
147
|
+
description: 'Select a page or enter slug/ID. <a href="https://pagecrawl.io/app/pages" target="_blank">View pages</a>.',
|
|
148
|
+
modes: [
|
|
149
|
+
{
|
|
150
|
+
displayName: 'From List',
|
|
151
|
+
name: 'list',
|
|
152
|
+
type: 'list',
|
|
153
|
+
typeOptions: {
|
|
154
|
+
searchListMethod: 'pageSearch',
|
|
155
|
+
searchable: true,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
displayName: 'By Slug',
|
|
160
|
+
name: 'slug',
|
|
161
|
+
type: 'string',
|
|
162
|
+
placeholder: 'e.g. my-page-name',
|
|
163
|
+
validation: [
|
|
164
|
+
{
|
|
165
|
+
type: 'regex',
|
|
166
|
+
properties: {
|
|
167
|
+
regex: '^[a-z0-9-]+$',
|
|
168
|
+
errorMessage: 'Slug must contain only lowercase letters, numbers, and hyphens',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
displayName: 'By ID',
|
|
175
|
+
name: 'id',
|
|
176
|
+
type: 'string',
|
|
177
|
+
placeholder: 'e.g. 12345',
|
|
178
|
+
validation: [
|
|
179
|
+
{
|
|
180
|
+
type: 'regex',
|
|
181
|
+
properties: {
|
|
182
|
+
regex: '^[0-9]+$',
|
|
183
|
+
errorMessage: 'ID must be a number',
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
},
|
|
188
|
+
],
|
|
148
189
|
},
|
|
149
190
|
{
|
|
150
191
|
displayName: 'Options',
|
|
@@ -215,6 +256,89 @@ exports.pageFields = [
|
|
|
215
256
|
placeholder: 'https://example.com',
|
|
216
257
|
description: 'The URL to track',
|
|
217
258
|
},
|
|
259
|
+
{
|
|
260
|
+
displayName: 'Tracking Type',
|
|
261
|
+
name: 'trackingType',
|
|
262
|
+
type: 'options',
|
|
263
|
+
required: true,
|
|
264
|
+
displayOptions: {
|
|
265
|
+
show: {
|
|
266
|
+
resource: ['page'],
|
|
267
|
+
operation: ['createSimple'],
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
options: [
|
|
271
|
+
{
|
|
272
|
+
name: 'Full Page',
|
|
273
|
+
value: 'fullpage',
|
|
274
|
+
description: 'Track the entire page for changes',
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'Selected Area',
|
|
278
|
+
value: 'text',
|
|
279
|
+
description: 'Track a specific area using CSS/XPath selector',
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: 'Number',
|
|
283
|
+
value: 'number',
|
|
284
|
+
description: 'Track a numeric value (e.g., stock count, ratings)',
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
name: 'Price',
|
|
288
|
+
value: 'price',
|
|
289
|
+
description: 'Auto-detect and track price changes',
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
default: 'fullpage',
|
|
293
|
+
description: 'What type of content to track',
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
displayName: 'Full Page Mode',
|
|
297
|
+
name: 'fullpageMode',
|
|
298
|
+
type: 'options',
|
|
299
|
+
displayOptions: {
|
|
300
|
+
show: {
|
|
301
|
+
resource: ['page'],
|
|
302
|
+
operation: ['createSimple'],
|
|
303
|
+
trackingType: ['fullpage'],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
options: [
|
|
307
|
+
{
|
|
308
|
+
name: 'Everything On Page',
|
|
309
|
+
value: 'everything',
|
|
310
|
+
description: 'Track all visible content on the page',
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
name: 'Content Only',
|
|
314
|
+
value: 'content',
|
|
315
|
+
description: 'Track main content, ignoring navigation and sidebars',
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: 'Reader Mode',
|
|
319
|
+
value: 'reader',
|
|
320
|
+
description: 'Extract and track article content only',
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
default: 'everything',
|
|
324
|
+
description: 'How to extract page content',
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
displayName: 'CSS/XPath Selector',
|
|
328
|
+
name: 'selector',
|
|
329
|
+
type: 'string',
|
|
330
|
+
required: true,
|
|
331
|
+
displayOptions: {
|
|
332
|
+
show: {
|
|
333
|
+
resource: ['page'],
|
|
334
|
+
operation: ['createSimple'],
|
|
335
|
+
trackingType: ['text', 'number'],
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
default: '',
|
|
339
|
+
placeholder: 'e.g. .price, #stock-count, //div[@class="value"]',
|
|
340
|
+
description: 'CSS selector or XPath expression to locate the element',
|
|
341
|
+
},
|
|
218
342
|
{
|
|
219
343
|
displayName: 'Additional Fields',
|
|
220
344
|
name: 'additionalFields',
|
|
@@ -228,13 +352,6 @@ exports.pageFields = [
|
|
|
228
352
|
},
|
|
229
353
|
},
|
|
230
354
|
options: [
|
|
231
|
-
{
|
|
232
|
-
displayName: 'CSS/XPath Selector',
|
|
233
|
-
name: 'selector',
|
|
234
|
-
type: 'string',
|
|
235
|
-
default: '',
|
|
236
|
-
description: 'CSS or XPath selector. If empty, tracks full page.',
|
|
237
|
-
},
|
|
238
355
|
{
|
|
239
356
|
displayName: 'Frequency',
|
|
240
357
|
name: 'frequency',
|
|
@@ -46,17 +46,58 @@ exports.screenshotFields = [
|
|
|
46
46
|
// screenshot:all
|
|
47
47
|
// ========================================
|
|
48
48
|
{
|
|
49
|
-
displayName: 'Page
|
|
49
|
+
displayName: 'Page',
|
|
50
50
|
name: 'pageId',
|
|
51
|
-
type: '
|
|
51
|
+
type: 'resourceLocator',
|
|
52
52
|
required: true,
|
|
53
53
|
displayOptions: {
|
|
54
54
|
show: {
|
|
55
55
|
resource: ['screenshot'],
|
|
56
56
|
},
|
|
57
57
|
},
|
|
58
|
-
default: '',
|
|
59
|
-
description: '
|
|
58
|
+
default: { mode: 'list', value: '' },
|
|
59
|
+
description: 'Select a page or enter slug/ID. <a href="https://pagecrawl.io/app/pages" target="_blank">View pages</a>.',
|
|
60
|
+
modes: [
|
|
61
|
+
{
|
|
62
|
+
displayName: 'From List',
|
|
63
|
+
name: 'list',
|
|
64
|
+
type: 'list',
|
|
65
|
+
typeOptions: {
|
|
66
|
+
searchListMethod: 'pageSearch',
|
|
67
|
+
searchable: true,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
displayName: 'By Slug',
|
|
72
|
+
name: 'slug',
|
|
73
|
+
type: 'string',
|
|
74
|
+
placeholder: 'e.g. my-page-name',
|
|
75
|
+
validation: [
|
|
76
|
+
{
|
|
77
|
+
type: 'regex',
|
|
78
|
+
properties: {
|
|
79
|
+
regex: '^[a-z0-9-]+$',
|
|
80
|
+
errorMessage: 'Slug must contain only lowercase letters, numbers, and hyphens',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
displayName: 'By ID',
|
|
87
|
+
name: 'id',
|
|
88
|
+
type: 'string',
|
|
89
|
+
placeholder: 'e.g. 12345',
|
|
90
|
+
validation: [
|
|
91
|
+
{
|
|
92
|
+
type: 'regex',
|
|
93
|
+
properties: {
|
|
94
|
+
regex: '^[0-9]+$',
|
|
95
|
+
errorMessage: 'ID must be a number',
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
60
101
|
},
|
|
61
102
|
// ========================================
|
|
62
103
|
// screenshot:getCheckScreenshot, getCheckDiff
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData } from 'n8n-workflow';
|
|
1
|
+
import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData, ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow';
|
|
2
2
|
export declare class PageCrawlTrigger implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
listSearch: {
|
|
6
|
+
pageSearch(this: ILoadOptionsFunctions, filter?: string): Promise<INodeListSearchResult>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
4
9
|
webhookMethods: {
|
|
5
10
|
default: {
|
|
6
11
|
checkExists(this: IHookFunctions): Promise<boolean>;
|
|
@@ -54,10 +54,51 @@ class PageCrawlTrigger {
|
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
displayName: 'Page',
|
|
57
|
-
name: '
|
|
58
|
-
type: '
|
|
59
|
-
default: '',
|
|
60
|
-
description: '
|
|
57
|
+
name: 'page',
|
|
58
|
+
type: 'resourceLocator',
|
|
59
|
+
default: { mode: 'list', value: '' },
|
|
60
|
+
description: 'Select a page to monitor or leave empty for all pages. Don\'t see your page? <a href="https://pagecrawl.io/app/pages" target="_blank">Create one on PageCrawl</a>.',
|
|
61
|
+
modes: [
|
|
62
|
+
{
|
|
63
|
+
displayName: 'From List',
|
|
64
|
+
name: 'list',
|
|
65
|
+
type: 'list',
|
|
66
|
+
typeOptions: {
|
|
67
|
+
searchListMethod: 'pageSearch',
|
|
68
|
+
searchable: true,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
displayName: 'By Slug',
|
|
73
|
+
name: 'slug',
|
|
74
|
+
type: 'string',
|
|
75
|
+
placeholder: 'e.g. my-page-name',
|
|
76
|
+
validation: [
|
|
77
|
+
{
|
|
78
|
+
type: 'regex',
|
|
79
|
+
properties: {
|
|
80
|
+
regex: '^[a-z0-9-]+$',
|
|
81
|
+
errorMessage: 'Slug must contain only lowercase letters, numbers, and hyphens',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
displayName: 'By ID',
|
|
88
|
+
name: 'id',
|
|
89
|
+
type: 'string',
|
|
90
|
+
placeholder: 'e.g. 12345',
|
|
91
|
+
validation: [
|
|
92
|
+
{
|
|
93
|
+
type: 'regex',
|
|
94
|
+
properties: {
|
|
95
|
+
regex: '^[0-9]+$',
|
|
96
|
+
errorMessage: 'ID must be a number',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
],
|
|
61
102
|
},
|
|
62
103
|
{
|
|
63
104
|
displayName: 'Payload Fields',
|
|
@@ -67,7 +108,7 @@ class PageCrawlTrigger {
|
|
|
67
108
|
name: field.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
68
109
|
value: field,
|
|
69
110
|
})),
|
|
70
|
-
default: ['id', 'title', 'status', 'changed_at', 'difference', 'page'],
|
|
111
|
+
default: ['id', 'title', 'status', 'changed_at', 'difference', 'page', 'contents', 'html_difference'],
|
|
71
112
|
description: 'Fields to include in the webhook payload',
|
|
72
113
|
},
|
|
73
114
|
{
|
|
@@ -88,13 +129,37 @@ class PageCrawlTrigger {
|
|
|
88
129
|
},
|
|
89
130
|
],
|
|
90
131
|
};
|
|
132
|
+
this.methods = {
|
|
133
|
+
listSearch: {
|
|
134
|
+
async pageSearch(filter) {
|
|
135
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
136
|
+
const response = await this.helpers.httpRequestWithAuthentication.call(this, 'pageCrawlApi', {
|
|
137
|
+
method: 'GET',
|
|
138
|
+
url: `${baseUrl}/api/pages`,
|
|
139
|
+
json: true,
|
|
140
|
+
});
|
|
141
|
+
const pages = response.data || response;
|
|
142
|
+
let results = pages.map((page) => ({
|
|
143
|
+
name: page.name || page.url,
|
|
144
|
+
value: page.slug,
|
|
145
|
+
url: `https://pagecrawl.io/app/pages/${page.slug}`,
|
|
146
|
+
}));
|
|
147
|
+
// Filter results if search term provided
|
|
148
|
+
if (filter) {
|
|
149
|
+
const filterLower = filter.toLowerCase();
|
|
150
|
+
results = results.filter((page) => page.name.toLowerCase().includes(filterLower) ||
|
|
151
|
+
page.value.toLowerCase().includes(filterLower));
|
|
152
|
+
}
|
|
153
|
+
return { results };
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
};
|
|
91
157
|
this.webhookMethods = {
|
|
92
158
|
default: {
|
|
93
159
|
async checkExists() {
|
|
94
160
|
const webhookData = this.getWorkflowStaticData('node');
|
|
95
161
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
96
|
-
const
|
|
97
|
-
const baseUrl = (credentials.baseUrl || 'https://pagecrawl.io').replace(/\/+$/, '');
|
|
162
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
98
163
|
if (!webhookData.webhookId) {
|
|
99
164
|
return false;
|
|
100
165
|
}
|
|
@@ -117,16 +182,16 @@ class PageCrawlTrigger {
|
|
|
117
182
|
async create() {
|
|
118
183
|
const webhookUrl = this.getNodeWebhookUrl('default');
|
|
119
184
|
const webhookData = this.getWorkflowStaticData('node');
|
|
120
|
-
const
|
|
185
|
+
const pageLocator = this.getNodeParameter('page', { mode: 'list', value: '' });
|
|
186
|
+
const pageValue = pageLocator.value || '';
|
|
121
187
|
const payloadFields = this.getNodeParameter('payloadFields', []);
|
|
122
|
-
const
|
|
123
|
-
const baseUrl = (credentials.baseUrl || 'https://pagecrawl.io').replace(/\/+$/, '');
|
|
188
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
124
189
|
const body = {
|
|
125
190
|
target_url: webhookUrl,
|
|
126
191
|
event_type: 'n8n',
|
|
127
192
|
};
|
|
128
|
-
if (
|
|
129
|
-
body.change_id =
|
|
193
|
+
if (pageValue) {
|
|
194
|
+
body.change_id = pageValue;
|
|
130
195
|
}
|
|
131
196
|
if (payloadFields.length > 0) {
|
|
132
197
|
body.payload_fields = payloadFields;
|
|
@@ -151,8 +216,7 @@ class PageCrawlTrigger {
|
|
|
151
216
|
},
|
|
152
217
|
async delete() {
|
|
153
218
|
const webhookData = this.getWorkflowStaticData('node');
|
|
154
|
-
const
|
|
155
|
-
const baseUrl = (credentials.baseUrl || 'https://pagecrawl.io').replace(/\/+$/, '');
|
|
219
|
+
const baseUrl = 'https://pagecrawl.io';
|
|
156
220
|
if (!webhookData.webhookId) {
|
|
157
221
|
return true;
|
|
158
222
|
}
|