@pipedream/salesforce_rest_api 1.14.0 → 2.0.0

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.
Files changed (87) hide show
  1. package/actions/add-contact-to-campaign/add-contact-to-campaign.mjs +1 -1
  2. package/actions/add-lead-to-campaign/add-lead-to-campaign.mjs +1 -1
  3. package/actions/common/base-create-update.mjs +2 -34
  4. package/actions/convert-soap-xml-to-json/convert-soap-xml-to-json.mjs +1 -1
  5. package/actions/create-account/create-account.mjs +1 -11
  6. package/actions/create-accounts-batch/create-accounts-batch.mjs +1 -1
  7. package/actions/create-attachment/create-attachment.mjs +8 -13
  8. package/actions/create-campaign/create-campaign.mjs +1 -17
  9. package/actions/create-case/create-case.mjs +1 -16
  10. package/actions/create-casecomment/create-casecomment.mjs +13 -13
  11. package/actions/create-contact/create-contact.mjs +1 -16
  12. package/actions/create-content-note/create-content-note.mjs +43 -33
  13. package/actions/create-crm-record/create-crm-record.mjs +2 -2
  14. package/actions/create-event/create-event.mjs +27 -25
  15. package/actions/create-lead/create-lead.mjs +1 -11
  16. package/actions/create-note/create-note.mjs +13 -9
  17. package/actions/create-opportunities-batch/create-opportunities-batch.mjs +1 -1
  18. package/actions/create-opportunity/create-opportunity.mjs +1 -11
  19. package/actions/create-record/create-record.mjs +15 -54
  20. package/actions/create-task/create-task.mjs +2 -21
  21. package/actions/create-user/create-user.mjs +1 -11
  22. package/actions/delete-crm-record/delete-crm-record.mjs +2 -2
  23. package/actions/delete-note/delete-note.mjs +1 -1
  24. package/actions/delete-opportunity/delete-opportunity.mjs +1 -1
  25. package/actions/delete-record/delete-record.mjs +1 -1
  26. package/actions/describe-object/describe-object.mjs +1 -1
  27. package/actions/find-records/find-records.mjs +1 -1
  28. package/actions/get-case/get-case.mjs +1 -1
  29. package/actions/get-current-user/get-current-user.mjs +1 -1
  30. package/actions/get-knowledge-articles/get-knowledge-articles.mjs +1 -1
  31. package/actions/get-knowledge-data-category-groups/get-knowledge-data-category-groups.mjs +1 -1
  32. package/actions/get-record-by-id/get-record-by-id.mjs +1 -1
  33. package/actions/get-related-records/get-related-records.mjs +1 -1
  34. package/actions/get-user/get-user.mjs +1 -1
  35. package/actions/get-user-info/get-user-info.mjs +1 -1
  36. package/actions/insert-blob-data/insert-blob-data.mjs +1 -1
  37. package/actions/list-case-comments/list-case-comments.mjs +1 -1
  38. package/actions/list-case-feed-items/list-case-feed-items.mjs +1 -1
  39. package/actions/list-cases/list-cases.mjs +1 -1
  40. package/actions/list-email-messages/list-email-messages.mjs +1 -1
  41. package/actions/list-email-templates/list-email-templates.mjs +1 -1
  42. package/actions/list-knowledge-articles/list-knowledge-articles.mjs +1 -1
  43. package/actions/list-object-fields/list-object-fields.mjs +1 -1
  44. package/actions/list-objects/list-objects.mjs +1 -1
  45. package/actions/post-feed-to-chatter/post-feed-to-chatter.mjs +1 -1
  46. package/actions/search-string/search-string.mjs +1 -1
  47. package/actions/send-email/send-email.mjs +1 -1
  48. package/actions/soql-query/soql-query.mjs +1 -1
  49. package/actions/soql-search/soql-search.mjs +1 -1
  50. package/actions/sosl-search/sosl-search.mjs +1 -1
  51. package/actions/text-search/text-search.mjs +1 -1
  52. package/actions/update-account/update-account.mjs +8 -22
  53. package/actions/update-accounts-batch/update-accounts-batch.mjs +1 -1
  54. package/actions/update-contact/update-contact.mjs +8 -27
  55. package/actions/update-content-note/update-content-note.mjs +8 -19
  56. package/actions/update-crm-record/update-crm-record.mjs +2 -2
  57. package/actions/update-email-template/update-email-template.mjs +13 -62
  58. package/actions/update-note/update-note.mjs +8 -19
  59. package/actions/update-opportunities-batch/update-opportunities-batch.mjs +1 -1
  60. package/actions/update-opportunity/update-opportunity.mjs +8 -22
  61. package/actions/update-record/update-record.mjs +24 -80
  62. package/actions/upsert-record/upsert-record.mjs +32 -76
  63. package/common/sobjects/attachment.mjs +2 -11
  64. package/common/sobjects/caseComment.mjs +2 -11
  65. package/common/sobjects/content-note.mjs +3 -11
  66. package/common/sobjects/event.mjs +3 -17
  67. package/common/sobjects/note.mjs +3 -12
  68. package/common/sobjects/opportunity.mjs +2 -10
  69. package/common/sobjects/user.mjs +2 -10
  70. package/package.json +1 -1
  71. package/salesforce_rest_api.app.mjs +0 -16
  72. package/sources/case-updated-instant/case-updated-instant.mjs +1 -1
  73. package/sources/common/common-feed.mjs +22 -17
  74. package/sources/common/common-new-record.mjs +19 -11
  75. package/sources/common/common-updated-record.mjs +21 -14
  76. package/sources/common/common.mjs +10 -1
  77. package/sources/email-template-updated-instant/email-template-updated-instant.mjs +1 -1
  78. package/sources/knowledge-article-updated-instant/knowledge-article-updated-instant.mjs +1 -1
  79. package/sources/new-case-instant/new-case-instant.mjs +1 -1
  80. package/sources/new-email-template-instant/new-email-template-instant.mjs +1 -1
  81. package/sources/new-feed-comment/new-feed-comment.mjs +1 -1
  82. package/sources/new-feed-item/new-feed-item.mjs +1 -1
  83. package/sources/new-knowledge-article-instant/new-knowledge-article-instant.mjs +1 -1
  84. package/sources/new-outbound-message/new-outbound-message.mjs +1 -1
  85. package/sources/new-record-instant/new-record-instant.mjs +1 -1
  86. package/sources/record-deleted-instant/record-deleted-instant.mjs +1 -1
  87. package/sources/record-updated-instant/record-updated-instant.mjs +1 -1
