@bonsae/node-red-salesforce 0.1.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 (46) hide show
  1. package/README.md +126 -0
  2. package/examples/1-soql-query.json +103 -0
  3. package/examples/10-streaming-platform-events.json +73 -0
  4. package/examples/11-streaming-change-data-capture.json +73 -0
  5. package/examples/2-dml-create.json +106 -0
  6. package/examples/3-dml-read.json +83 -0
  7. package/examples/4-dml-update.json +83 -0
  8. package/examples/5-dml-delete.json +83 -0
  9. package/examples/6-describe.json +97 -0
  10. package/examples/7-apex-rest.json +99 -0
  11. package/examples/8-bulk-insert.json +63 -0
  12. package/examples/9-bulk-query.json +63 -0
  13. package/icons/salesforce-apex.png +0 -0
  14. package/icons/salesforce-bulk.png +0 -0
  15. package/icons/salesforce-connection.png +0 -0
  16. package/icons/salesforce-describe.png +0 -0
  17. package/icons/salesforce-dml.png +0 -0
  18. package/icons/salesforce-soql.png +0 -0
  19. package/icons/salesforce-streaming.png +0 -0
  20. package/index.d.ts +268 -0
  21. package/index.html +2 -0
  22. package/index.js +14 -0
  23. package/index.mjs +913 -0
  24. package/index.mjs.map +1 -0
  25. package/locales/de/index.html +226 -0
  26. package/locales/de/index.json +154 -0
  27. package/locales/en-US/index.html +226 -0
  28. package/locales/en-US/index.json +154 -0
  29. package/locales/es-ES/index.html +226 -0
  30. package/locales/es-ES/index.json +154 -0
  31. package/locales/fr/index.html +226 -0
  32. package/locales/fr/index.json +154 -0
  33. package/locales/ja/index.html +226 -0
  34. package/locales/ja/index.json +154 -0
  35. package/locales/ko/index.html +226 -0
  36. package/locales/ko/index.json +154 -0
  37. package/locales/pt-BR/index.html +226 -0
  38. package/locales/pt-BR/index.json +154 -0
  39. package/locales/ru/index.html +226 -0
  40. package/locales/ru/index.json +154 -0
  41. package/locales/zh-CN/index.html +226 -0
  42. package/locales/zh-CN/index.json +154 -0
  43. package/locales/zh-TW/index.html +226 -0
  44. package/locales/zh-TW/index.json +154 -0
  45. package/package.json +52 -0
  46. package/resources/index.CfTW8fjc.js +1 -0
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ <a href="https://bonsaedev.github.io/nrg/"><img src="https://img.shields.io/badge/built%20with-nrg-A80000.svg?labelColor=black&style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9Im91dGxpbmVHcmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiAjODA4MDgwOyBzdG9wLW9wYWNpdHk6IDEiIC8+CiAgICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6ICM0MDQwNDA7IHN0b3Atb3BhY2l0eTogMSIgLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImhleGFnb25HcmFkaWVudCIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMTAwJSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0eWxlPSJzdG9wLWNvbG9yOiAjQTgwMDAwOyBzdG9wLW9wYWNpdHk6IDEiIC8+CiAgICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6ICM0QjAwMDA7IHN0b3Atb3BhY2l0eTogMSIgLz4KICAgIDwvbGluZWFyR3JhZGllbnQ+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImxpZ2h0bmluZ0dyYWRpZW50IiB4MT0iMCUiIHkxPSIwJSIgeDI9IjEwMCUiIHkyPSIxMDAlIj4KICAgICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3R5bGU9InN0b3AtY29sb3I6ICNmZmZmZmY7IHN0b3Atb3BhY2l0eTogMSIgLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjogI2UwZTBlMDsgc3RvcC1vcGFjaXR5OiAxIiAvPgogICAgPC9saW5lYXJHcmFkaWVudD4KICA8L2RlZnM+CiAgPHBvbHlnb24gcG9pbnRzPSI1MCwyIDk4LDI1IDk4LDc1IDUwLDk4IDMsNzUgMywyNSIgCiAgICAgICAgICAgc3Ryb2tlPSJ1cmwoI291dGxpbmVHcmFkaWVudCkiIHN0cm9rZS13aWR0aD0iNCIgZmlsbD0idXJsKCNoZXhhZ29uR3JhZGllbnQpIiAvPgoKICA8cGF0aCBkPSJNMzMgMGwxOS43OTcyIDM5LjQ1NzQtMjguNTAyMi0xMS4xMTg0TDc0IDk4IDUxLjA2MDggNDkuMzA1NCA3MSA1NloiIAogICAgICAgIGZpbGw9InVybCgjbGlnaHRuaW5nR3JhZGllbnQpIiBzdHJva2U9Im5vbmUiIC8+Cjwvc3ZnPgo=" alt="built with nrg"/></a>
2
+ <a href="https://www.npmjs.com/package/@bonsae/node-red-salesforce"><img alt="NPM Version" src="https://img.shields.io/npm/v/@bonsae/node-red-salesforce"></a>
3
+ <a href="https://github.com/bonsaedev/node-red-salesforce/actions/workflows/ci.yaml"><img src="https://github.com/bonsaedev/node-red-salesforce/actions/workflows/ci.yaml/badge.svg?branch=main" alt="build status"/></a>
4
+ <a href="https://socket.dev/npm/package/@bonsae/node-red-salesforce"><img src="https://socket.dev/api/badge/npm/package/@bonsae/node-red-salesforce" alt="socket badge"/></a>
5
+ <a href="https://codecov.io/gh/bonsaedev/node-red-salesforce"><img src="https://codecov.io/gh/bonsaedev/node-red-salesforce/graph/badge.svg" alt="codecov"/></a>
6
+
7
+ # @bonsae/node-red-salesforce
8
+
9
+ Salesforce nodes for [Node-RED](https://nodered.org) built with [@bonsae/nrg](https://bonsaedev.github.io/nrg/).
10
+
11
+ ## Nodes
12
+
13
+ | Node | Description |
14
+ | --- | --- |
15
+ | **Connection** | OAuth 2.0 PKCE authentication with token management |
16
+ | **SOQL** | Execute SOQL queries and return matching records |
17
+ | **DML** | Create, read, update, delete, and upsert SObjects |
18
+ | **Bulk** | Bulk API 2.0 operations for large data volumes |
19
+ | **Describe** | Retrieve SObject metadata (fields, relationships, record types) |
20
+ | **Streaming** | Subscribe to Platform Events and Change Data Capture via Pub/Sub API (gRPC) |
21
+ | **Apex** | Invoke Apex REST endpoints |
22
+
23
+ ## Prerequisites
24
+
25
+ - [Node.js](https://nodejs.org/) >= 22
26
+ - [pnpm](https://pnpm.io/) >= 10.11.0
27
+ - A Salesforce org with a Connected App configured for OAuth 2.0 with PKCE
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pnpm add @bonsae/node-red-salesforce
33
+ ```
34
+
35
+ ## Connected App Setup
36
+
37
+ Create a Connected App in Salesforce Setup:
38
+
39
+ 1. Go to **Setup > App Manager > New Connected App**
40
+ 2. Enable **OAuth Settings**
41
+ 3. Set the **Callback URL** to `{your-node-red-url}/salesforce/auth/callback`
42
+ 4. Enable **Require Proof Key for Code Exchange (PKCE)**
43
+ 5. Add required OAuth scopes (`api`, `refresh_token`)
44
+ 6. Save and copy the **Consumer Key** (Client ID)
45
+
46
+ ## Usage
47
+
48
+ 1. Drag a Salesforce node onto the canvas
49
+ 2. Double-click to configure
50
+ 3. Select or create a **Connection** config node
51
+ 4. In the Connection config, enter your **Login URL**, **Client ID**, and **API Version**
52
+ 5. Click **Authorize with Salesforce** to complete the OAuth PKCE flow
53
+ 6. Configure the node's specific settings (query, SObject type, etc.)
54
+
55
+ ### SOQL Query
56
+
57
+ Wire an inject node to a SOQL node configured with a query like `SELECT Id, Name FROM Account`. The output `msg.payload` contains the array of records, `msg.totalSize` the total count, and `msg.done` whether all records were fetched.
58
+
59
+ ### DML Operations
60
+
61
+ Set the operation (create, read, update, delete, upsert) and SObject type. Pass record data in `msg.payload`:
62
+
63
+ - **create/update/upsert**: a record object or array of records
64
+ - **read/delete**: a record ID or array of IDs
65
+ - **upsert**: also set the External ID Field
66
+
67
+ ### Bulk API 2.0
68
+
69
+ For large data volumes. Pass an array of records in `msg.payload` for ingest operations, or a SOQL string for bulk queries.
70
+
71
+ ### Describe
72
+
73
+ Pass the SObject API name and receive the full describe result including fields, child relationships, and record type info.
74
+
75
+ ### Streaming (Pub/Sub API)
76
+
77
+ Subscribes to Salesforce Platform Events and Change Data Capture events using the gRPC-based Pub/Sub API. This node has no input port -- it emits messages when events are received.
78
+
79
+ Configure the channel (e.g., `/event/MyEvent__e`), subscribe type (LATEST, EARLIEST, or CUSTOM with a replay ID), and batch size.
80
+
81
+ ### Apex REST
82
+
83
+ Invoke custom Apex REST endpoints. Set the HTTP method and path (e.g., `/MyEndpoint`). For POST/PUT/PATCH, the request body is taken from `msg.payload`.
84
+
85
+ ## Development
86
+
87
+ ```bash
88
+ # Install dependencies
89
+ pnpm install
90
+
91
+ # Start dev server (launches Node-RED with hot reload)
92
+ pnpm dev
93
+
94
+ # Build for production
95
+ pnpm build
96
+
97
+ # Run tests
98
+ pnpm test
99
+
100
+ # Type check
101
+ pnpm tsc:server
102
+ pnpm tsc:client
103
+
104
+ # Lint and format
105
+ pnpm lint
106
+ pnpm format
107
+ ```
108
+
109
+ ## Locales
110
+
111
+ Labels and auto-generated help docs are available in:
112
+
113
+ - English (en-US)
114
+ - German (de)
115
+ - Spanish (es-ES)
116
+ - French (fr)
117
+ - Japanese (ja)
118
+ - Korean (ko)
119
+ - Portuguese (pt-BR)
120
+ - Russian (ru)
121
+ - Chinese Simplified (zh-CN)
122
+ - Chinese Traditional (zh-TW)
123
+
124
+ ## License
125
+
126
+ MIT
@@ -0,0 +1,103 @@
1
+ [
2
+ {
3
+ "id": "flow-soql",
4
+ "type": "tab",
5
+ "label": "SOQL Query",
6
+ "disabled": false,
7
+ "info": "Query records from Salesforce using static and dynamic SOQL"
8
+ },
9
+ {
10
+ "id": "config-sf-1",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "inject-static",
21
+ "type": "inject",
22
+ "z": "flow-soql",
23
+ "name": "Query Accounts",
24
+ "props": [],
25
+ "repeat": "",
26
+ "once": false,
27
+ "x": 140,
28
+ "y": 80,
29
+ "wires": [["soql-static"]]
30
+ },
31
+ {
32
+ "id": "soql-static",
33
+ "type": "salesforce-soql",
34
+ "z": "flow-soql",
35
+ "name": "Static Query",
36
+ "connection": "config-sf-1",
37
+ "query": {
38
+ "type": "str",
39
+ "value": "SELECT Id, Name, Industry, CreatedDate FROM Account ORDER BY CreatedDate DESC LIMIT 10"
40
+ },
41
+ "x": 350,
42
+ "y": 80,
43
+ "wires": [["debug-static"]]
44
+ },
45
+ {
46
+ "id": "debug-static",
47
+ "type": "debug",
48
+ "z": "flow-soql",
49
+ "name": "Results",
50
+ "active": true,
51
+ "tosidebar": true,
52
+ "console": false,
53
+ "complete": "true",
54
+ "x": 530,
55
+ "y": 80,
56
+ "wires": []
57
+ },
58
+ {
59
+ "id": "inject-dynamic",
60
+ "type": "inject",
61
+ "z": "flow-soql",
62
+ "name": "Query Contacts",
63
+ "props": [
64
+ {
65
+ "p": "query",
66
+ "v": "SELECT Id, Name, Email FROM Contact LIMIT 5",
67
+ "vt": "str"
68
+ }
69
+ ],
70
+ "repeat": "",
71
+ "once": false,
72
+ "x": 150,
73
+ "y": 180,
74
+ "wires": [["soql-dynamic"]]
75
+ },
76
+ {
77
+ "id": "soql-dynamic",
78
+ "type": "salesforce-soql",
79
+ "z": "flow-soql",
80
+ "name": "Dynamic Query",
81
+ "connection": "config-sf-1",
82
+ "query": {
83
+ "type": "msg",
84
+ "value": "query"
85
+ },
86
+ "x": 360,
87
+ "y": 180,
88
+ "wires": [["debug-dynamic"]]
89
+ },
90
+ {
91
+ "id": "debug-dynamic",
92
+ "type": "debug",
93
+ "z": "flow-soql",
94
+ "name": "Results",
95
+ "active": true,
96
+ "tosidebar": true,
97
+ "console": false,
98
+ "complete": "true",
99
+ "x": 530,
100
+ "y": 180,
101
+ "wires": []
102
+ }
103
+ ]
@@ -0,0 +1,73 @@
1
+ [
2
+ {
3
+ "id": "flow-streaming",
4
+ "type": "tab",
5
+ "label": "Platform Events",
6
+ "disabled": false,
7
+ "info": "Subscribe to Salesforce Platform Events using the Pub/Sub API (gRPC). Requires a Platform Event defined in your org (e.g., MyEvent__e)."
8
+ },
9
+ {
10
+ "id": "config-sf-9",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "streaming-latest",
21
+ "type": "salesforce-streaming",
22
+ "z": "flow-streaming",
23
+ "name": "New Events",
24
+ "connection": "config-sf-9",
25
+ "channelName": "/event/MyEvent__e",
26
+ "subscribeType": "LATEST",
27
+ "replayId": "",
28
+ "numRequested": 100,
29
+ "x": 150,
30
+ "y": 80,
31
+ "wires": [["debug-event"]]
32
+ },
33
+ {
34
+ "id": "debug-event",
35
+ "type": "debug",
36
+ "z": "flow-streaming",
37
+ "name": "Event",
38
+ "active": true,
39
+ "tosidebar": true,
40
+ "console": false,
41
+ "complete": "true",
42
+ "x": 350,
43
+ "y": 80,
44
+ "wires": []
45
+ },
46
+ {
47
+ "id": "streaming-earliest",
48
+ "type": "salesforce-streaming",
49
+ "z": "flow-streaming",
50
+ "name": "Replay All",
51
+ "connection": "config-sf-9",
52
+ "channelName": "/event/MyEvent__e",
53
+ "subscribeType": "EARLIEST",
54
+ "replayId": "",
55
+ "numRequested": 50,
56
+ "x": 140,
57
+ "y": 200,
58
+ "wires": [["debug-replay"]]
59
+ },
60
+ {
61
+ "id": "debug-replay",
62
+ "type": "debug",
63
+ "z": "flow-streaming",
64
+ "name": "Replayed Event",
65
+ "active": true,
66
+ "tosidebar": true,
67
+ "console": false,
68
+ "complete": "true",
69
+ "x": 370,
70
+ "y": 200,
71
+ "wires": []
72
+ }
73
+ ]
@@ -0,0 +1,73 @@
1
+ [
2
+ {
3
+ "id": "flow-cdc",
4
+ "type": "tab",
5
+ "label": "Change Data Capture",
6
+ "disabled": false,
7
+ "info": "Subscribe to Salesforce Change Data Capture events. Enable CDC for the desired objects in Salesforce Setup > Change Data Capture."
8
+ },
9
+ {
10
+ "id": "config-sf-10",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "streaming-account-cdc",
21
+ "type": "salesforce-streaming",
22
+ "z": "flow-cdc",
23
+ "name": "Account Changes",
24
+ "connection": "config-sf-10",
25
+ "channelName": "/data/AccountChangeEvent",
26
+ "subscribeType": "LATEST",
27
+ "replayId": "",
28
+ "numRequested": 100,
29
+ "x": 160,
30
+ "y": 80,
31
+ "wires": [["debug-cdc-account"]]
32
+ },
33
+ {
34
+ "id": "debug-cdc-account",
35
+ "type": "debug",
36
+ "z": "flow-cdc",
37
+ "name": "Account Change",
38
+ "active": true,
39
+ "tosidebar": true,
40
+ "console": false,
41
+ "complete": "true",
42
+ "x": 390,
43
+ "y": 80,
44
+ "wires": []
45
+ },
46
+ {
47
+ "id": "streaming-all-cdc",
48
+ "type": "salesforce-streaming",
49
+ "z": "flow-cdc",
50
+ "name": "All Changes",
51
+ "connection": "config-sf-10",
52
+ "channelName": "/data/ChangeEvents",
53
+ "subscribeType": "LATEST",
54
+ "replayId": "",
55
+ "numRequested": 100,
56
+ "x": 150,
57
+ "y": 200,
58
+ "wires": [["debug-cdc-all"]]
59
+ },
60
+ {
61
+ "id": "debug-cdc-all",
62
+ "type": "debug",
63
+ "z": "flow-cdc",
64
+ "name": "Any Change",
65
+ "active": true,
66
+ "tosidebar": true,
67
+ "console": false,
68
+ "complete": "true",
69
+ "x": 370,
70
+ "y": 200,
71
+ "wires": []
72
+ }
73
+ ]
@@ -0,0 +1,106 @@
1
+ [
2
+ {
3
+ "id": "flow-create",
4
+ "type": "tab",
5
+ "label": "DML Create",
6
+ "disabled": false,
7
+ "info": "Create records in Salesforce using static JSON and dynamic msg"
8
+ },
9
+ {
10
+ "id": "config-sf-2",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "inject-create-static",
21
+ "type": "inject",
22
+ "z": "flow-create",
23
+ "name": "Create (static JSON)",
24
+ "props": [],
25
+ "repeat": "",
26
+ "once": false,
27
+ "x": 160,
28
+ "y": 80,
29
+ "wires": [["dml-create-static"]]
30
+ },
31
+ {
32
+ "id": "dml-create-static",
33
+ "type": "salesforce-dml",
34
+ "z": "flow-create",
35
+ "name": "Create Account",
36
+ "connection": "config-sf-2",
37
+ "operation": "create",
38
+ "sObjectType": { "type": "str", "value": "Account" },
39
+ "record": {
40
+ "type": "json",
41
+ "value": "{\"Name\":\"Node-RED Test\",\"Industry\":\"Technology\"}"
42
+ },
43
+ "externalIdField": "",
44
+ "x": 390,
45
+ "y": 80,
46
+ "wires": [["debug-create-1"]]
47
+ },
48
+ {
49
+ "id": "debug-create-1",
50
+ "type": "debug",
51
+ "z": "flow-create",
52
+ "name": "Result",
53
+ "active": true,
54
+ "tosidebar": true,
55
+ "console": false,
56
+ "complete": "payload",
57
+ "x": 570,
58
+ "y": 80,
59
+ "wires": []
60
+ },
61
+ {
62
+ "id": "inject-create-dynamic",
63
+ "type": "inject",
64
+ "z": "flow-create",
65
+ "name": "Create (from msg)",
66
+ "props": [
67
+ {
68
+ "p": "payload",
69
+ "v": "{\"Name\":\"Dynamic Account\",\"Industry\":\"Finance\"}",
70
+ "vt": "json"
71
+ }
72
+ ],
73
+ "repeat": "",
74
+ "once": false,
75
+ "x": 160,
76
+ "y": 180,
77
+ "wires": [["dml-create-dynamic"]]
78
+ },
79
+ {
80
+ "id": "dml-create-dynamic",
81
+ "type": "salesforce-dml",
82
+ "z": "flow-create",
83
+ "name": "Create Account",
84
+ "connection": "config-sf-2",
85
+ "operation": "create",
86
+ "sObjectType": { "type": "str", "value": "Account" },
87
+ "record": { "type": "msg", "value": "payload" },
88
+ "externalIdField": "",
89
+ "x": 390,
90
+ "y": 180,
91
+ "wires": [["debug-create-2"]]
92
+ },
93
+ {
94
+ "id": "debug-create-2",
95
+ "type": "debug",
96
+ "z": "flow-create",
97
+ "name": "Result",
98
+ "active": true,
99
+ "tosidebar": true,
100
+ "console": false,
101
+ "complete": "payload",
102
+ "x": 570,
103
+ "y": 180,
104
+ "wires": []
105
+ }
106
+ ]
@@ -0,0 +1,83 @@
1
+ [
2
+ {
3
+ "id": "flow-read",
4
+ "type": "tab",
5
+ "label": "DML Read",
6
+ "disabled": false,
7
+ "info": "Retrieve a record by ID from Salesforce"
8
+ },
9
+ {
10
+ "id": "config-sf-read",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "inject-read",
21
+ "type": "inject",
22
+ "z": "flow-read",
23
+ "name": "Read Account",
24
+ "props": [],
25
+ "repeat": "",
26
+ "once": false,
27
+ "x": 140,
28
+ "y": 80,
29
+ "wires": [["soql-find-for-read"]]
30
+ },
31
+ {
32
+ "id": "soql-find-for-read",
33
+ "type": "salesforce-soql",
34
+ "z": "flow-read",
35
+ "name": "Get First Account ID",
36
+ "connection": "config-sf-read",
37
+ "query": {
38
+ "type": "str",
39
+ "value": "SELECT Id FROM Account LIMIT 1"
40
+ },
41
+ "x": 370,
42
+ "y": 80,
43
+ "wires": [["func-extract-read-id"]]
44
+ },
45
+ {
46
+ "id": "func-extract-read-id",
47
+ "type": "function",
48
+ "z": "flow-read",
49
+ "name": "Extract ID",
50
+ "func": "if (msg.payload && msg.payload.length > 0) {\n msg.payload = msg.payload[0].Id;\n return msg;\n}\nnode.warn(\"No account found\");\nreturn null;",
51
+ "outputs": 1,
52
+ "x": 570,
53
+ "y": 80,
54
+ "wires": [["dml-read"]]
55
+ },
56
+ {
57
+ "id": "dml-read",
58
+ "type": "salesforce-dml",
59
+ "z": "flow-read",
60
+ "name": "Read Account",
61
+ "connection": "config-sf-read",
62
+ "operation": "read",
63
+ "sObjectType": { "type": "str", "value": "Account" },
64
+ "record": { "type": "msg", "value": "payload" },
65
+ "externalIdField": "",
66
+ "x": 750,
67
+ "y": 80,
68
+ "wires": [["debug-read"]]
69
+ },
70
+ {
71
+ "id": "debug-read",
72
+ "type": "debug",
73
+ "z": "flow-read",
74
+ "name": "Account Record",
75
+ "active": true,
76
+ "tosidebar": true,
77
+ "console": false,
78
+ "complete": "payload",
79
+ "x": 940,
80
+ "y": 80,
81
+ "wires": []
82
+ }
83
+ ]
@@ -0,0 +1,83 @@
1
+ [
2
+ {
3
+ "id": "flow-update",
4
+ "type": "tab",
5
+ "label": "DML Update",
6
+ "disabled": false,
7
+ "info": "Find an account by name and update its Industry"
8
+ },
9
+ {
10
+ "id": "config-sf-3",
11
+ "type": "salesforce-connection",
12
+ "name": "Salesforce",
13
+ "loginUrl": "https://login.salesforce.com",
14
+ "clientId": "",
15
+ "apiVersion": "62.0",
16
+ "callbackUrl": "http://localhost:1880/salesforce/auth/callback",
17
+ "z": ""
18
+ },
19
+ {
20
+ "id": "inject-update",
21
+ "type": "inject",
22
+ "z": "flow-update",
23
+ "name": "Update Account",
24
+ "props": [],
25
+ "repeat": "",
26
+ "once": false,
27
+ "x": 140,
28
+ "y": 80,
29
+ "wires": [["soql-find-update"]]
30
+ },
31
+ {
32
+ "id": "soql-find-update",
33
+ "type": "salesforce-soql",
34
+ "z": "flow-update",
35
+ "name": "Find Account",
36
+ "connection": "config-sf-3",
37
+ "query": {
38
+ "type": "str",
39
+ "value": "SELECT Id, Name FROM Account WHERE Name = 'Node-RED Test' LIMIT 1"
40
+ },
41
+ "x": 340,
42
+ "y": 80,
43
+ "wires": [["func-prep-update"]]
44
+ },
45
+ {
46
+ "id": "func-prep-update",
47
+ "type": "function",
48
+ "z": "flow-update",
49
+ "name": "Prepare Update",
50
+ "func": "if (msg.payload && msg.payload.length > 0) {\n msg.payload = {\n Id: msg.payload[0].Id,\n Industry: \"Finance\"\n };\n return msg;\n}\nnode.warn(\"No account found\");\nreturn null;",
51
+ "outputs": 1,
52
+ "x": 540,
53
+ "y": 80,
54
+ "wires": [["dml-update"]]
55
+ },
56
+ {
57
+ "id": "dml-update",
58
+ "type": "salesforce-dml",
59
+ "z": "flow-update",
60
+ "name": "Update Account",
61
+ "connection": "config-sf-3",
62
+ "operation": "update",
63
+ "sObjectType": { "type": "str", "value": "Account" },
64
+ "record": { "type": "msg", "value": "payload" },
65
+ "externalIdField": "",
66
+ "x": 740,
67
+ "y": 80,
68
+ "wires": [["debug-update"]]
69
+ },
70
+ {
71
+ "id": "debug-update",
72
+ "type": "debug",
73
+ "z": "flow-update",
74
+ "name": "Result",
75
+ "active": true,
76
+ "tosidebar": true,
77
+ "console": false,
78
+ "complete": "payload",
79
+ "x": 910,
80
+ "y": 80,
81
+ "wires": []
82
+ }
83
+ ]