@pipedream/salesforce_rest_api 1.2.1 → 1.3.1
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/README.md +92 -0
- package/actions/add-contact-to-campaign/add-contact-to-campaign.mjs +25 -25
- package/actions/add-lead-to-campaign/add-lead-to-campaign.mjs +25 -24
- package/actions/common/base-create-update.mjs +108 -0
- package/actions/convert-soap-xml-to-json/convert-soap-xml-to-json.mjs +11 -3
- package/actions/create-account/create-account.mjs +33 -36
- package/actions/create-attachment/create-attachment.mjs +36 -50
- package/actions/create-campaign/create-campaign.mjs +41 -37
- package/actions/create-case/create-case.mjs +41 -37
- package/actions/create-casecomment/create-casecomment.mjs +26 -38
- package/actions/create-contact/create-contact.mjs +38 -35
- package/actions/create-event/create-event.mjs +57 -66
- package/actions/create-lead/create-lead.mjs +34 -42
- package/actions/create-note/create-note.mjs +24 -43
- package/actions/create-opportunity/create-opportunity.mjs +38 -47
- package/actions/create-record/create-record.mjs +49 -15
- package/actions/create-task/create-task.mjs +50 -42
- package/actions/create-user/create-user.mjs +33 -196
- package/actions/delete-opportunity/delete-opportunity.mjs +17 -13
- package/actions/delete-record/delete-record.mjs +18 -16
- package/actions/find-records/find-records.mjs +41 -26
- package/actions/insert-blob-data/insert-blob-data.mjs +3 -7
- package/actions/post-feed-to-chatter/post-feed-to-chatter.mjs +45 -20
- package/actions/search-string/search-string.mjs +22 -20
- package/actions/soql-search/soql-search.mjs +13 -8
- package/actions/sosl-search/sosl-search.mjs +19 -9
- package/actions/update-account/update-account.mjs +54 -41
- package/actions/update-contact/update-contact.mjs +59 -40
- package/actions/update-opportunity/update-opportunity.mjs +56 -54
- package/actions/update-record/update-record.mjs +67 -20
- package/common/all-sobjects.mjs +3812 -0
- package/common/constants-props.mjs +1539 -0
- package/common/props-async-options.mjs +154 -0
- package/common/props-utils.mjs +88 -31
- package/common/sobjects/account.mjs +349 -22
- package/common/sobjects/attachment.mjs +56 -17
- package/common/sobjects/campaign.mjs +125 -23
- package/common/sobjects/case.mjs +193 -13
- package/common/sobjects/caseComment.mjs +28 -4
- package/common/sobjects/contact.mjs +207 -43
- package/common/sobjects/event.mjs +218 -18
- package/common/sobjects/lead.mjs +245 -22
- package/common/sobjects/note.mjs +37 -14
- package/common/sobjects/opportunity.mjs +148 -22
- package/common/sobjects/task.mjs +240 -19
- package/common/sobjects/user.mjs +965 -0
- package/package.json +2 -2
- package/salesforce_rest_api.app.mjs +72 -249
- package/sources/common-webhook-methods.mjs +71 -0
- package/sources/common.mjs +85 -22
- package/sources/new-outbound-message/new-outbound-message.mjs +11 -3
- package/sources/new-record-instant/new-record-instant.mjs +95 -7
- package/sources/record-deleted-instant/record-deleted-instant.mjs +40 -5
- package/sources/record-updated-instant/record-updated-instant.mjs +137 -5
- package/actions/common/base.mjs +0 -18
- package/actions/find-create-record/find-create-record.mjs +0 -89
- package/actions/get-sobject-fields-values/get-sobject-fields-values.mjs +0 -57
- package/common/utils.mjs +0 -51
- package/sources/common-instant.mjs +0 -146
- package/sources/new-record/new-record.mjs +0 -91
- package/sources/record-deleted/record-deleted.mjs +0 -51
- package/sources/record-updated/record-updated.mjs +0 -94
- package/sources/updated-field-on-record/updated-field-on-record.mjs +0 -161
- package/sources/updated-field-on-record-instant/updated-field-on-record-instant.mjs +0 -76
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipedream/salesforce_rest_api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Pipedream Salesforce (REST API) Components",
|
|
5
5
|
"main": "salesforce_rest_api.app.mjs",
|
|
6
6
|
"keywords": [
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://pipedream.com/apps/salesforce_rest_api",
|
|
11
11
|
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@pipedream/platform": "^
|
|
13
|
+
"@pipedream/platform": "^3.0.0",
|
|
14
14
|
"fast-xml-parser": "^4.3.2",
|
|
15
15
|
"handlebars": "^4.7.7",
|
|
16
16
|
"lodash": "^4.17.21",
|
|
@@ -4,19 +4,6 @@ export default {
|
|
|
4
4
|
type: "app",
|
|
5
5
|
app: "salesforce_rest_api",
|
|
6
6
|
propDefinitions: {
|
|
7
|
-
sobjectId: {
|
|
8
|
-
type: "string",
|
|
9
|
-
label: "SObject ID",
|
|
10
|
-
description: "ID of the Standard object to get field values from",
|
|
11
|
-
async options(context) {
|
|
12
|
-
const { objectType } = context;
|
|
13
|
-
const { recentItems } = await this.listSObjectTypeIds(objectType);
|
|
14
|
-
return recentItems.map((item) => ({
|
|
15
|
-
label: item.Name,
|
|
16
|
-
value: item.Id,
|
|
17
|
-
}));
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
7
|
objectType: {
|
|
21
8
|
type: "string",
|
|
22
9
|
label: "SObject Type",
|
|
@@ -38,6 +25,21 @@ export default {
|
|
|
38
25
|
return sobjects.filter(filter).map(mapper);
|
|
39
26
|
},
|
|
40
27
|
},
|
|
28
|
+
recordId: {
|
|
29
|
+
type: "string",
|
|
30
|
+
label: "Record ID",
|
|
31
|
+
description: "The ID of the record of the selected object type.",
|
|
32
|
+
async options({
|
|
33
|
+
objType,
|
|
34
|
+
nameField,
|
|
35
|
+
}) {
|
|
36
|
+
if (!nameField) nameField = await this.getNameFieldForObjectType(objType);
|
|
37
|
+
return this.listRecordOptions({
|
|
38
|
+
objType,
|
|
39
|
+
nameField,
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
},
|
|
41
43
|
field: {
|
|
42
44
|
type: "string",
|
|
43
45
|
label: "Field",
|
|
@@ -53,37 +55,30 @@ export default {
|
|
|
53
55
|
return fields.filter(filter).map(({ name }) => name);
|
|
54
56
|
},
|
|
55
57
|
},
|
|
56
|
-
|
|
57
|
-
type: "string",
|
|
58
|
-
label: "Field Updated to",
|
|
59
|
-
description:
|
|
60
|
-
"If provided, the trigger will only fire when the updated field is an EXACT MATCH (including spacing and casing) to the value you provide in this field",
|
|
61
|
-
optional: true,
|
|
62
|
-
},
|
|
63
|
-
fieldSelector: {
|
|
58
|
+
fieldsToUpdate: {
|
|
64
59
|
type: "string[]",
|
|
65
|
-
label: "
|
|
66
|
-
description: "Select
|
|
67
|
-
options
|
|
60
|
+
label: "Fields to Update",
|
|
61
|
+
description: "Select the field(s) you want to update for this record.",
|
|
62
|
+
async options({ objType }) {
|
|
63
|
+
const fields = await this.getFieldsForObjectType(objType);
|
|
64
|
+
return fields.filter((field) => field.updateable).map(({ name }) => name);
|
|
65
|
+
},
|
|
68
66
|
},
|
|
69
|
-
|
|
67
|
+
fieldsToObtain: {
|
|
70
68
|
type: "string[]",
|
|
71
|
-
label: "
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
...contacts,
|
|
77
|
-
...leads,
|
|
78
|
-
];
|
|
79
|
-
return allContacts.map(({
|
|
80
|
-
Name, Id,
|
|
81
|
-
}) => ({
|
|
82
|
-
label: Name,
|
|
83
|
-
value: Id,
|
|
84
|
-
}));
|
|
69
|
+
label: "Fields to Obtain",
|
|
70
|
+
description: "Select the field(s) to obtain for the selected record(s) (or all records).",
|
|
71
|
+
async options({ objType }) {
|
|
72
|
+
const fields = await this.getFieldsForObjectType(objType);
|
|
73
|
+
return fields.map(({ name }) => name);
|
|
85
74
|
},
|
|
86
|
-
|
|
75
|
+
},
|
|
76
|
+
useAdvancedProps: {
|
|
77
|
+
type: "boolean",
|
|
78
|
+
label: "See All Props",
|
|
79
|
+
description: "Set to true to see all available props for this object.",
|
|
80
|
+
optional: true,
|
|
81
|
+
reloadProps: true,
|
|
87
82
|
},
|
|
88
83
|
},
|
|
89
84
|
methods: {
|
|
@@ -138,10 +133,6 @@ export default {
|
|
|
138
133
|
const baseUrl = this._sObjectTypeApiUrl(sObjectType);
|
|
139
134
|
return `${baseUrl}/describe`;
|
|
140
135
|
},
|
|
141
|
-
_sObjectTypeUpdatedApiUrl(sObjectType) {
|
|
142
|
-
const baseUrl = this._sObjectTypeApiUrl(sObjectType);
|
|
143
|
-
return `${baseUrl}/updated`;
|
|
144
|
-
},
|
|
145
136
|
_sObjectTypeDeletedApiUrl(sObjectType) {
|
|
146
137
|
const baseUrl = this._sObjectTypeApiUrl(sObjectType);
|
|
147
138
|
return `${baseUrl}/deleted`;
|
|
@@ -223,35 +214,32 @@ export default {
|
|
|
223
214
|
});
|
|
224
215
|
return data.fields;
|
|
225
216
|
},
|
|
226
|
-
async
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
(sobject) =>
|
|
230
|
-
sobject.associateParentEntity === objectType &&
|
|
231
|
-
this.isHistorySObject(sobject),
|
|
232
|
-
);
|
|
233
|
-
return historyObject;
|
|
234
|
-
},
|
|
235
|
-
async createObject(objectType, data) {
|
|
236
|
-
const url = `${this._sObjectsApiUrl()}/${objectType}`;
|
|
217
|
+
async createObject({
|
|
218
|
+
objectType, ...args
|
|
219
|
+
}) {
|
|
237
220
|
return this._makeRequest({
|
|
238
|
-
url
|
|
239
|
-
data,
|
|
221
|
+
url: `${this._sObjectsApiUrl()}/${objectType}`,
|
|
240
222
|
method: "POST",
|
|
223
|
+
...args,
|
|
241
224
|
});
|
|
242
225
|
},
|
|
243
|
-
async
|
|
244
|
-
|
|
226
|
+
async deleteRecord({
|
|
227
|
+
sobjectType, recordId, ...args
|
|
228
|
+
}) {
|
|
229
|
+
const url = `${this._sObjectsApiUrl()}/${sobjectType}/${recordId}`;
|
|
245
230
|
return this._makeRequest({
|
|
246
231
|
url,
|
|
247
232
|
method: "DELETE",
|
|
233
|
+
...args,
|
|
248
234
|
});
|
|
249
235
|
},
|
|
250
|
-
async getRecords(
|
|
236
|
+
async getRecords({
|
|
237
|
+
objectType, ...args
|
|
238
|
+
}) {
|
|
251
239
|
const url = `${this._sCompositeApiUrl()}/${objectType}`;
|
|
252
240
|
return this._makeRequest({
|
|
253
241
|
url,
|
|
254
|
-
|
|
242
|
+
...args,
|
|
255
243
|
});
|
|
256
244
|
},
|
|
257
245
|
async getSObject(objectType, id, params = null) {
|
|
@@ -261,17 +249,6 @@ export default {
|
|
|
261
249
|
params,
|
|
262
250
|
});
|
|
263
251
|
},
|
|
264
|
-
async getUpdatedForObjectType(objectType, start, end) {
|
|
265
|
-
const url = this._sObjectTypeUpdatedApiUrl(objectType);
|
|
266
|
-
const params = {
|
|
267
|
-
start: this._formatDateString(start),
|
|
268
|
-
end: this._formatDateString(end),
|
|
269
|
-
};
|
|
270
|
-
return this._makeRequest({
|
|
271
|
-
url,
|
|
272
|
-
params,
|
|
273
|
-
});
|
|
274
|
-
},
|
|
275
252
|
async getDeletedForObjectType(objectType, start, end) {
|
|
276
253
|
const url = this._sObjectTypeDeletedApiUrl(objectType);
|
|
277
254
|
const params = {
|
|
@@ -293,159 +270,6 @@ export default {
|
|
|
293
270
|
},
|
|
294
271
|
});
|
|
295
272
|
},
|
|
296
|
-
async createAccount({
|
|
297
|
-
$, data,
|
|
298
|
-
}) {
|
|
299
|
-
const url = this._sObjectTypeApiUrl("Account");
|
|
300
|
-
return this._makeRequest({
|
|
301
|
-
$,
|
|
302
|
-
url,
|
|
303
|
-
method: "POST",
|
|
304
|
-
data,
|
|
305
|
-
});
|
|
306
|
-
},
|
|
307
|
-
async updateAccount({
|
|
308
|
-
$, id, data,
|
|
309
|
-
}) {
|
|
310
|
-
const url = this._sObjectDetailsApiUrl("Account", id);
|
|
311
|
-
return this._makeRequest({
|
|
312
|
-
$,
|
|
313
|
-
url,
|
|
314
|
-
method: "PATCH",
|
|
315
|
-
data,
|
|
316
|
-
});
|
|
317
|
-
},
|
|
318
|
-
async createAttachment({
|
|
319
|
-
$, data,
|
|
320
|
-
}) {
|
|
321
|
-
const url = this._sObjectTypeApiUrl("Attachment");
|
|
322
|
-
return this._makeRequest({
|
|
323
|
-
$,
|
|
324
|
-
url,
|
|
325
|
-
method: "POST",
|
|
326
|
-
data,
|
|
327
|
-
});
|
|
328
|
-
},
|
|
329
|
-
async createCampaign({
|
|
330
|
-
$, data,
|
|
331
|
-
}) {
|
|
332
|
-
const url = this._sObjectTypeApiUrl("Campaign");
|
|
333
|
-
return this._makeRequest({
|
|
334
|
-
$,
|
|
335
|
-
url,
|
|
336
|
-
method: "POST",
|
|
337
|
-
data,
|
|
338
|
-
});
|
|
339
|
-
},
|
|
340
|
-
async createCase({
|
|
341
|
-
$, data,
|
|
342
|
-
}) {
|
|
343
|
-
const url = this._sObjectTypeApiUrl("Case");
|
|
344
|
-
return this._makeRequest({
|
|
345
|
-
$,
|
|
346
|
-
url,
|
|
347
|
-
method: "POST",
|
|
348
|
-
data,
|
|
349
|
-
});
|
|
350
|
-
},
|
|
351
|
-
async createCaseComment({
|
|
352
|
-
$, data,
|
|
353
|
-
}) {
|
|
354
|
-
const url = this._sObjectTypeApiUrl("CaseComment");
|
|
355
|
-
return this._makeRequest({
|
|
356
|
-
$,
|
|
357
|
-
url,
|
|
358
|
-
method: "POST",
|
|
359
|
-
data,
|
|
360
|
-
});
|
|
361
|
-
},
|
|
362
|
-
async createContact({
|
|
363
|
-
$, data,
|
|
364
|
-
}) {
|
|
365
|
-
const url = this._sObjectTypeApiUrl("Contact");
|
|
366
|
-
return this._makeRequest({
|
|
367
|
-
$,
|
|
368
|
-
url,
|
|
369
|
-
method: "POST",
|
|
370
|
-
data,
|
|
371
|
-
});
|
|
372
|
-
},
|
|
373
|
-
async updateContact({
|
|
374
|
-
$, id, data,
|
|
375
|
-
}) {
|
|
376
|
-
const url = this._sObjectDetailsApiUrl("Contact", id);
|
|
377
|
-
return this._makeRequest({
|
|
378
|
-
$,
|
|
379
|
-
url,
|
|
380
|
-
method: "PATCH",
|
|
381
|
-
data,
|
|
382
|
-
});
|
|
383
|
-
},
|
|
384
|
-
async createEvent({
|
|
385
|
-
$, data,
|
|
386
|
-
}) {
|
|
387
|
-
const url = this._sObjectTypeApiUrl("Event");
|
|
388
|
-
return this._makeRequest({
|
|
389
|
-
$,
|
|
390
|
-
url,
|
|
391
|
-
method: "POST",
|
|
392
|
-
data,
|
|
393
|
-
});
|
|
394
|
-
},
|
|
395
|
-
async createLead({
|
|
396
|
-
$, data,
|
|
397
|
-
}) {
|
|
398
|
-
const url = this._sObjectTypeApiUrl("Lead");
|
|
399
|
-
return this._makeRequest({
|
|
400
|
-
$,
|
|
401
|
-
url,
|
|
402
|
-
method: "POST",
|
|
403
|
-
data,
|
|
404
|
-
});
|
|
405
|
-
},
|
|
406
|
-
async createNote({
|
|
407
|
-
$, data,
|
|
408
|
-
}) {
|
|
409
|
-
const url = this._sObjectTypeApiUrl("Note");
|
|
410
|
-
return this._makeRequest({
|
|
411
|
-
$,
|
|
412
|
-
url,
|
|
413
|
-
method: "POST",
|
|
414
|
-
data,
|
|
415
|
-
});
|
|
416
|
-
},
|
|
417
|
-
async createOpportunity({
|
|
418
|
-
$, data,
|
|
419
|
-
}) {
|
|
420
|
-
const url = this._sObjectTypeApiUrl("Opportunity");
|
|
421
|
-
return this._makeRequest({
|
|
422
|
-
$,
|
|
423
|
-
url,
|
|
424
|
-
method: "POST",
|
|
425
|
-
data,
|
|
426
|
-
});
|
|
427
|
-
},
|
|
428
|
-
async updateOpportunity({
|
|
429
|
-
$, id, data,
|
|
430
|
-
}) {
|
|
431
|
-
const url = this._sObjectDetailsApiUrl("Opportunity", id);
|
|
432
|
-
return this._makeRequest({
|
|
433
|
-
$,
|
|
434
|
-
url,
|
|
435
|
-
method: "PATCH",
|
|
436
|
-
data,
|
|
437
|
-
});
|
|
438
|
-
},
|
|
439
|
-
async getRecordFieldValues(sobjectName, {
|
|
440
|
-
$, id, params,
|
|
441
|
-
}) {
|
|
442
|
-
const url = this._sObjectDetailsApiUrl(sobjectName, id);
|
|
443
|
-
return this._makeRequest({
|
|
444
|
-
$,
|
|
445
|
-
url,
|
|
446
|
-
params,
|
|
447
|
-
});
|
|
448
|
-
},
|
|
449
273
|
async createRecord(sobjectName, {
|
|
450
274
|
$, data,
|
|
451
275
|
}) {
|
|
@@ -468,27 +292,6 @@ export default {
|
|
|
468
292
|
data,
|
|
469
293
|
});
|
|
470
294
|
},
|
|
471
|
-
async createTask({
|
|
472
|
-
$, data,
|
|
473
|
-
}) {
|
|
474
|
-
const url = this._sObjectTypeApiUrl("Task");
|
|
475
|
-
return this._makeRequest({
|
|
476
|
-
$,
|
|
477
|
-
url,
|
|
478
|
-
method: "POST",
|
|
479
|
-
data,
|
|
480
|
-
});
|
|
481
|
-
},
|
|
482
|
-
async deleteOpportunity({
|
|
483
|
-
$, id,
|
|
484
|
-
}) {
|
|
485
|
-
const url = this._sObjectDetailsApiUrl("Opportunity", id);
|
|
486
|
-
return this._makeRequest({
|
|
487
|
-
$,
|
|
488
|
-
url,
|
|
489
|
-
method: "DELETE",
|
|
490
|
-
});
|
|
491
|
-
},
|
|
492
295
|
async query({
|
|
493
296
|
$, query,
|
|
494
297
|
}) {
|
|
@@ -499,6 +302,26 @@ export default {
|
|
|
499
302
|
url,
|
|
500
303
|
});
|
|
501
304
|
},
|
|
305
|
+
async listRecordOptions({
|
|
306
|
+
objType,
|
|
307
|
+
nameField = "Id",
|
|
308
|
+
}) {
|
|
309
|
+
const fields = [
|
|
310
|
+
"Id",
|
|
311
|
+
...nameField === "Id"
|
|
312
|
+
? []
|
|
313
|
+
: [
|
|
314
|
+
nameField,
|
|
315
|
+
],
|
|
316
|
+
];
|
|
317
|
+
const { records } = await this.query({
|
|
318
|
+
query: `SELECT ${fields.join(", ")} FROM ${objType}`,
|
|
319
|
+
});
|
|
320
|
+
return records?.map?.((item) => ({
|
|
321
|
+
label: item[nameField],
|
|
322
|
+
value: item.Id,
|
|
323
|
+
})) ?? [];
|
|
324
|
+
},
|
|
502
325
|
async search({
|
|
503
326
|
$, search,
|
|
504
327
|
}) {
|
|
@@ -509,14 +332,14 @@ export default {
|
|
|
509
332
|
url,
|
|
510
333
|
});
|
|
511
334
|
},
|
|
512
|
-
async parameterizedSearch(
|
|
335
|
+
async parameterizedSearch(args) {
|
|
513
336
|
const baseUrl = this._baseApiVersionUrl();
|
|
514
337
|
const url = `${baseUrl}/parameterizedSearch/`;
|
|
515
338
|
|
|
516
339
|
return this._makeRequest({
|
|
517
340
|
url,
|
|
518
341
|
method: "GET",
|
|
519
|
-
|
|
342
|
+
...args,
|
|
520
343
|
});
|
|
521
344
|
},
|
|
522
345
|
async insertBlobData(sobjectName, {
|
|
@@ -534,7 +357,7 @@ export default {
|
|
|
534
357
|
};
|
|
535
358
|
return axios($ ?? this, requestConfig);
|
|
536
359
|
},
|
|
537
|
-
async postFeed(args
|
|
360
|
+
async postFeed(args) {
|
|
538
361
|
const baseUrl = this._baseApiVersionUrl();
|
|
539
362
|
const url = `${baseUrl}/chatter/feed-elements`;
|
|
540
363
|
return this._makeRequest({
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import salesforceWebhooks from "salesforce-webhooks";
|
|
2
|
+
|
|
3
|
+
const { SalesforceClient } = salesforceWebhooks;
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
getClient() {
|
|
7
|
+
const { salesforce } = this;
|
|
8
|
+
return new SalesforceClient({
|
|
9
|
+
apiVersion: salesforce._apiVersion(),
|
|
10
|
+
authToken: salesforce._authToken(),
|
|
11
|
+
instance: salesforce._subdomain(),
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
createWebhook(args = {}) {
|
|
15
|
+
const client = this.getClient();
|
|
16
|
+
return client.createWebhook(args);
|
|
17
|
+
},
|
|
18
|
+
deleteWebhook(args = {}) {
|
|
19
|
+
const client = this.getClient();
|
|
20
|
+
return client.deleteWebhook(args);
|
|
21
|
+
},
|
|
22
|
+
_getSecretToken() {
|
|
23
|
+
return this.db.get("secretToken");
|
|
24
|
+
},
|
|
25
|
+
_setSecretToken(secretToken) {
|
|
26
|
+
this.db.set("secretToken", secretToken);
|
|
27
|
+
},
|
|
28
|
+
_getWebhookData() {
|
|
29
|
+
return this.db.get("webhookData");
|
|
30
|
+
},
|
|
31
|
+
_setWebhookData(webhookData) {
|
|
32
|
+
this.db.set("webhookData", webhookData);
|
|
33
|
+
},
|
|
34
|
+
_isValidSource(event) {
|
|
35
|
+
const webhookToken = event.headers["x-webhook-token"];
|
|
36
|
+
const secretToken = this._getSecretToken();
|
|
37
|
+
return webhookToken === secretToken;
|
|
38
|
+
},
|
|
39
|
+
processWebhookEvent(event) {
|
|
40
|
+
const { body } = event;
|
|
41
|
+
const meta = this.generateWebhookMeta(event);
|
|
42
|
+
this.$emit(body, meta);
|
|
43
|
+
},
|
|
44
|
+
generateWebhookMeta() {
|
|
45
|
+
throw new Error("generateWebhookMeta is not implemented");
|
|
46
|
+
},
|
|
47
|
+
getEventType() {
|
|
48
|
+
throw new Error("getEventType is not implemented");
|
|
49
|
+
},
|
|
50
|
+
/**
|
|
51
|
+
* This method returns the fields in the SObject type (e.g. Account, Lead, etc.) that the event
|
|
52
|
+
* source should listen for updates to. This base implementation returns `undefined`, to not
|
|
53
|
+
* necessitate any specific fields to be updated.
|
|
54
|
+
*
|
|
55
|
+
* @returns the fields in the SObject type for which to receive updates
|
|
56
|
+
*/
|
|
57
|
+
getFieldsToCheck() {
|
|
58
|
+
return undefined;
|
|
59
|
+
},
|
|
60
|
+
/**
|
|
61
|
+
* This method returns whether the event source should listen for updates where `all` the fields
|
|
62
|
+
* in the SObject are updated, or when `any` of them are. This base implementation returns
|
|
63
|
+
* `undefined` to use to client's default `fieldToCheckMode` (`any`).
|
|
64
|
+
*
|
|
65
|
+
* @returns whether the webhook should receive events when `all` the fields to check are
|
|
66
|
+
* updated, or when `any` of them are
|
|
67
|
+
*/
|
|
68
|
+
getFieldsToCheckMode() {
|
|
69
|
+
return undefined;
|
|
70
|
+
},
|
|
71
|
+
};
|
package/sources/common.mjs
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
|
|
2
2
|
import salesforce from "../salesforce_rest_api.app.mjs";
|
|
3
3
|
import constants from "../common/constants.mjs";
|
|
4
|
+
import { v4 as uuidv4 } from "uuid";
|
|
5
|
+
import commonWebhookMethods from "./common-webhook-methods.mjs";
|
|
4
6
|
|
|
5
7
|
export default {
|
|
6
8
|
dedupe: "unique",
|
|
7
9
|
props: {
|
|
8
10
|
salesforce,
|
|
9
11
|
db: "$.service.db",
|
|
10
|
-
|
|
12
|
+
http: {
|
|
13
|
+
type: "$.interface.http",
|
|
14
|
+
customResponse: true,
|
|
15
|
+
},
|
|
11
16
|
timer: {
|
|
12
17
|
type: "$.interface.timer",
|
|
18
|
+
description: "The timer is only used as a fallback if instant event delivery (webhook) is not available.",
|
|
13
19
|
default: {
|
|
14
20
|
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
|
|
15
21
|
},
|
|
16
22
|
},
|
|
17
23
|
objectType: {
|
|
18
|
-
type: "string",
|
|
19
24
|
label: "Object Type",
|
|
20
25
|
description: "The type of object for which to monitor events",
|
|
21
26
|
propDefinition: [
|
|
@@ -26,17 +31,51 @@ export default {
|
|
|
26
31
|
},
|
|
27
32
|
hooks: {
|
|
28
33
|
async activate() {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
// Attempt to create the webhook
|
|
35
|
+
const secretToken = uuidv4();
|
|
36
|
+
let webhookData;
|
|
37
|
+
try {
|
|
38
|
+
webhookData = await this.createWebhook({
|
|
39
|
+
endpointUrl: this.http.endpoint,
|
|
40
|
+
sObjectType: this.objectType,
|
|
41
|
+
event: this.getEventType(),
|
|
42
|
+
secretToken,
|
|
43
|
+
fieldsToCheck: this.getFieldsToCheck(),
|
|
44
|
+
fieldsToCheckMode: this.getFieldsToCheckMode(),
|
|
45
|
+
skipValidation: true, // neccessary for custom objects
|
|
46
|
+
});
|
|
47
|
+
console.log("Webhook created successfully");
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.log("Error creating webhook:", err);
|
|
50
|
+
console.log("The source will operate on the polling schedule instead.");
|
|
51
|
+
|
|
52
|
+
const latestDateCovered = this.getLatestDateCovered();
|
|
53
|
+
if (!latestDateCovered) {
|
|
54
|
+
const now = new Date().toISOString();
|
|
55
|
+
this.setLatestDateCovered(now);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await this.timerActivateHook?.();
|
|
33
59
|
}
|
|
60
|
+
this._setSecretToken(secretToken);
|
|
61
|
+
this._setWebhookData(webhookData);
|
|
34
62
|
|
|
35
63
|
const nameField = await this.salesforce.getNameFieldForObjectType(this.objectType);
|
|
36
64
|
this.setNameField(nameField);
|
|
37
65
|
},
|
|
66
|
+
async deactivate() {
|
|
67
|
+
// Delete the webhook, if it exists
|
|
68
|
+
const webhookData = this._getWebhookData();
|
|
69
|
+
if (webhookData) {
|
|
70
|
+
await this.deleteWebhook(webhookData);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
38
73
|
},
|
|
39
74
|
methods: {
|
|
75
|
+
...commonWebhookMethods,
|
|
76
|
+
timerActivateHook() {
|
|
77
|
+
return null;
|
|
78
|
+
},
|
|
40
79
|
getObjectTypeColumns() {
|
|
41
80
|
return this.db.get("columns") ?? [];
|
|
42
81
|
},
|
|
@@ -55,8 +94,8 @@ export default {
|
|
|
55
94
|
setNameField(nameField) {
|
|
56
95
|
this.db.set("nameField", nameField);
|
|
57
96
|
},
|
|
58
|
-
|
|
59
|
-
throw new Error("
|
|
97
|
+
processTimerEvent() {
|
|
98
|
+
throw new Error("processTimerEvent is not implemented");
|
|
60
99
|
},
|
|
61
100
|
getObjectTypeDescription(objectType) {
|
|
62
101
|
const { salesforce } = this;
|
|
@@ -120,21 +159,45 @@ export default {
|
|
|
120
159
|
},
|
|
121
160
|
},
|
|
122
161
|
async run(event) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
162
|
+
// Timer event
|
|
163
|
+
if (event.timestamp) {
|
|
164
|
+
if (this._getWebhookData()) {
|
|
165
|
+
console.log("Ignoring timer event (webhook active)");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const startTimestamp = this.getLatestDateCovered();
|
|
169
|
+
const endTimestamp = new Date(event.timestamp * 1000).toISOString();
|
|
170
|
+
const timeDiffSec = Math.floor(
|
|
171
|
+
(Date.parse(endTimestamp) - Date.parse(startTimestamp)) / 1000,
|
|
172
|
+
);
|
|
173
|
+
if (timeDiffSec < 60) {
|
|
174
|
+
console.log(`
|
|
175
|
+
Skipping execution (already executed less than 60 seconds ago)
|
|
176
|
+
`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
await this.processTimerEvent({
|
|
181
|
+
startTimestamp,
|
|
182
|
+
endTimestamp,
|
|
183
|
+
});
|
|
133
184
|
}
|
|
134
185
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
186
|
+
// Webhook event
|
|
187
|
+
else {
|
|
188
|
+
if (!this._isValidSource(event)) {
|
|
189
|
+
this.http.respond({
|
|
190
|
+
statusCode: 404,
|
|
191
|
+
});
|
|
192
|
+
console.log("Skipping event from unrecognized source");
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
this.http.respond({
|
|
197
|
+
statusCode: 200,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
await this.processWebhookEvent(event);
|
|
201
|
+
}
|
|
139
202
|
},
|
|
140
203
|
};
|
|
@@ -5,17 +5,25 @@ export default {
|
|
|
5
5
|
type: "source",
|
|
6
6
|
name: "New Outbound Message (Instant)",
|
|
7
7
|
key: "salesforce_rest_api-new-outbound-message",
|
|
8
|
-
description: "Emit new event when a new outbound message is received in Salesforce.
|
|
9
|
-
version: "0.1.
|
|
8
|
+
description: "Emit new event when a new outbound message is received in Salesforce.",
|
|
9
|
+
version: "0.1.7",
|
|
10
10
|
dedupe: "unique",
|
|
11
11
|
props: {
|
|
12
12
|
db: "$.service.db",
|
|
13
|
-
// eslint-disable-next-line pipedream/props-label,pipedream/props-description
|
|
14
13
|
http: {
|
|
15
14
|
type: "$.interface.http",
|
|
16
15
|
customResponse: true,
|
|
17
16
|
},
|
|
18
17
|
salesforce,
|
|
18
|
+
infoBox: {
|
|
19
|
+
type: "alert",
|
|
20
|
+
alertType: "info",
|
|
21
|
+
content: `See Salesforce's guide on [setting up Outbound Messaging](https://sforce.co/3JbZJom).
|
|
22
|
+
\\
|
|
23
|
+
Set the Outbound Message's \`Endpoint URL\` to the endpoint of this source, which you can view after it is created.
|
|
24
|
+
\\
|
|
25
|
+
The \`Send Session ID\` option must be enabled in Salesforce for validating outbound messages.`,
|
|
26
|
+
},
|
|
19
27
|
},
|
|
20
28
|
methods: {
|
|
21
29
|
_unwrapMessage(message) {
|