@@ -1,9 +1,5 @@
1
1
  // x-pd-ai: optimized
2
- import {
3
- convertFieldsToProps, getAdditionalFields,
4
- } from "../../common/props-utils.mjs";
5
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
6
- import { additionalFields } from "../common/base-create-update.mjs";
7
3
 
8
4
  export default {
9
5
  key: "salesforce_rest_api-upsert-record",
@@ -13,9 +9,9 @@ export default {
13
9
  + " Use **Create CRM Record** or **Update CRM Record** when you already know whether the record exists."
14
10
  + " "
15
11
  + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_upsert.htm)",
16
- version: "0.0.8",
12
+ version: "1.0.0",
17
13
  annotations: {
18
- destructiveHint: true,
14
+ destructiveHint: false,
19
15
  openWorldHint: true,
20
16
  readOnlyHint: false,
21
17
  },
@@ -23,17 +19,37 @@ export default {
23
19
  props: {
24
20
  salesforce,
25
21
  objectType: {
26
- propDefinition: [
27
- salesforce,
28
- "objectType",
29
- ],
30
- description: "The type of object to create a record of",
31
- reloadProps: true,
22
+ type: "string",
23
+ label: "Object Type",
24
+ description:
25
+ "The Salesforce object API name (e.g. `Account`, `Contact`). Use **List Objects** to discover custom object types (ending in `__c`).",
26
+ },
27
+ externalIdFieldName: {
28
+ type: "string",
29
+ label: "External ID Field",
30
+ description:
31
+ "API name of the field marked as External ID used to identify the record (e.g. `External_ID__c`). The field must be flagged as an External ID in Salesforce Object Manager. Run **List Object Fields** to find valid external-ID field API names.",
32
+ },
33
+ externalIdValue: {
34
+ type: "string",
35
+ label: "External ID Value",
36
+ description:
37
+ "The value of the external ID field. If a record with this value exists it is updated, otherwise a new one is created.",
38
+ },
39
+ updateOnly: {
40
+ type: "boolean",
41
+ label: "Update Only",
42
+ description: "If enabled, only update an existing record; do not create a new one (adds `?updateOnly=true`).",
43
+ optional: true,
44
+ },
45
+ fields: {
46
+ type: "object",
47
+ label: "Fields",
48
+ description:
49
+ "Field name -> value pairs for the record. Example: `{\"LastName\": \"Doe\", \"Email\": \"doe@example.com\"}`. Use **Describe Object** to discover valid field names.",
32
50
  },
33
51
  },
34
52
  methods: {
35
- getAdditionalFields,
36
- convertFieldsToProps,
37
53
  async upsertRecord(sobjectName, {
38
54
  externalIdFieldName, externalIdValue, ...args
39
55
  }) {
@@ -45,71 +61,14 @@ export default {
45
61
  });
46
62
  },
47
63
  },
48
- async additionalProps() {
49
- const { objectType } = this;
50
- const fields = await this.salesforce.getFieldsForObjectType(objectType);
51
-
52
- const requiredFields = fields.filter((field) => {
53
- return field.createable && field.updateable && !field.nillable && !field.defaultedOnCreate;
54
- });
55
-
56
- const externalIdFieldOptions = fields.filter((field) => field.externalId).map(({
57
- label, name,
58
- }) => ({
59
- label,
60
- value: name,
61
- }));
62
-
63
- const requiredFieldProps = this.convertFieldsToProps(requiredFields);
64
-
65
- return {
66
- docsInfo: {
67
- type: "alert",
68
- alertType: "info",
69
- content: `[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_${objectType.toLowerCase()}.htm) for information on all available fields.`,
70
- },
71
- externalIdFieldName: {
72
- type: "string",
73
- label: "External ID Field",
74
- description: "The field to use as the external ID to identify the record.",
75
- options: externalIdFieldOptions,
76
- },
77
- docsInfoExtId: {
78
- type: "alert",
79
- alertType: "info",
80
- content: "If you don't see any fields in the above list, you probably need to create one in Salesforce's Object Manager. Only a field marked as an external id field can be used to identify a record.",
81
- },
82
- externalIdValue: {
83
- type: "string",
84
- label: "External ID Value",
85
- description: "The value of the external ID field selected above. If a record with this value exists, it will be updated, otherwise a new one will be created.",
86
- },
87
- updateOnly: {
88
- type: "boolean",
89
- label: "Update Only",
90
- description: "If enabled, the action will only update an existing record, but not create one.",
91
- optional: true,
92
- },
93
- ...requiredFieldProps,
94
- additionalFields,
95
- };
96
- },
97
64
  async run({ $ }) {
98
- /* eslint-disable no-unused-vars */
99
65
  const {
100
- salesforce,
101
66
  objectType,
102
- getAdditionalFields: getData,
103
- convertFieldsToProps,
104
- docsInfo,
105
- docsInfoExtId,
106
- additionalFields,
107
67
  externalIdFieldName,
108
68
  externalIdValue,
109
69
  updateOnly,
110
- ...data
70
+ fields,
111
71
  } = this;
112
- /* eslint-enable no-unused-vars */
113
72
  const response = await this.upsertRecord(objectType, {
114
73
  $,
115
74
  externalIdFieldName,
@@ -117,10 +76,7 @@ export default {
117
76
  params: {
118
77
  updateOnly,
119
78
  },
120
- data: {
121
- ...data,
122
- ...getData(),
123
- },
79
+ data: fields,
124
80
  });
125
81
  $.export("$summary", `Successfully ${response.created
126
82
  ? "created"
@@ -1,5 +1,3 @@
1
- import salesforce from "../../salesforce_rest_api.app.mjs";
2
-
3
1
  export default {
4
2
  createProps: {
5
3
  Name: {
@@ -52,16 +50,9 @@ export default {
52
50
  optional: true,
53
51
  },
54
52
  OwnerId: {
55
- propDefinition: [
56
- salesforce,
57
- "recordId",
58
- () => ({
59
- objType: "User",
60
- nameField: "Name",
61
- }),
62
- ],
53
+ type: "string",
63
54
  label: "Owner ID",
64
- description: "ID of the user who owns the attachment.",
55
+ description: "ID of the user who owns the attachment (Salesforce's 15- or 18-character record ID, e.g. `005XX000001SvR2`). Use **SOQL Query** to find the User ID.",
65
56
  optional: true,
66
57
  },
67
58
  },
@@ -1,5 +1,3 @@
1
- import salesforce from "../../salesforce_rest_api.app.mjs";
2
-
3
1
  export default {
4
2
  initialProps: {
5
3
  CommentBody: {
@@ -9,16 +7,9 @@ export default {
9
7
  optional: true,
10
8
  },
11
9
  ParentId: {
12
- propDefinition: [
13
- salesforce,
14
- "recordId",
15
- () => ({
16
- objType: "Case",
17
- nameField: "CaseNumber",
18
- }),
19
- ],
10
+ type: "string",
20
11
  label: "Parent Case ID",
21
- description: "ID of the parent Case.",
12
+ description: "ID of the parent Case (Salesforce's 15- or 18-character record ID, e.g. `500XX000001SvR2`). Use **SOQL Query** to find the Case ID.",
22
13
  },
23
14
  IsPublished: {
24
15
  type: "boolean",
@@ -1,18 +1,10 @@
1
- import salesforce from "../../salesforce_rest_api.app.mjs";
2
-
3
1
  export default {
4
2
  initialProps: {
5
3
  OwnerId: {
6
- propDefinition: [
7
- salesforce,
8
- "recordId",
9
- () => ({
10
- objType: "User",
11
- nameField: "Name",
12
- }),
13
- ],
4
+ type: "string",
14
5
  label: "Owner ID",
15
- description: "ID of the user who owns the note.",
6
+ description: "ID of the user who owns the note (Salesforce's 15- or 18-character record ID, e.g. `005XX000001SvR2`). Use **SOQL Query** to find the User ID.",
7
+ optional: true,
16
8
  },
17
9
  Title: {
18
10
  type: "string",
@@ -6,24 +6,10 @@ import commonProps from "../props-async-options.mjs";
6
6
  export default {
7
7
  initialProps: {
8
8
  AcceptedEventInviteeIds: {
9
- ...commonProps.ContactOrLeadIds,
9
+ type: "string[]",
10
10
  label: "Accepted Event Invitee IDs",
11
- description: "One or more Contact or Lead IDs who accepted this event.",
12
- optional: true,
13
- async options() {
14
- const contacts = await this.salesforce.listRecordOptions({
15
- objType: "Contact",
16
- nameField: "Name",
17
- });
18
- const leads = await this.salesforce.listRecordOptions({
19
- objType: "Lead",
20
- nameField: "Name",
21
- });
22
- return [
23
- ...(contacts ?? []),
24
- ...(leads ?? []),
25
- ];
26
- },
11
+ description: "One or more Contact or Lead IDs who accepted this event (Salesforce's 15- or 18-character record ID, e.g. `003XX000004TmiQ` for a Contact). Use **SOQL Query** to find Contact or Lead IDs.",
12
+ optional: true,
27
13
  },
28
14
  ActivityDate: {
29
15
  type: "string",
@@ -1,5 +1,3 @@
1
- import salesforce from "../../salesforce_rest_api.app.mjs";
2
-
3
1
  export default {
4
2
  initialProps: {
5
3
  Body: {
@@ -10,20 +8,13 @@ export default {
10
8
  IsPrivate: {
11
9
  type: "boolean",
12
10
  label: "Private",
13
- description: "If true, only the note owner or a user with the Modify All Data permission can view the note or query it via the API.",
11
+ description: "If true, only the note owner or a user with the \"Modify All Data\" permission can view the note or query it via the API.",
14
12
  optional: true,
15
13
  },
16
14
  OwnerId: {
17
- propDefinition: [
18
- salesforce,
19
- "recordId",
20
- () => ({
21
- objType: "User",
22
- nameField: "Name",
23
- }),
24
- ],
15
+ type: "string",
25
16
  label: "Owner ID",
26
- description: "ID of the user who owns the note.",
17
+ description: "ID of the user who owns the note (Salesforce's 15- or 18-character record ID, e.g. `005XX000001SvR2`). Use **SOQL Query** to find the User ID.",
27
18
  optional: true,
28
19
  },
29
20
  ParentId: {
@@ -1,21 +1,13 @@
1
1
  import { RECORD_SOURCE_OPTIONS } from "../constants-props.mjs";
2
2
  import commonProps from "../props-async-options.mjs";
3
- import salesforce from "../../salesforce_rest_api.app.mjs";
4
3
 
5
4
  export default {
6
5
  createProps: {
7
6
  ContactId: {
8
- propDefinition: [
9
- salesforce,
10
- "recordId",
11
- () => ({
12
- objType: "Contact",
13
- nameField: "Name",
14
- }),
15
- ],
7
+ type: "string",
16
8
  label: "Contact ID",
17
9
  description:
18
- "ID of the contact associated with this opportunity, set as the primary contact.",
10
+ "ID of the contact associated with this opportunity, set as the primary contact (Salesforce's 15- or 18-character record ID, e.g. `003XX000004TmiQ`). Use **SOQL Query** to find the Contact ID.",
19
11
  optional: true,
20
12
  },
21
13
  },
@@ -1,4 +1,3 @@
1
- import salesforce from "../../salesforce_rest_api.app.mjs";
2
1
  import {
3
2
  EMAIL_ENCODING_OPTIONS,
4
3
  GEOCODE_ACCURACY_OPTIONS,
@@ -80,17 +79,10 @@ export default {
80
79
  options: LOCALE_OPTIONS,
81
80
  },
82
81
  ProfileId: {
83
- propDefinition: [
84
- salesforce,
85
- "recordId",
86
- () => ({
87
- objType: "Profile",
88
- nameField: "Name",
89
- }),
90
- ],
82
+ type: "string",
91
83
  label: "Profile ID",
92
84
  description:
93
- "ID of the user's Profile. Use this value to cache metadata based on profile.",
85
+ "ID of the user's Profile (Salesforce's 15- or 18-character record ID, e.g. `00eXX000001SvR2`). Use **SOQL Query** to find the Profile ID.",
94
86
  },
95
87
  TimeZoneSidKey: {
96
88
  type: "string",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/salesforce_rest_api",
3
- "version": "1.14.0",
3
+ "version": "2.0.0",
4
4
  "description": "Pipedream Salesforce (REST API) Components",
5
5
  "main": "salesforce_rest_api.app.mjs",
6
6
  "keywords": [
@@ -55,15 +55,6 @@ export default {
55
55
  return fields.filter(filter).map(({ name }) => name);
56
56
  },
57
57
  },
58
- fieldsToUpdate: {
59
- type: "string[]",
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
- },
66
- },
67
58
  fieldsToObtain: {
68
59
  type: "string[]",
69
60
  label: "Fields to Obtain",
@@ -73,13 +64,6 @@ export default {
73
64
  return fields.map(({ name }) => name);
74
65
  },
75
66
  },
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,
82
- },
83
67
  },
84
68
  methods: {
85
69
  _authToken() {
@@ -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",
10
+ version: "0.0.12",
11
11
  props: {
12
12
  salesforce: common.props.salesforce,
13
13
  db: "$.service.db",
@@ -43,24 +43,29 @@ export default {
43
43
  const nameField = await this.salesforce.getNameFieldForObjectType(objectType);
44
44
  this.setNameField(nameField);
45
45
 
46
- const extraConditions = await this._buildExtraConditions();
47
- const { records } = await this.query({
48
- query: `SELECT Id FROM ${objectType} WHERE Id != null ${extraConditions} ORDER BY CreatedDate DESC LIMIT ${DEPLOY_HISTORICAL_LIMIT}`,
49
- });
46
+ try {
47
+ const extraConditions = await this._buildExtraConditions();
48
+ const { records } = await this.query({
49
+ query: `SELECT Id FROM ${objectType} WHERE Id != null ${extraConditions} ORDER BY CreatedDate DESC LIMIT ${DEPLOY_HISTORICAL_LIMIT}`,
50
+ });
50
51
 
51
- // Emit oldest-first so historical events are delivered chronologically,
52
- // matching the timer polling path.
53
- for (const record of [
54
- ...records,
55
- ].reverse()) {
56
- const object = await this.salesforce.getSObject(objectType, record.Id);
57
- const event = {
58
- body: {
59
- "New": object,
60
- "UserId": record.Id,
61
- },
62
- };
63
- await this.processWebhookEvent(event);
52
+ // Emit oldest-first so historical events are delivered chronologically,
53
+ // matching the timer polling path.
54
+ for (const record of [
55
+ ...records,
56
+ ].reverse()) {
57
+ const object = await this.salesforce.getSObject(objectType, record.Id);
58
+ const event = {
59
+ body: {
60
+ "New": object,
61
+ "UserId": record.Id,
62
+ },
63
+ };
64
+ await this.processWebhookEvent(event);
65
+ }
66
+ } catch (err) {
67
+ console.log("Error seeding historical records during deploy:", err);
68
+ console.log("The source will still be created and will emit new records going forward.");
64
69
  }
65
70
  },
66
71
  },
@@ -1,6 +1,7 @@
1
1
  import startCase from "lodash/startCase.js";
2
2
  import { v4 as uuidv4 } from "uuid";
3
3
  import common from "../common/common.mjs";
4
+ import constants from "../../common/constants.mjs";
4
5
 
5
6
  export default {
6
7
  ...common,
@@ -12,17 +13,24 @@ export default {
12
13
  this.setNameField(nameField);
13
14
 
14
15
  // emit historical events
15
- const { recentItems } = await this.salesforce.listSObjectTypeIds(objectType);
16
- const ids = recentItems.map((item) => item.Id);
17
- for (const id of ids.slice(-25)) {
18
- const object = await this.salesforce.getSObject(objectType, id);
19
- const event = {
20
- body: {
21
- "New": object,
22
- "UserId": id,
23
- },
24
- };
25
- this.processWebhookEvent(event);
16
+ try {
17
+ const { records } = await this.query({
18
+ query: `SELECT Id FROM ${objectType} ORDER BY ${constants.FIELD_NAME.CREATED_DATE} DESC LIMIT ${constants.DEPLOY_HISTORICAL_LIMIT}`,
19
+ });
20
+ const ids = records.map((r) => r.Id);
21
+ for (const id of ids.slice(-constants.DEPLOY_HISTORICAL_LIMIT).reverse()) {
22
+ const object = await this.salesforce.getSObject(objectType, id);
23
+ const event = {
24
+ body: {
25
+ "New": object,
26
+ "UserId": id,
27
+ },
28
+ };
29
+ this.processWebhookEvent(event);
30
+ }
31
+ } catch (err) {
32
+ console.log("Error seeding historical records during deploy:", err);
33
+ console.log("The source will still be created and will emit new records going forward.");
26
34
  }
27
35
  },
28
36
  async activate() {
@@ -13,20 +13,27 @@ export default {
13
13
  this.setNameField(nameField);
14
14
 
15
15
  if (!this.skipFirstRun) {
16
- const { recentItems } = await this.salesforce.listSObjectTypeIds(objectType);
17
- const ids = recentItems.map((item) => item.Id);
18
-
19
- for (const id of ids.slice(-25)) {
20
- const object = await this.salesforce.getSObject(objectType, id);
21
-
22
- const event = {
23
- body: {
24
- "New": object,
25
- "UserId": id,
26
- },
27
- };
28
- const meta = this.generateWebhookMeta(event);
29
- this.$emit(event.body, meta);
16
+ try {
17
+ const { records } = await this.query({
18
+ query: `SELECT Id FROM ${objectType} ORDER BY ${constants.FIELD_NAME.LAST_MODIFIED_DATE} DESC LIMIT ${constants.DEPLOY_HISTORICAL_LIMIT}`,
19
+ });
20
+ const ids = records.map((r) => r.Id);
21
+
22
+ for (const id of ids.slice(-constants.DEPLOY_HISTORICAL_LIMIT).reverse()) {
23
+ const object = await this.salesforce.getSObject(objectType, id);
24
+
25
+ const event = {
26
+ body: {
27
+ "New": object,
28
+ "UserId": id,
29
+ },
30
+ };
31
+ const meta = this.generateWebhookMeta(event);
32
+ this.$emit(event.body, meta);
33
+ }
34
+ } catch (err) {
35
+ console.log("Error seeding historical records during deploy:", err);
36
+ console.log("The source will still be created and will emit updated records going forward.");
30
37
  }
31
38
  }
32
39
  },
@@ -89,9 +89,18 @@ export default {
89
89
  this.db.set("latestDateCovered", latestDateCovered);
90
90
  },
91
91
  getNameField() {
92
- return this.db.get("nameField");
92
+ // Cache in memory for the lifetime of this execution. The deploy hook emits
93
+ // up to DEPLOY_HISTORICAL_LIMIT historical events, each building meta via
94
+ // getNameField(); without this the db is read once per event (e.g. 25x).
95
+ if (this._nameField === undefined) {
96
+ this._nameField = this.db.get("nameField");
97
+ }
98
+ return this._nameField;
93
99
  },
94
100
  setNameField(nameField) {
101
+ // Keep the in-memory cache coherent with the persisted value so a read after
102
+ // a write doesn't fall back to db.get.
103
+ this._nameField = nameField;
95
104
  this.db.set("nameField", nameField);
96
105
  },
97
106
  processTimerEvent() {
@@ -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",
10
+ version: "0.0.12",
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",
10
+ version: "0.0.12",
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",
10
+ version: "0.0.12",
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",
10
+ version: "0.0.12",
11
11
  props: {
12
12
  salesforce: common.props.salesforce,
13
13
  db: "$.service.db",
@@ -12,7 +12,7 @@ export default {
12
12
  name: "New Chatter Feed Comment (Instant or Polling)",
13
13
  key: "salesforce_rest_api-new-feed-comment",
14
14
  description: "Emit new events for each Chatter FeedComment (reply) created in Salesforce, polling `FeedComment` via SOQL on `CreatedDate`. Use this to react to comments on Chatter posts, since Chatter activity does not update the parent record's `LastModifiedDate`. The payload includes both `ParentId` (a polymorphic reference to the feed's parent - either a record feed, e.g. a Case ID starting with `500`, or a User feed) and `FeedItemId` (the ID of the FeedItem the comment belongs to) - these are distinct fields; do not confuse them. Set `parentObjectType` to a parent object API name (e.g. `Case`) to append `AND Parent.Type = '<value>'` to the SOQL WHERE clause. Set `excludeSelf` to `true` to drop comments authored by the connected integration user. Note: querying FeedComment without a parent filter requires the `View All Data` permission on the connected user. Attempts instant delivery via webhook and falls back to timer polling automatically. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_feedcomment.htm)",
15
- version: "0.0.2",
15
+ version: "0.0.4",
16
16
  props: {
17
17
  ...common.props,
18
18
  parentObjectType: {
@@ -12,7 +12,7 @@ export default {
12
12
  name: "New Chatter Feed Item (Instant or Polling)",
13
13
  key: "salesforce_rest_api-new-feed-item",
14
14
  description: "Emit new events for each Chatter FeedItem (post) created in Salesforce, polling `FeedItem` via SOQL on `CreatedDate`. Use this to react to Chatter posts on Cases and other records, since Chatter activity does not update the parent record's `LastModifiedDate` (so **New Record (Instant, of Selectable Type)** and **New Case (Instant, of Selectable Type)** never emit for it). Set `parentObjectType` to the parent object's API name (e.g. `Case`, `Opportunity`) to only emit posts whose parent record is of that type. Set `excludeSelf` to `true` to drop posts authored by the connected integration user. Note: `Body` is null for system-generated post types (e.g. `TrackedChange`). Attempts instant delivery via webhook and falls back to timer polling automatically when the Streaming API does not support this object. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_feeditem.htm)",
15
- version: "0.0.2",
15
+ version: "0.0.4",
16
16
  props: {
17
17
  ...common.props,
18
18
  parentObjectType: {
@@ -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",
10
+ version: "0.0.12",
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.13",
9
+ version: "0.1.14",
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.10",
9
+ version: "0.2.12",
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.9",
10
+ version: "0.1.11",
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",
10
+ version: "0.2.12",
11
11
  props: {
12
12
  ...common.props,
13
13
  fields: {