@bonsae/node-red-salesforce 0.4.0 → 0.5.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.
package/README.md CHANGED
@@ -18,7 +18,8 @@ Salesforce nodes for [Node-RED](https://nodered.org) built with [@bonsae/nrg](ht
18
18
  | **Bulk** | Bulk API 2.0 operations for large data volumes |
19
19
  | **Describe** | Retrieve SObject metadata (fields, relationships, record types) |
20
20
  | **Streaming** | Subscribe to Platform Events and Change Data Capture via Pub/Sub API (gRPC) |
21
- | **Apex** | Invoke Apex REST endpoints |
21
+ | **Apex Invocation** | Call existing Apex REST endpoints or Invocable Actions |
22
+ | **Apex Code** | Deploy and execute custom inline Apex code (Invocable or REST) |
22
23
 
23
24
  ## Prerequisites
24
25
 
@@ -66,7 +67,16 @@ Set the operation (create, read, update, delete, upsert) and SObject type. Pass
66
67
 
67
68
  ### Bulk API 2.0
68
69
 
69
- For large data volumes. Pass an array of records in `msg.payload` for ingest operations, or a SOQL string for bulk queries.
70
+ For large data volumes. Supports three input types:
71
+
72
+ - **Record array**: `msg.payload` as `Record[]` for ingest operations
73
+ - **CSV string**: `msg.payload` as a CSV string
74
+ - **Readable stream**: `msg.payload` as a Node.js `Readable` stream (for streaming from files)
75
+ - **SOQL string**: `msg.payload` as a SOQL query string when operation is "query"
76
+
77
+ Operations: insert, update, upsert, delete, hardDelete, query.
78
+
79
+ For ingest operations, the output `msg.payload` contains `{ successfulResults, failedResults, unprocessedRecords }`. For queries, each record is streamed as a separate message. Job lifecycle progress is reported via the status port.
70
80
 
71
81
  ### Describe
72
82
 
@@ -78,9 +88,35 @@ Subscribes to Salesforce Platform Events and Change Data Capture events using th
78
88
 
79
89
  Configure the channel (e.g., `/event/MyEvent__e`), subscribe type (LATEST, EARLIEST, or CUSTOM with a replay ID), and batch size.
80
90
 
81
- ### Apex REST
91
+ ### Apex Invocation
92
+
93
+ Call existing Apex endpoints deployed in your Salesforce org. Select the type (REST or Invocable), then pick the endpoint or action from a dropdown that queries your org. For REST, choose the HTTP method and endpoint path. For Invocable, select the action by name. The payload is passed in `msg.payload`.
94
+
95
+ ### Apex Code
96
+
97
+ Deploy and execute custom Apex code directly from Node-RED. Select the type (Invocable or REST), enter a class name, and write your Apex method body in the built-in code editor. The node automatically deploys the class to Salesforce on Node-RED deploy and removes it when the node is deleted.
98
+
99
+ Your code receives the input as a `payload` string and returns any value:
100
+
101
+ ```apex
102
+ // Invocable example
103
+ Map<String, Object> data = (Map<String, Object>) JSON.deserializeUntyped(payload);
104
+ String name = (String) data.get('name');
105
+ return 'Hello, ' + name + '!';
106
+ ```
107
+
108
+ ```apex
109
+ // REST example
110
+ return new Map<String, Object>{ 'message' => 'Received: ' + payload };
111
+ ```
112
+
113
+ The class name prefix defaults to `NRG_` and can be overridden in `settings.js`:
114
+
115
+ ```javascript
116
+ salesforceApexCodeClassPrefix: "MY_"
117
+ ```
82
118
 
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`.
119
+ For REST mode, you also configure the URL mapping (e.g., `/my/endpoint/*`).
84
120
 
85
121
  ## Development
86
122
 
Binary file
package/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Connection } from 'jsforce';
3
3
  import { Infer } from '@bonsae/nrg/server';
4
4
  import { IONode } from '@bonsae/nrg/server';
5
5
  import { ModuleDefinition } from '@bonsae/nrg/server';
6
+ import { Readable } from 'stream';
6
7
  import { RED } from '@bonsae/nrg/server';
7
8
  import { Schema } from '@bonsae/nrg/server';
8
9
  import { TAny } from '@sinclair/typebox';
@@ -17,105 +18,161 @@ import { TString } from '@sinclair/typebox';
17
18
  import { TTypedInput } from '@bonsae/nrg/server';
18
19
  import { TUnion } from '@sinclair/typebox';
19
20
 
20
- declare type Config = Infer<typeof SalesforceApexConfigSchema>;
21
+ declare type Config = Infer<typeof SalesforceApexCodeConfigSchema>;
21
22
 
22
23
  declare type Config_2 = Infer<typeof SalesforceConnectionConfigSchema>;
23
24
 
24
- declare type Config_3 = Infer<typeof SalesforceBulkConfigSchema>;
25
+ declare type Config_3 = Infer<typeof SalesforceApexInvocationConfigSchema>;
25
26
 
26
- declare type Config_4 = Infer<typeof SalesforceDescribeConfigSchema>;
27
+ declare type Config_4 = Infer<typeof SalesforceBulkConfigSchema>;
27
28
 
28
- declare type Config_5 = Infer<typeof SalesforceDmlConfigSchema>;
29
+ declare type Config_5 = Infer<typeof SalesforceDescribeConfigSchema>;
29
30
 
30
- declare type Config_6 = Infer<typeof SalesforceSoqlConfigSchema>;
31
+ declare type Config_6 = Infer<typeof SalesforceDmlConfigSchema>;
31
32
 
32
- declare type Config_7 = Infer<typeof SalesforceStreamingConfigSchema>;
33
+ declare type Config_7 = Infer<typeof SalesforceSoqlConfigSchema>;
34
+
35
+ declare type Config_8 = Infer<typeof SalesforceStreamingConfigSchema>;
33
36
 
34
37
  declare type Credentials = Infer<typeof SalesforceConnectionCredentialsSchema>;
35
38
 
36
39
  declare const _default: ModuleDefinition;
37
40
  export default _default;
38
41
 
39
- declare type Input = Infer<typeof SalesforceApexInputSchema>;
42
+ declare type Input = Infer<typeof SalesforceApexCodeInputSchema>;
43
+
44
+ declare type Input_2 = Infer<typeof SalesforceApexInvocationInputSchema>;
45
+
46
+ declare type Input_3 = {
47
+ payload: string | Record<string, unknown>[] | Readable;
48
+ };
40
49
 
41
- declare type Input_2 = Infer<typeof SalesforceBulkInputSchema>;
50
+ declare type Input_4 = Infer<typeof SalesforceDescribeInputSchema>;
42
51
 
43
- declare type Input_3 = Infer<typeof SalesforceDescribeInputSchema>;
52
+ declare type Input_5 = Infer<typeof SalesforceDmlInputSchema>;
44
53
 
45
- declare type Input_4 = Infer<typeof SalesforceDmlInputSchema>;
54
+ declare type Input_6 = Infer<typeof SalesforceSoqlInputSchema>;
46
55
 
47
- declare type Input_5 = Infer<typeof SalesforceSoqlInputSchema>;
56
+ declare type Output = Infer<typeof SalesforceApexCodeOutputsSchema>;
48
57
 
49
- declare type Output = Infer<typeof SalesforceApexOutputsSchema>;
58
+ declare type Output_2 = Infer<typeof SalesforceApexInvocationOutputsSchema>;
50
59
 
51
- declare type Output_2 = Infer<typeof SalesforceDescribeOutputsSchema>;
60
+ declare type Output_3 = Infer<typeof SalesforceDescribeOutputsSchema>;
52
61
 
53
- declare type Output_3 = Infer<typeof SalesforceDmlOutputsSchema>;
62
+ declare type Output_4 = Infer<typeof SalesforceDmlOutputsSchema>;
54
63
 
55
- declare type Output_4 = Infer<typeof SalesforceSoqlOutputsSchema>;
64
+ declare type Output_5 = Infer<typeof SalesforceSoqlOutputsSchema>;
56
65
 
57
- declare type Output_5 = Infer<typeof SalesforceStreamingOutputsSchema>;
66
+ declare type Output_6 = Infer<typeof SalesforceStreamingOutputsSchema>;
58
67
 
59
- export declare class SalesforceApex extends IONode<Config, any, Input, Output> {
60
- static readonly type = "salesforce-apex";
68
+ export declare class SalesforceApexCode extends IONode<Config, any, Input, Output, Settings> {
69
+ static readonly type = "salesforce-apex-code";
61
70
  static readonly category = "salesforce";
62
71
  static readonly color: `#${string}`;
63
72
  static readonly configSchema: Schema;
64
73
  static readonly inputSchema: Schema;
65
74
  static readonly outputsSchema: Schema;
75
+ static readonly settingsSchema: Schema;
76
+ private deployed;
77
+ private getFullClassName;
78
+ private buildApexBody;
79
+ created(): Promise<void>;
66
80
  input(msg: Input): Promise<void>;
81
+ closed(removed?: boolean): Promise<void>;
67
82
  }
68
83
 
69
- export declare const SalesforceApexConfigSchema: Schema< {
84
+ export declare const SalesforceApexCodeConfigSchema: Schema< {
70
85
  name: TString;
71
86
  connection: TNodeRef<SalesforceConnection>;
87
+ apexType: TUnion<[TLiteral<"invocable">, TLiteral<"rest">]>;
88
+ className: TString;
89
+ urlMapping: TString;
90
+ httpMethod: TUnion<[TLiteral<"HttpGet">, TLiteral<"HttpPost">, TLiteral<"HttpPut">, TLiteral<"HttpPatch">, TLiteral<"HttpDelete">]>;
91
+ code: TString;
92
+ errorPort: TBoolean;
93
+ completePort: TBoolean;
94
+ statusPort: TBoolean;
95
+ }>;
96
+
97
+ export declare const SalesforceApexCodeInputSchema: Schema< {
98
+ payload: TAny;
99
+ }>;
100
+
101
+ export declare const SalesforceApexCodeOutputsSchema: Schema< {
102
+ payload: TAny;
103
+ }>;
104
+
105
+ export declare const SalesforceApexCodeSettingsSchema: Schema< {
106
+ classPrefix: TString;
107
+ }>;
108
+
109
+ export declare class SalesforceApexInvocation extends IONode<Config_3, any, Input_2, Output_2> {
110
+ static readonly type = "salesforce-apex-invocation";
111
+ static readonly category = "salesforce";
112
+ static readonly color: `#${string}`;
113
+ static readonly configSchema: Schema;
114
+ static readonly inputSchema: Schema;
115
+ static readonly outputsSchema: Schema;
116
+ input(msg: Input_2): Promise<void>;
117
+ }
118
+
119
+ export declare const SalesforceApexInvocationConfigSchema: Schema< {
120
+ name: TString;
121
+ connection: TNodeRef<SalesforceConnection>;
122
+ apexType: TUnion<[TLiteral<"rest">, TLiteral<"invocable">]>;
72
123
  method: TUnion<[TLiteral<"GET">, TLiteral<"POST">, TLiteral<"PUT">, TLiteral<"PATCH">, TLiteral<"DELETE">]>;
73
124
  path: TTypedInput<string>;
74
- emitError: TBoolean;
75
- emitComplete: TBoolean;
76
- emitStatus: TBoolean;
125
+ actionName: TString;
126
+ errorPort: TBoolean;
127
+ completePort: TBoolean;
128
+ statusPort: TBoolean;
77
129
  }>;
78
130
 
79
- export declare const SalesforceApexInputSchema: Schema< {
131
+ export declare const SalesforceApexInvocationInputSchema: Schema< {
80
132
  payload: TAny;
81
133
  }>;
82
134
 
83
- export declare const SalesforceApexOutputsSchema: Schema< {
135
+ export declare const SalesforceApexInvocationOutputsSchema: Schema< {
84
136
  payload: TAny;
85
137
  }>;
86
138
 
87
- export declare class SalesforceBulk extends IONode<Config_3> {
139
+ export declare class SalesforceBulk extends IONode<Config_4, any, Input_3> {
88
140
  static readonly type = "salesforce-bulk";
89
141
  static readonly category = "salesforce";
90
142
  static readonly color: `#${string}`;
91
143
  static readonly configSchema: Schema;
92
144
  static readonly inputSchema: Schema;
93
- static readonly outputsSchema: Schema[];
94
- private sendRecord;
95
- private sendJobCreated;
96
- input(msg: Input_2): Promise<void>;
145
+ static readonly outputsSchema: Schema;
146
+ input(msg: Input_3): Promise<void>;
147
+ private executeQuery;
148
+ private executeIngest;
97
149
  }
98
150
 
99
151
  export declare const SalesforceBulkConfigSchema: Schema< {
100
152
  name: TString;
101
153
  connection: TNodeRef<SalesforceConnection>;
102
- operation: TUnion<[TLiteral<"insert">, TLiteral<"update">, TLiteral<"upsert">, TLiteral<"delete">, TLiteral<"query">]>;
154
+ operation: TUnion<[TLiteral<"insert">, TLiteral<"update">, TLiteral<"upsert">, TLiteral<"delete">, TLiteral<"hardDelete">, TLiteral<"query">]>;
103
155
  sObjectType: TTypedInput<string>;
156
+ query: TTypedInput<string>;
104
157
  externalIdField: TOptional<TString>;
105
158
  assignmentRuleId: TOptional<TString>;
106
159
  columnDelimiter: TUnion<[TLiteral<"COMMA">, TLiteral<"TAB">, TLiteral<"PIPE">, TLiteral<"SEMICOLON">, TLiteral<"CARET">, TLiteral<"BACKQUOTE">]>;
107
160
  lineEnding: TUnion<[TLiteral<"LF">, TLiteral<"CRLF">]>;
108
161
  pollInterval: TNumber;
109
162
  pollTimeout: TNumber;
110
- emitError: TBoolean;
111
- emitComplete: TBoolean;
112
- emitStatus: TBoolean;
163
+ errorPort: TBoolean;
164
+ completePort: TBoolean;
165
+ statusPort: TBoolean;
113
166
  }>;
114
167
 
115
168
  export declare const SalesforceBulkInputSchema: Schema< {
116
169
  payload: TAny;
117
170
  }>;
118
171
 
172
+ export declare const SalesforceBulkOutputsSchema: Schema< {
173
+ payload: TAny;
174
+ }>;
175
+
119
176
  export declare class SalesforceConnection extends ConfigNode<Config_2, Credentials> {
120
177
  static readonly type = "salesforce-connection";
121
178
  static readonly configSchema: Schema;
@@ -142,23 +199,23 @@ refreshToken: TString;
142
199
  instanceUrl: TString;
143
200
  }>;
144
201
 
145
- export declare class SalesforceDescribe extends IONode<Config_4, any, Input_3, Output_2> {
202
+ export declare class SalesforceDescribe extends IONode<Config_5, any, Input_4, Output_3> {
146
203
  static readonly type = "salesforce-describe";
147
204
  static readonly category = "salesforce";
148
205
  static readonly color: `#${string}`;
149
206
  static readonly configSchema: Schema;
150
207
  static readonly inputSchema: Schema;
151
208
  static readonly outputsSchema: Schema;
152
- input(msg: Input_3): Promise<void>;
209
+ input(msg: Input_4): Promise<void>;
153
210
  }
154
211
 
155
212
  export declare const SalesforceDescribeConfigSchema: Schema< {
156
213
  name: TString;
157
214
  connection: TNodeRef<SalesforceConnection>;
158
215
  sObjectType: TTypedInput<string>;
159
- emitError: TBoolean;
160
- emitComplete: TBoolean;
161
- emitStatus: TBoolean;
216
+ errorPort: TBoolean;
217
+ completePort: TBoolean;
218
+ statusPort: TBoolean;
162
219
  }>;
163
220
 
164
221
  export declare const SalesforceDescribeInputSchema: Schema< {
@@ -174,14 +231,14 @@ recordTypeInfos: TArray<TAny>;
174
231
  }>;
175
232
  }>;
176
233
 
177
- export declare class SalesforceDml extends IONode<Config_5, any, Input_4, Output_3> {
234
+ export declare class SalesforceDml extends IONode<Config_6, any, Input_5, Output_4> {
178
235
  static readonly type = "salesforce-dml";
179
236
  static readonly category = "salesforce";
180
237
  static readonly color: `#${string}`;
181
238
  static readonly configSchema: Schema;
182
239
  static readonly inputSchema: Schema;
183
240
  static readonly outputsSchema: Schema;
184
- input(msg: Input_4): Promise<void>;
241
+ input(msg: Input_5): Promise<void>;
185
242
  }
186
243
 
187
244
  export declare const SalesforceDmlConfigSchema: Schema< {
@@ -191,9 +248,9 @@ operation: TUnion<[TLiteral<"create">, TLiteral<"read">, TLiteral<"update">, TLi
191
248
  sObjectType: TTypedInput<string>;
192
249
  record: TTypedInput<any>;
193
250
  externalIdField: TOptional<TString>;
194
- emitError: TBoolean;
195
- emitComplete: TBoolean;
196
- emitStatus: TBoolean;
251
+ errorPort: TBoolean;
252
+ completePort: TBoolean;
253
+ statusPort: TBoolean;
197
254
  }>;
198
255
 
199
256
  export declare const SalesforceDmlInputSchema: Schema< {
@@ -204,20 +261,23 @@ export declare const SalesforceDmlOutputsSchema: Schema< {
204
261
  payload: TAny;
205
262
  }>;
206
263
 
207
- export declare class SalesforceSoql extends IONode<Config_6, any, Input_5, Output_4> {
264
+ export declare class SalesforceSoql extends IONode<Config_7, any, Input_6, Output_5> {
208
265
  static readonly type = "salesforce-soql";
209
266
  static readonly category = "salesforce";
210
267
  static readonly color: `#${string}`;
211
268
  static readonly configSchema: Schema;
212
269
  static readonly inputSchema: Schema;
213
270
  static readonly outputsSchema: Schema;
214
- input(msg: Input_5): Promise<void>;
271
+ input(msg: Input_6): Promise<void>;
215
272
  }
216
273
 
217
274
  export declare const SalesforceSoqlConfigSchema: Schema< {
218
275
  name: TString;
219
276
  connection: TNodeRef<SalesforceConnection>;
220
277
  query: TTypedInput<string>;
278
+ errorPort: TBoolean;
279
+ completePort: TBoolean;
280
+ statusPort: TBoolean;
221
281
  }>;
222
282
 
223
283
  export declare const SalesforceSoqlInputSchema: Schema< {
@@ -230,7 +290,7 @@ totalSize: TNumber;
230
290
  done: TBoolean;
231
291
  }>;
232
292
 
233
- export declare class SalesforceStreaming extends IONode<Config_7, any, any, Output_5> {
293
+ export declare class SalesforceStreaming extends IONode<Config_8, any, any, Output_6> {
234
294
  static readonly type = "salesforce-streaming";
235
295
  static readonly category = "salesforce";
236
296
  static readonly color: `#${string}`;
@@ -256,8 +316,9 @@ channelName: TString;
256
316
  subscribeType: TUnion<[TLiteral<"LATEST">, TLiteral<"EARLIEST">, TLiteral<"CUSTOM">]>;
257
317
  replayId: TOptional<TString>;
258
318
  numRequested: TNumber;
259
- emitError: TBoolean;
260
- emitStatus: TBoolean;
319
+ errorPort: TBoolean;
320
+ completePort: TBoolean;
321
+ statusPort: TBoolean;
261
322
  }>;
262
323
 
263
324
  export declare const SalesforceStreamingOutputsSchema: Schema< {
@@ -267,4 +328,6 @@ channel: TString;
267
328
  topic: TString;
268
329
  }>;
269
330
 
331
+ declare type Settings = Infer<typeof SalesforceApexCodeSettingsSchema>;
332
+
270
333
  export { }
package/index.html CHANGED
@@ -63,4 +63,4 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
63
63
  LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
64
64
 
65
65
  -->
66
- <script type="module" src="resources/@bonsae/node-red-salesforce/index.BmVSYWAa.js" defer></script>
66
+ <script type="module" src="resources/@bonsae/node-red-salesforce/index.dnWzY-T-.js" defer></script>