@pipedream/salesforce_rest_api 1.11.4 → 1.11.6
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/actions/search-string/search-string.mjs +11 -2
- package/package.json +2 -2
- package/sources/case-updated-instant/case-updated-instant.mjs +1 -1
- package/sources/common/common-updated-record.mjs +123 -2
- package/sources/email-template-updated-instant/email-template-updated-instant.mjs +1 -1
- package/sources/knowledge-article-updated-instant/knowledge-article-updated-instant.mjs +1 -1
- package/sources/new-case-instant/new-case-instant.mjs +1 -1
- package/sources/new-email-template-instant/new-email-template-instant.mjs +1 -1
- package/sources/new-knowledge-article-instant/new-knowledge-article-instant.mjs +1 -1
- package/sources/new-outbound-message/new-outbound-message.mjs +1 -1
- package/sources/new-record-instant/new-record-instant.mjs +1 -1
- package/sources/record-deleted-instant/record-deleted-instant.mjs +1 -1
- package/sources/record-updated-instant/record-updated-instant.mjs +1 -1
|
@@ -4,7 +4,7 @@ export default {
|
|
|
4
4
|
key: "salesforce_rest_api-search-string",
|
|
5
5
|
name: "Search Object Records",
|
|
6
6
|
description: "Searches for records in an object using a parameterized search. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_search_parameterized_get.htm)",
|
|
7
|
-
version: "0.0.
|
|
7
|
+
version: "0.0.8",
|
|
8
8
|
annotations: {
|
|
9
9
|
destructiveHint: false,
|
|
10
10
|
openWorldHint: true,
|
|
@@ -40,6 +40,13 @@ export default {
|
|
|
40
40
|
],
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
|
+
methods: {
|
|
44
|
+
// constructs a url that users can copy into a browser to view the record in Salesforce
|
|
45
|
+
createBrowserUrl(baseUrl, url) {
|
|
46
|
+
return `${baseUrl.replace(".my.salesforce.com", ".lightning.force.com")}/lightning/r/${url.match(/sobjects\/([^/]+)\/([^/]+)/).slice(1)
|
|
47
|
+
.join("/")}/view`;
|
|
48
|
+
},
|
|
49
|
+
},
|
|
43
50
|
async run({ $ }) {
|
|
44
51
|
const {
|
|
45
52
|
sobjectType,
|
|
@@ -56,6 +63,7 @@ export default {
|
|
|
56
63
|
},
|
|
57
64
|
});
|
|
58
65
|
const resultsFound = response.searchRecords.length;
|
|
66
|
+
const baseUrl = this.salesforce._baseApiUrl();
|
|
59
67
|
response.searchRecords = response.searchRecords.map((record) => {
|
|
60
68
|
const url = record?.attributes?.url;
|
|
61
69
|
if (!url) return record;
|
|
@@ -63,7 +71,8 @@ export default {
|
|
|
63
71
|
...record,
|
|
64
72
|
attributes: {
|
|
65
73
|
...record.attributes,
|
|
66
|
-
url: `${
|
|
74
|
+
url: `${baseUrl}${url}`, // api url
|
|
75
|
+
browserUrl: this.createBrowserUrl(baseUrl, url),
|
|
67
76
|
},
|
|
68
77
|
};
|
|
69
78
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipedream/salesforce_rest_api",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.6",
|
|
4
4
|
"description": "Pipedream Salesforce (REST API) Components",
|
|
5
5
|
"main": "salesforce_rest_api.app.mjs",
|
|
6
6
|
"keywords": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@pipedream/platform": "^3.1.1",
|
|
14
|
-
"fast-xml-parser": "^5.3.
|
|
14
|
+
"fast-xml-parser": "^5.3.6",
|
|
15
15
|
"handlebars": "^4.7.7",
|
|
16
16
|
"lodash": "^4.17.23",
|
|
17
17
|
"lodash-es": "^4.17.23",
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "Case Updated (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-case-updated-instant",
|
|
9
9
|
description: "Emit new event when a case is updated. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -15,8 +15,10 @@ export default {
|
|
|
15
15
|
if (!this.skipFirstRun) {
|
|
16
16
|
const { recentItems } = await this.salesforce.listSObjectTypeIds(objectType);
|
|
17
17
|
const ids = recentItems.map((item) => item.Id);
|
|
18
|
+
|
|
18
19
|
for (const id of ids.slice(-25)) {
|
|
19
20
|
const object = await this.salesforce.getSObject(objectType, id);
|
|
21
|
+
|
|
20
22
|
const event = {
|
|
21
23
|
body: {
|
|
22
24
|
"New": object,
|
|
@@ -65,6 +67,89 @@ export default {
|
|
|
65
67
|
},
|
|
66
68
|
methods: {
|
|
67
69
|
...common.methods,
|
|
70
|
+
getHistoryObjectName(objectType) {
|
|
71
|
+
if (objectType.endsWith("__c")) {
|
|
72
|
+
return objectType.replace(/__c$/, "__History");
|
|
73
|
+
}
|
|
74
|
+
return `${objectType}History`;
|
|
75
|
+
},
|
|
76
|
+
getHistoryParentIdField(objectType) {
|
|
77
|
+
if (objectType.endsWith("__c")) {
|
|
78
|
+
return "ParentId";
|
|
79
|
+
}
|
|
80
|
+
return `${objectType}Id`;
|
|
81
|
+
},
|
|
82
|
+
async queryFieldHistory({
|
|
83
|
+
objectType, recordIds, fields, startTimestamp,
|
|
84
|
+
}) {
|
|
85
|
+
if (!recordIds?.length || !fields?.length) {
|
|
86
|
+
return new Set();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const validFields = fields.filter((f) => /^[a-zA-Z_]\w*$/.test(f));
|
|
90
|
+
if (!validFields.length) {
|
|
91
|
+
return new Set();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const historyObjectName = this.getHistoryObjectName(objectType);
|
|
95
|
+
const parentIdField = this.getHistoryParentIdField(objectType);
|
|
96
|
+
const fieldList = validFields.map((f) => `'${f}'`).join(", ");
|
|
97
|
+
|
|
98
|
+
const BATCH_SIZE = 200;
|
|
99
|
+
const recordsWithChanges = new Set();
|
|
100
|
+
let totalHistoryRecords = 0;
|
|
101
|
+
let successfulBatches = 0;
|
|
102
|
+
let failedBatches = 0;
|
|
103
|
+
const totalBatches = Math.ceil(recordIds.length / BATCH_SIZE);
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < recordIds.length; i += BATCH_SIZE) {
|
|
106
|
+
const batch = recordIds.slice(i, i + BATCH_SIZE);
|
|
107
|
+
const recordIdList = batch.map((id) => `'${id}'`).join(", ");
|
|
108
|
+
const batchNumber = Math.floor(i / BATCH_SIZE) + 1;
|
|
109
|
+
|
|
110
|
+
const query = `
|
|
111
|
+
SELECT ${parentIdField}, Field, OldValue, NewValue, CreatedDate
|
|
112
|
+
FROM ${historyObjectName}
|
|
113
|
+
WHERE ${parentIdField} IN (${recordIdList})
|
|
114
|
+
AND Field IN (${fieldList})
|
|
115
|
+
AND CreatedDate >= ${startTimestamp}
|
|
116
|
+
ORDER BY CreatedDate DESC
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const { records } = await this.query({
|
|
121
|
+
query,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
totalHistoryRecords += records.length;
|
|
125
|
+
for (const record of records) {
|
|
126
|
+
recordsWithChanges.add(record[parentIdField]);
|
|
127
|
+
}
|
|
128
|
+
successfulBatches++;
|
|
129
|
+
} catch (err) {
|
|
130
|
+
failedBatches++;
|
|
131
|
+
console.log(`Field history query batch ${batchNumber}/${totalBatches} failed for ${historyObjectName}: ${err.message}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// If all batches failed, fall back to emitting all records
|
|
136
|
+
if (successfulBatches === 0) {
|
|
137
|
+
console.log("All field history query batches failed.");
|
|
138
|
+
console.log("This usually means field history tracking is not enabled for this object or the selected fields.");
|
|
139
|
+
console.log("To enable field history tracking in Salesforce:");
|
|
140
|
+
console.log("1. Go to Setup → Object Manager → [Your Object] → Fields & Relationships");
|
|
141
|
+
console.log("2. Click 'Set History Tracking' and select the fields you want to track");
|
|
142
|
+
console.log("Falling back to emitting all updated records without field filtering.");
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (failedBatches > 0) {
|
|
147
|
+
console.log(`Warning: ${failedBatches}/${totalBatches} batches failed, results may be incomplete`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
console.log(`Field history query found ${totalHistoryRecords} change(s) for ${recordsWithChanges.size} record(s)`);
|
|
151
|
+
return recordsWithChanges;
|
|
152
|
+
},
|
|
68
153
|
generateWebhookMeta(data) {
|
|
69
154
|
const nameField = this.getNameField();
|
|
70
155
|
const { New: newObject } = data.body;
|
|
@@ -157,9 +242,10 @@ export default {
|
|
|
157
242
|
|
|
158
243
|
const fieldName = getNameField();
|
|
159
244
|
const columns = getObjectTypeColumns();
|
|
245
|
+
const objectType = this.getObjectType();
|
|
160
246
|
|
|
161
247
|
const events = await paginate({
|
|
162
|
-
objectType
|
|
248
|
+
objectType,
|
|
163
249
|
startTimestamp,
|
|
164
250
|
endTimestamp,
|
|
165
251
|
columns,
|
|
@@ -177,7 +263,42 @@ export default {
|
|
|
177
263
|
latestDateCovered.setSeconds(0);
|
|
178
264
|
setLatestDateCovered(latestDateCovered.toISOString());
|
|
179
265
|
|
|
180
|
-
|
|
266
|
+
const { fields } = this;
|
|
267
|
+
|
|
268
|
+
if (!fields?.length) {
|
|
269
|
+
Array.from(events)
|
|
270
|
+
.reverse()
|
|
271
|
+
.forEach((item) => {
|
|
272
|
+
const meta = generateTimerMeta(item, fieldName);
|
|
273
|
+
emit(item, meta);
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const recordIds = events.map((event) => event.Id);
|
|
279
|
+
const recordsWithFieldChanges = await this.queryFieldHistory({
|
|
280
|
+
objectType,
|
|
281
|
+
recordIds,
|
|
282
|
+
fields,
|
|
283
|
+
startTimestamp,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
if (recordsWithFieldChanges === null) {
|
|
287
|
+
console.log("Emitting all updated records due to field history unavailability");
|
|
288
|
+
Array.from(events)
|
|
289
|
+
.reverse()
|
|
290
|
+
.forEach((item) => {
|
|
291
|
+
const meta = generateTimerMeta(item, fieldName);
|
|
292
|
+
emit(item, meta);
|
|
293
|
+
});
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const filteredEvents = events.filter((item) => recordsWithFieldChanges.has(item.Id));
|
|
298
|
+
|
|
299
|
+
console.log(`Filtered ${events.length} updated records to ${filteredEvents.length} with watched field changes`);
|
|
300
|
+
|
|
301
|
+
Array.from(filteredEvents)
|
|
181
302
|
.reverse()
|
|
182
303
|
.forEach((item) => {
|
|
183
304
|
const meta = generateTimerMeta(item, fieldName);
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "Email Template Updated (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-email-template-updated-instant",
|
|
9
9
|
description: "Emit new event when an email template is updated. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "Knowledge Article Updated (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-knowledge-article-updated-instant",
|
|
9
9
|
description: "Emit new event when a knowledge article is updated. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "New Case (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-new-case-instant",
|
|
9
9
|
description: "Emit new event when a case is created. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "New Email Template (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-new-email-template-instant",
|
|
9
9
|
description: "Emit new event when an email template is created. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "New Knowledge Article (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-new-knowledge-article-instant",
|
|
9
9
|
description: "Emit new event when a knowledge article is created. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.8",
|
|
11
11
|
props: {
|
|
12
12
|
salesforce: common.props.salesforce,
|
|
13
13
|
db: "$.service.db",
|
|
@@ -6,7 +6,7 @@ export default {
|
|
|
6
6
|
name: "New Outbound Message (Instant)",
|
|
7
7
|
key: "salesforce_rest_api-new-outbound-message",
|
|
8
8
|
description: "Emit new event when a new outbound message is received in Salesforce.",
|
|
9
|
-
version: "0.1.
|
|
9
|
+
version: "0.1.13",
|
|
10
10
|
dedupe: "unique",
|
|
11
11
|
props: {
|
|
12
12
|
db: "$.service.db",
|
|
@@ -6,7 +6,7 @@ export default {
|
|
|
6
6
|
name: "New Record (Instant, of Selectable Type)",
|
|
7
7
|
key: "salesforce_rest_api-new-record-instant",
|
|
8
8
|
description: "Emit new event when a record of the selected object type is created. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
9
|
-
version: "0.2.
|
|
9
|
+
version: "0.2.8",
|
|
10
10
|
props: {
|
|
11
11
|
...common.props,
|
|
12
12
|
fieldsToObtain: {
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "New Deleted Record (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-record-deleted-instant",
|
|
9
9
|
description: "Emit new event when a record of the selected object type is deleted. [See the documentation](https://sforce.co/3msDDEE)",
|
|
10
|
-
version: "0.1.
|
|
10
|
+
version: "0.1.7",
|
|
11
11
|
methods: {
|
|
12
12
|
...common.methods,
|
|
13
13
|
generateWebhookMeta(data) {
|
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
name: "New Updated Record (Instant, of Selectable Type)",
|
|
8
8
|
key: "salesforce_rest_api-record-updated-instant",
|
|
9
9
|
description: "Emit new event when a record of the selected type is updated. [See the documentation](https://sforce.co/3yPSJZy)",
|
|
10
|
-
version: "0.2.
|
|
10
|
+
version: "0.2.8",
|
|
11
11
|
props: {
|
|
12
12
|
...common.props,
|
|
13
13
|
fields: {
|