@pipedream/salesforce_rest_api 1.13.0 → 1.14.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.
Files changed (79) hide show
  1. package/actions/add-contact-to-campaign/add-contact-to-campaign.mjs +7 -2
  2. package/actions/add-lead-to-campaign/add-lead-to-campaign.mjs +7 -2
  3. package/actions/convert-soap-xml-to-json/convert-soap-xml-to-json.mjs +7 -2
  4. package/actions/create-account/create-account.mjs +7 -2
  5. package/actions/create-accounts-batch/create-accounts-batch.mjs +8 -2
  6. package/actions/create-attachment/create-attachment.mjs +7 -2
  7. package/actions/create-campaign/create-campaign.mjs +7 -2
  8. package/actions/create-case/create-case.mjs +7 -2
  9. package/actions/create-casecomment/create-casecomment.mjs +7 -2
  10. package/actions/create-contact/create-contact.mjs +7 -2
  11. package/actions/create-content-note/create-content-note.mjs +9 -2
  12. package/actions/create-crm-record/create-crm-record.mjs +5 -3
  13. package/actions/create-event/create-event.mjs +7 -2
  14. package/actions/create-lead/create-lead.mjs +7 -2
  15. package/actions/create-note/create-note.mjs +7 -2
  16. package/actions/create-opportunities-batch/create-opportunities-batch.mjs +9 -2
  17. package/actions/create-opportunity/create-opportunity.mjs +7 -2
  18. package/actions/create-record/create-record.mjs +7 -2
  19. package/actions/create-task/create-task.mjs +7 -2
  20. package/actions/create-user/create-user.mjs +7 -2
  21. package/actions/delete-crm-record/delete-crm-record.mjs +6 -4
  22. package/actions/delete-note/delete-note.mjs +7 -2
  23. package/actions/delete-opportunity/delete-opportunity.mjs +7 -2
  24. package/actions/delete-record/delete-record.mjs +7 -2
  25. package/actions/describe-object/describe-object.mjs +5 -3
  26. package/actions/find-records/find-records.mjs +49 -12
  27. package/actions/get-case/get-case.mjs +7 -2
  28. package/actions/get-current-user/get-current-user.mjs +2 -1
  29. package/actions/get-knowledge-articles/get-knowledge-articles.mjs +7 -2
  30. package/actions/get-knowledge-data-category-groups/get-knowledge-data-category-groups.mjs +7 -2
  31. package/actions/get-record-by-id/get-record-by-id.mjs +7 -2
  32. package/actions/get-related-records/get-related-records.mjs +5 -3
  33. package/actions/get-user/get-user.mjs +7 -2
  34. package/actions/get-user-info/get-user-info.mjs +5 -3
  35. package/actions/insert-blob-data/insert-blob-data.mjs +7 -2
  36. package/actions/list-case-comments/list-case-comments.mjs +51 -7
  37. package/actions/list-case-feed-items/list-case-feed-items.mjs +73 -0
  38. package/actions/list-cases/list-cases.mjs +131 -0
  39. package/actions/list-email-messages/list-email-messages.mjs +57 -10
  40. package/actions/list-email-templates/list-email-templates.mjs +45 -6
  41. package/actions/list-knowledge-articles/list-knowledge-articles.mjs +45 -6
  42. package/actions/list-object-fields/list-object-fields.mjs +7 -2
  43. package/actions/list-objects/list-objects.mjs +5 -3
  44. package/actions/post-feed-to-chatter/post-feed-to-chatter.mjs +7 -2
  45. package/actions/search-string/search-string.mjs +7 -2
  46. package/actions/send-email/send-email.mjs +7 -2
  47. package/actions/soql-query/soql-query.mjs +5 -3
  48. package/actions/soql-search/soql-search.mjs +7 -2
  49. package/actions/sosl-search/sosl-search.mjs +7 -2
  50. package/actions/text-search/text-search.mjs +5 -3
  51. package/actions/update-account/update-account.mjs +7 -2
  52. package/actions/update-accounts-batch/update-accounts-batch.mjs +9 -2
  53. package/actions/update-contact/update-contact.mjs +7 -2
  54. package/actions/update-content-note/update-content-note.mjs +9 -2
  55. package/actions/update-crm-record/update-crm-record.mjs +5 -3
  56. package/actions/update-email-template/update-email-template.mjs +7 -2
  57. package/actions/update-note/update-note.mjs +7 -2
  58. package/actions/update-opportunities-batch/update-opportunities-batch.mjs +9 -2
  59. package/actions/update-opportunity/update-opportunity.mjs +7 -2
  60. package/actions/update-record/update-record.mjs +7 -2
  61. package/actions/upsert-record/upsert-record.mjs +7 -2
  62. package/common/constants.mjs +52 -0
  63. package/common/soql.mjs +96 -0
  64. package/package.json +1 -1
  65. package/sources/case-updated-instant/case-updated-instant.mjs +1 -1
  66. package/sources/common/common-feed.mjs +22 -17
  67. package/sources/common/common-new-record.mjs +19 -11
  68. package/sources/common/common-updated-record.mjs +21 -14
  69. package/sources/common/common.mjs +10 -1
  70. package/sources/email-template-updated-instant/email-template-updated-instant.mjs +1 -1
  71. package/sources/knowledge-article-updated-instant/knowledge-article-updated-instant.mjs +1 -1
  72. package/sources/new-case-instant/new-case-instant.mjs +1 -1
  73. package/sources/new-email-template-instant/new-email-template-instant.mjs +1 -1
  74. package/sources/new-feed-comment/new-feed-comment.mjs +1 -1
  75. package/sources/new-feed-item/new-feed-item.mjs +1 -1
  76. package/sources/new-knowledge-article-instant/new-knowledge-article-instant.mjs +1 -1
  77. package/sources/new-record-instant/new-record-instant.mjs +1 -1
  78. package/sources/record-deleted-instant/record-deleted-instant.mjs +1 -1
  79. package/sources/record-updated-instant/record-updated-instant.mjs +1 -1
@@ -1,10 +1,18 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
3
+ import constants from "../../common/constants.mjs";
4
+ import {
5
+ buildFieldList, truncationNote,
6
+ } from "../../common/soql.mjs";
2
7
 
3
8
  export default {
4
9
  key: "salesforce_rest_api-list-knowledge-articles",
5
10
  name: "List Knowledge Articles",
6
- description: "Lists all knowledge articles. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_knowledgearticle.htm)",
7
- version: "0.0.5",
11
+ description: "List Salesforce Knowledge articles, newest first."
12
+ + " Returns the article container records (`KnowledgeArticle`), not the published article bodies - use **Get Knowledge Articles** to read article content, and **List Knowledge Data Category Groups** to discover the categories articles are filed under."
13
+ + " This can return a lot of records on a mature org, so set `Limit`."
14
+ + " [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_knowledgearticle.htm)",
15
+ version: "0.1.0",
8
16
  annotations: {
9
17
  destructiveHint: false,
10
18
  openWorldHint: true,
@@ -13,16 +21,47 @@ export default {
13
21
  type: "action",
14
22
  props: {
15
23
  salesforce,
24
+ fields: {
25
+ propDefinition: [
26
+ salesforce,
27
+ "fieldsToObtain",
28
+ () => ({
29
+ objType: constants.OBJECT_TYPE.KNOWLEDGE_ARTICLE,
30
+ }),
31
+ ],
32
+ label: "Fields",
33
+ description: "The KnowledgeArticle fields to return. Defaults to every field on the object. `Id` is always returned.",
34
+ optional: true,
35
+ },
36
+ limit: {
37
+ type: "integer",
38
+ label: "Limit",
39
+ description: `The maximum number of articles to return. Valid values are integers from 1 through ${constants.MAX_LIMIT}. Omit to return every article Salesforce sends in one batch.`,
40
+ min: 1,
41
+ max: constants.MAX_LIMIT,
42
+ optional: true,
43
+ },
16
44
  },
17
45
  async run({ $ }) {
18
- const fields = (await this.salesforce.getFieldsForObjectType("KnowledgeArticle")).map(({ name }) => name);
19
- const query = `SELECT ${fields.join(", ")} FROM KnowledgeArticle`;
46
+ const allFields = (await this.salesforce
47
+ .getFieldsForObjectType(constants.OBJECT_TYPE.KNOWLEDGE_ARTICLE))
48
+ .map(({ name }) => name);
49
+ const fields = buildFieldList(this.fields, allFields);
20
50
 
21
- const { records } = await this.salesforce.query({
51
+ let query = `SELECT ${fields.join(", ")} FROM ${constants.OBJECT_TYPE.KNOWLEDGE_ARTICLE}`
52
+ + " ORDER BY CreatedDate DESC, Id DESC";
53
+ if (this.limit) {
54
+ query += ` LIMIT ${this.limit}`;
55
+ }
56
+
57
+ const response = await this.salesforce.query({
22
58
  $,
23
59
  query,
24
60
  });
25
- $.export("$summary", `Sucessfully retrieved ${records.length} knowledge articles`);
61
+ const { records } = response;
62
+ $.export("$summary", `Successfully retrieved ${records.length} knowledge article${records.length === 1
63
+ ? ""
64
+ : "s"}.${truncationNote(response, records.length)}`);
26
65
  return records;
27
66
  },
28
67
  };
@@ -1,10 +1,15 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
 
3
4
  export default {
4
5
  key: "salesforce_rest_api-list-object-fields",
5
6
  name: "List Object Fields",
6
- description: "Lists all fields for a given object type. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_describe.htm)",
7
- version: "0.0.2",
7
+ description: "List the field names for a Salesforce object type."
8
+ + " Use this to discover valid field names before calling **Find Records**, **SOQL Query** or any create/update action."
9
+ + " Use **Describe Object** instead when you also need field types, required flags and picklist values."
10
+ + " "
11
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_describe.htm)",
12
+ version: "0.0.3",
8
13
  type: "action",
9
14
  annotations: {
10
15
  destructiveHint: false,
@@ -1,4 +1,4 @@
1
- // vandelay-test-dr
1
+ // x-pd-ai: optimized
2
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
3
3
 
4
4
  export default {
@@ -9,8 +9,10 @@ export default {
9
9
  + " Use when the user references an object type you're not sure about, or to discover custom objects."
10
10
  + " Custom objects end in `__c`."
11
11
  + " Standard CRM objects: Account, Contact, Lead, Opportunity, Case, Task, Event, Campaign, User."
12
- + " Use **Describe Object** to get field details for a specific object type.",
13
- version: "0.0.1",
12
+ + " Use **Describe Object** to get field details for a specific object type."
13
+ + " "
14
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_describeGlobal.htm)",
15
+ version: "0.0.2",
14
16
  type: "action",
15
17
  annotations: {
16
18
  readOnlyHint: true,
@@ -1,11 +1,16 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
 
3
4
  export default {
4
5
  key: "salesforce_rest_api-post-feed-to-chatter",
5
6
  name: "Post a Message to Chatter Feed",
6
7
  description:
7
- "Post a feed item in Chatter. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/quickreference_post_feed_item.htm)",
8
- version: "0.1.4",
8
+ "Post a Chatter message to a Salesforce record's feed."
9
+ + " Use **List Case Feed Items** to read a case feed, or **Create Case Comment** to add a case comment instead of a Chatter post."
10
+ + " The message is built from segments - a plain string becomes text, and `{ \"type\": \"Mention\", \"username\": \"jsmith\" }` mentions a user."
11
+ + " "
12
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.chatterapi.meta/chatterapi/quickreference_post_feed_item.htm)",
13
+ version: "0.1.5",
9
14
  annotations: {
10
15
  destructiveHint: false,
11
16
  openWorldHint: true,
@@ -1,10 +1,15 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
 
3
4
  export default {
4
5
  key: "salesforce_rest_api-search-string",
5
6
  name: "Search Object Records",
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.8",
7
+ description: "Search for records of one object type using a parameterized SOSL search."
8
+ + " Use **Text Search** to search across several object types at once, or **SOQL Query** for exact field filters."
9
+ + " SOSL matches indexed text fields, so it finds partial words but will not filter on numeric or date criteria."
10
+ + " "
11
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_search_parameterized_get.htm)",
12
+ version: "0.0.9",
8
13
  annotations: {
9
14
  destructiveHint: false,
10
15
  openWorldHint: true,
@@ -1,10 +1,15 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
 
3
4
  export default {
4
5
  key: "salesforce_rest_api-send-email",
5
6
  name: "Send Email",
6
- description: "Sends an email. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_action.meta/api_action/actions_obj_email_simple.htm)",
7
- version: "0.1.0",
7
+ description: "Send an email through Salesforce."
8
+ + " Use **List Email Templates** to find a template ID first when sending templated mail."
9
+ + " Sent mail is logged against the related record - use **List Email Messages** to read it back."
10
+ + " "
11
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_action.meta/api_action/actions_obj_email_simple.htm)",
12
+ version: "0.1.1",
8
13
  annotations: {
9
14
  destructiveHint: false,
10
15
  openWorldHint: true,
@@ -1,4 +1,4 @@
1
- // vandelay-test-dr
1
+ // x-pd-ai: optimized
2
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
3
3
 
4
4
  export default {
@@ -25,8 +25,10 @@ export default {
25
25
  + "\n- Sorting/limits: `ORDER BY CreatedDate DESC LIMIT 10`"
26
26
  + "\n\n"
27
27
  + "**Always include `Id` in SELECT.** Include a clickable Salesforce link for every record"
28
- + " using the format `{instanceUrl}/lightning/r/{objectType}/{Id}/view` (get `instanceUrl` from **Get User Info**).",
29
- version: "0.0.1",
28
+ + " using the format `{instanceUrl}/lightning/r/{objectType}/{Id}/view` (get `instanceUrl` from **Get User Info**)."
29
+ + " "
30
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_query.htm)",
31
+ version: "0.0.2",
30
32
  type: "action",
31
33
  annotations: {
32
34
  readOnlyHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
  import { docsInfo } from "../sosl-search/sosl-search.mjs";
3
4
 
@@ -6,8 +7,12 @@ const docsLink = "https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.me
6
7
  export default {
7
8
  key: "salesforce_rest_api-soql-search",
8
9
  name: "SOQL Query (Object Query)",
9
- description: `Executes a [Salesforce Object Query Language (SOQL)](${docsLink}) query-based, SQL-like search.`,
10
- version: "0.2.13",
10
+ description: "Run a SOQL query with guided prompts for the object, fields and filter."
11
+ + " Prefer **SOQL Query** for agent and API use - it accepts a complete query string and pages through every result, while this action returns only the first batch."
12
+ + " SOQL filters on exact field values; use **Text Search** for keyword search."
13
+ + " "
14
+ + `[See the documentation](${docsLink})`,
15
+ version: "0.2.14",
11
16
  annotations: {
12
17
  destructiveHint: false,
13
18
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
2
3
 
3
4
  const docsLink = "https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_sosl_examples.htm";
@@ -11,8 +12,12 @@ export const docsInfo = {
11
12
  export default {
12
13
  key: "salesforce_rest_api-sosl-search",
13
14
  name: "SOSL Search (Object Search)",
14
- description: `Executes a [Salesforce Object Search Language (SOSL)](${docsLink}) text-based search query.`,
15
- version: "0.2.12",
15
+ description: "Run a SOSL text search with guided prompts."
16
+ + " Prefer **Text Search** for agent and API use - it takes a plain keyword and searches several object types at once."
17
+ + " SOSL matches indexed text fields, so it finds partial words but will not filter on numeric or date criteria."
18
+ + " "
19
+ + `[See the documentation](${docsLink})`,
20
+ version: "0.2.13",
16
21
  annotations: {
17
22
  destructiveHint: false,
18
23
  openWorldHint: true,
@@ -1,4 +1,4 @@
1
- // vandelay-test-dr
1
+ // x-pd-ai: optimized
2
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
3
3
 
4
4
  export default {
@@ -8,8 +8,10 @@ export default {
8
8
  "Search Salesforce records by keyword across multiple object types simultaneously."
9
9
  + " Use for free-text search when the user mentions a name, term, or keyword without specifying an object type."
10
10
  + " Use **SOQL Query** instead for structured queries on a single object type with specific conditions."
11
- + " Results are grouped by object type.",
12
- version: "0.0.1",
11
+ + " Results are grouped by object type."
12
+ + " "
13
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_search.htm)",
14
+ version: "0.0.2",
13
15
  type: "action",
14
16
  annotations: {
15
17
  readOnlyHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import common, { getProps } from "../common/base-create-update.mjs";
2
3
  import account from "../../common/sobjects/account.mjs";
3
4
  import { docsLink } from "../create-account/create-account.mjs";
@@ -14,8 +15,12 @@ export default {
14
15
  ...common,
15
16
  key: "salesforce_rest_api-update-account",
16
17
  name: "Update Account",
17
- description: `Updates a Salesforce account. [See the documentation](${docsLink})`,
18
- version: "0.3.6",
18
+ description: "Update fields on an existing Salesforce account."
19
+ + " Only the fields you supply change; everything else is left as-is."
20
+ + " Use **Find Records** on `Account` to get the record ID first."
21
+ + " "
22
+ + `[See the documentation](${docsLink})`,
23
+ version: "0.3.7",
19
24
  annotations: {
20
25
  destructiveHint: true,
21
26
  openWorldHint: true,
@@ -1,11 +1,18 @@
1
+ // x-pd-ai: optimized
1
2
  import common from "../common/batch-operation.mjs";
2
3
 
3
4
  export default {
4
5
  ...common,
5
6
  key: "salesforce_rest_api-update-accounts-batch",
6
7
  name: "Update Accounts (Batch)",
7
- description: "Update multiple Accounts in Salesforce using Bulk API 2.0. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_understanding_bulk2_ingest.htm)",
8
- version: "0.0.5",
8
+ description: "Update many Salesforce accounts in one job using Bulk API 2.0."
9
+ + " Use this instead of **Update Account** when updating more than roughly 200 records - it is asynchronous and returns a job ID, not the updated records."
10
+ + " Every row must include the record `Id` of the account to update."
11
+ + " Input is a CSV file - supply a path under `/tmp` or a URL to download it from, with a header row of Salesforce field API names."
12
+ + " Poll the job in Salesforce to confirm completion; a successful response means the job was accepted, not that every row loaded."
13
+ + " "
14
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_understanding_bulk2_ingest.htm)",
15
+ version: "0.0.6",
9
16
  annotations: {
10
17
  destructiveHint: true,
11
18
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import common, { getProps } from "../common/base-create-update.mjs";
2
3
  import contact from "../../common/sobjects/contact.mjs";
3
4
  import { docsLink } from "../create-contact/create-contact.mjs";
@@ -15,8 +16,12 @@ export default {
15
16
  ...common,
16
17
  key: "salesforce_rest_api-update-contact",
17
18
  name: "Update Contact",
18
- description: `Updates a contact. [See the documentation](${docsLink})`,
19
- version: "0.3.6",
19
+ description: "Update fields on an existing Salesforce contact."
20
+ + " Only the fields you supply change; everything else is left as-is."
21
+ + " Use **Find Records** on `Contact` to get the record ID first."
22
+ + " "
23
+ + `[See the documentation](${docsLink})`,
24
+ version: "0.3.7",
20
25
  annotations: {
21
26
  destructiveHint: true,
22
27
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import common, { getProps } from "../common/base-create-update.mjs";
2
3
  import contentNote from "../../common/sobjects/content-note.mjs";
3
4
  import { NOTE_INFO_PROP } from "../../common/props-info.mjs";
@@ -16,8 +17,14 @@ export default {
16
17
  ...common,
17
18
  key: "salesforce_rest_api-update-content-note",
18
19
  name: "Update Content Note",
19
- description: `Updates an enhanced Salesforce content note, which can include formatted text and is part of Salesforce Files. [See the documentation](${docsLink}) and [Set Up Notes](https://help.salesforce.com/s/articleView?id=sales.notes_admin_setup.htm&type=5).`,
20
- version: "0.0.3",
20
+ description: "Update an enhanced Salesforce content note (rich text, stored in Salesforce Files)."
21
+ + " Use **Update Note** instead for classic plain-text notes - the two are different objects."
22
+ + " Supplying `Content` replaces the note body outright rather than appending to it."
23
+ + " "
24
+ + "Notes must be enabled in the org first - see [Set Up Notes](https://help.salesforce.com/s/articleView?id=sales.notes_admin_setup.htm&type=5)."
25
+ + " "
26
+ + `[See the documentation](${docsLink})`,
27
+ version: "0.0.4",
21
28
  type: "action",
22
29
  annotations: {
23
30
  destructiveHint: true,
@@ -1,4 +1,4 @@
1
- // vandelay-test-dr
1
+ // x-pd-ai: optimized
2
2
  import salesforce from "../../salesforce_rest_api.app.mjs";
3
3
 
4
4
  export default {
@@ -7,8 +7,10 @@ export default {
7
7
  description:
8
8
  "Update an existing Salesforce record. Only pass fields you want to change — unspecified fields remain unchanged."
9
9
  + " Use **Describe Object** for valid field names and picklist values."
10
- + " Use **SOQL Query** to find the record ID if you only have the name.",
11
- version: "0.0.1",
10
+ + " Use **SOQL Query** to find the record ID if you only have the name."
11
+ + " "
12
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
13
+ version: "0.0.2",
12
14
  type: "action",
13
15
  annotations: {
14
16
  readOnlyHint: false,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import {
2
3
  convertFieldsToProps, getAdditionalFields,
3
4
  } from "../../common/props-utils.mjs";
@@ -7,8 +8,12 @@ import { additionalFields } from "../common/base-create-update.mjs";
7
8
  export default {
8
9
  key: "salesforce_rest_api-update-email-template",
9
10
  name: "Update Email Template",
10
- description: "Updates an email template. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
11
- version: "0.0.6",
11
+ description: "Update an existing Salesforce email template."
12
+ + " Use **List Email Templates** to find the template ID first."
13
+ + " Only the fields you supply change; everything else is left as-is."
14
+ + " "
15
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
16
+ version: "0.0.7",
12
17
  annotations: {
13
18
  destructiveHint: true,
14
19
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import common, { getProps } from "../common/base-create-update.mjs";
2
3
  import note from "../../common/sobjects/note.mjs";
3
4
  import { NOTE_INFO_PROP } from "../../common/props-info.mjs";
@@ -16,8 +17,12 @@ export default {
16
17
  ...common,
17
18
  key: "salesforce_rest_api-update-note",
18
19
  name: "Update Note",
19
- description: `Updates a classic Salesforce note, which can contain up to 32 KB of text and is associated with a parent record. [See the documentation](${docsLink})`,
20
- version: "0.0.3",
20
+ description: "Update a classic Salesforce note (up to 32 KB of plain text)."
21
+ + " Use **Update Content Note** instead for enhanced rich-text notes - the two are different objects."
22
+ + " Supplying `Body` replaces the note text outright rather than appending to it."
23
+ + " "
24
+ + `[See the documentation](${docsLink})`,
25
+ version: "0.0.4",
21
26
  type: "action",
22
27
  annotations: {
23
28
  destructiveHint: true,
@@ -1,11 +1,18 @@
1
+ // x-pd-ai: optimized
1
2
  import common from "../common/batch-operation.mjs";
2
3
 
3
4
  export default {
4
5
  ...common,
5
6
  key: "salesforce_rest_api-update-opportunities-batch",
6
7
  name: "Update Opportunities (Batch)",
7
- description: "Update multiple Opportunities in Salesforce using Bulk API 2.0. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_understanding_bulk2_ingest.htm)",
8
- version: "0.0.5",
8
+ description: "Update many Salesforce opportunities in one job using Bulk API 2.0."
9
+ + " Use this instead of **Update Opportunity** when updating more than roughly 200 records - it is asynchronous and returns a job ID, not the updated records."
10
+ + " Every row must include the record `Id` of the opportunity to update."
11
+ + " Input is a CSV file - supply a path under `/tmp` or a URL to download it from, with a header row of Salesforce field API names."
12
+ + " Poll the job in Salesforce to confirm completion; a successful response means the job was accepted, not that every row loaded."
13
+ + " "
14
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_understanding_bulk2_ingest.htm)",
15
+ version: "0.0.6",
9
16
  annotations: {
10
17
  destructiveHint: true,
11
18
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import common, { getProps } from "../common/base-create-update.mjs";
2
3
  import opportunity from "../../common/sobjects/opportunity.mjs";
3
4
  import { docsLink } from "../create-opportunity/create-opportunity.mjs";
@@ -16,8 +17,12 @@ export default {
16
17
  ...common,
17
18
  key: "salesforce_rest_api-update-opportunity",
18
19
  name: "Update Opportunity",
19
- description: `Updates an opportunity. [See the documentation](${docsLink})`,
20
- version: "0.3.6",
20
+ description: "Update fields on an existing Salesforce opportunity, such as moving it to a new stage."
21
+ + " Use **Describe Object** on `Opportunity` to list the valid `StageName` values for your org."
22
+ + " Only the fields you supply change; everything else is left as-is."
23
+ + " "
24
+ + `[See the documentation](${docsLink})`,
25
+ version: "0.3.7",
21
26
  annotations: {
22
27
  destructiveHint: true,
23
28
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import {
2
3
  convertFieldsToProps, getAdditionalFields,
3
4
  } from "../../common/props-utils.mjs";
@@ -7,8 +8,12 @@ import { additionalFields } from "../common/base-create-update.mjs";
7
8
  export default {
8
9
  key: "salesforce_rest_api-update-record",
9
10
  name: "Update Record",
10
- description: "Update fields of a record. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
11
- version: "0.3.7",
11
+ description: "Update a Salesforce record of any object type, choosing fields interactively."
12
+ + " Prefer **Update CRM Record** in agent and API contexts - this action builds its field list dynamically, so the available inputs are not visible until an object type is chosen."
13
+ + " Only the fields you supply change; everything else is left as-is."
14
+ + " "
15
+ + "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
16
+ version: "0.3.8",
12
17
  annotations: {
13
18
  destructiveHint: true,
14
19
  openWorldHint: true,
@@ -1,3 +1,4 @@
1
+ // x-pd-ai: optimized
1
2
  import {
2
3
  convertFieldsToProps, getAdditionalFields,
3
4
  } from "../../common/props-utils.mjs";
@@ -7,8 +8,12 @@ import { additionalFields } from "../common/base-create-update.mjs";
7
8
  export default {
8
9
  key: "salesforce_rest_api-upsert-record",
9
10
  name: "Upsert Record",
10
- description: "Create or update a record of a given object. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_upsert.htm)",
11
- version: "0.0.7",
11
+ description: "Create a Salesforce record, or update it if a matching one already exists, matched on an external ID field."
12
+ + " The object must have an external ID field defined - use **Describe Object** to find one before calling."
13
+ + " Use **Create CRM Record** or **Update CRM Record** when you already know whether the record exists."
14
+ + " "
15
+ + "[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
17
  annotations: {
13
18
  destructiveHint: true,
14
19
  openWorldHint: true,
@@ -27,11 +27,63 @@ export default {
27
27
  "Cadence",
28
28
  "Call",
29
29
  ],
30
+ CASE_FEED_ITEM_TYPES: [
31
+ "ActivityEvent",
32
+ "AdvancedTextPost",
33
+ "ApprovalPost",
34
+ "AttachArticleEvent",
35
+ "CallLogPost",
36
+ "CanvasPost",
37
+ "CaseCommentPost",
38
+ "ChangeStatusPost",
39
+ "ChatTranscriptPost",
40
+ "ContentPost",
41
+ "CreatedRecordEvent",
42
+ "EmailMessageEvent",
43
+ "LinkPost",
44
+ "MilestoneEvent",
45
+ "PollPost",
46
+ "QuestionPost",
47
+ "SocialPost",
48
+ "TextPost",
49
+ "TrackedChange",
50
+ ],
51
+ CASE_DEFAULT_STATUSES: [
52
+ "New",
53
+ "Working",
54
+ "Escalated",
55
+ "Closed",
56
+ ],
57
+ CASE_LIST_FIELDS: [
58
+ "Id",
59
+ "CaseNumber",
60
+ "Subject",
61
+ "Status",
62
+ "Priority",
63
+ "Origin",
64
+ "IsClosed",
65
+ "AccountId",
66
+ "ContactId",
67
+ "OwnerId",
68
+ "CreatedDate",
69
+ "LastModifiedDate",
70
+ ],
71
+ DEFAULT_LIMIT: 100,
72
+ MAX_LIMIT: 1000,
73
+ SALESFORCE_ID_REGEX: /^[a-zA-Z0-9]{15}([a-zA-Z0-9]{3})?$/,
74
+ DATE_ONLY_REGEX: /^\d{4}-\d{2}-\d{2}$/,
75
+ DATE_TIME_REGEX: /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/,
30
76
  OBJECT_TYPE: {
31
77
  CAMPAIGN: "Campaign",
32
78
  CONTACT: "Contact",
33
79
  CAMPAIGN_MEMBER: "CampaignMember",
34
80
  LEAD: "Lead",
81
+ CASE: "Case",
82
+ CASE_FEED: "CaseFeed",
83
+ CASE_COMMENT: "CaseComment",
84
+ EMAIL_MESSAGE: "EmailMessage",
85
+ EMAIL_TEMPLATE: "EmailTemplate",
86
+ KNOWLEDGE_ARTICLE: "KnowledgeArticle",
35
87
  FEED_ITEM: "FeedItem",
36
88
  FEED_COMMENT: "FeedComment",
37
89
  },
@@ -0,0 +1,96 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import constants from "./constants.mjs";
3
+
4
+ /**
5
+ * Escapes a value for use inside a quoted SOQL string literal.
6
+ * Salesforce escapes with a backslash, so the backslash itself must go first.
7
+ */
8
+ export function escapeSoqlString(value) {
9
+ return String(value)
10
+ .replace(/\\/g, "\\\\")
11
+ .replace(/'/g, "\\'");
12
+ }
13
+
14
+ /**
15
+ * Validates a value that will be interpolated into SOQL as a record ID.
16
+ * IDs are unquoted-adjacent, high-trust values, so a bad one is rejected up front
17
+ * rather than escaped.
18
+ */
19
+ export function assertSalesforceId(value, label) {
20
+ if (!constants.SALESFORCE_ID_REGEX.test(value)) {
21
+ throw new ConfigurationError(`**${label}** must be a 15- or 18-character Salesforce ID`);
22
+ }
23
+ return value;
24
+ }
25
+
26
+ /**
27
+ * Builds a SELECT field list, always including Id so a caller that narrows the
28
+ * fields to save context still gets the ID every follow-up action needs.
29
+ */
30
+ export function buildFieldList(selected, fallback) {
31
+ return [
32
+ ...new Set([
33
+ "Id",
34
+ ...selected?.length
35
+ ? selected
36
+ : fallback,
37
+ ]),
38
+ ];
39
+ }
40
+
41
+ /**
42
+ * Salesforce returns at most one batch per query and signals a partial result
43
+ * with `done: false`. Callers that ignore it answer confidently from page one,
44
+ * so say so in the summary instead.
45
+ */
46
+ export function truncationNote({
47
+ done, totalSize,
48
+ }, returned) {
49
+ if (done !== false) {
50
+ return "";
51
+ }
52
+ const total = totalSize
53
+ ? ` of ${totalSize}`
54
+ : "";
55
+ return ` This is a partial result (${returned}${total} records) - narrow the filters, or use the **SOQL Query** action, which pages through every record.`;
56
+ }
57
+
58
+ /**
59
+ * Normalizes a user-supplied date/datetime into a SOQL datetime literal.
60
+ * SOQL datetime literals are NOT quoted, so the value must be strictly validated
61
+ * instead of escaped. A date-only value is widened to the start of that day (UTC).
62
+ */
63
+ export function toSoqlDateTimeLiteral(value, label) {
64
+ const raw = String(value).trim();
65
+ const shapeOk = constants.DATE_ONLY_REGEX.test(raw) || constants.DATE_TIME_REGEX.test(raw);
66
+ if (!shapeOk) {
67
+ throw new ConfigurationError(`**${label}** must be an ISO 8601 date (\`2026-08-01\`) or date-time (\`2026-08-01T00:00:00Z\`)`);
68
+ }
69
+
70
+ const literal = constants.DATE_ONLY_REGEX.test(raw)
71
+ ? `${raw}T00:00:00Z`
72
+ : raw;
73
+
74
+ // The shape check alone accepts impossible values. Date.parse rejects month 13,
75
+ // hour 25 and offset +99, but silently rolls 2026-02-31 over to March 3, so the
76
+ // calendar day is round-tripped separately.
77
+ const [
78
+ year,
79
+ month,
80
+ day,
81
+ ] = raw.slice(0, 10).split("-")
82
+ .map(Number);
83
+ // Date.UTC maps years 0-99 to 1900-1999, so building the date there first would
84
+ // roll a valid leap day like `0000-02-29` into March (1900 is not a leap year) and
85
+ // reject it. Setting all three parts together on an epoch date avoids that.
86
+ const utc = new Date(0);
87
+ utc.setUTCFullYear(year, month - 1, day);
88
+ const dayIsReal = utc.getUTCFullYear() === year
89
+ && utc.getUTCMonth() === month - 1
90
+ && utc.getUTCDate() === day;
91
+
92
+ if (!dayIsReal || Number.isNaN(Date.parse(literal))) {
93
+ throw new ConfigurationError(`**${label}** is not a real date: \`${raw}\``);
94
+ }
95
+ return literal;
96
+ }