@bonsae/node-red-salesforce 0.4.1 → 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,38 +18,44 @@ 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>;
40
45
 
41
- declare type Input_2 = Infer<typeof SalesforceBulkInputSchema>;
46
+ declare type Input_3 = {
47
+ payload: string | Record<string, unknown>[] | Readable;
48
+ };
42
49
 
43
- declare type Input_3 = Infer<typeof SalesforceDescribeInputSchema>;
50
+ declare type Input_4 = Infer<typeof SalesforceDescribeInputSchema>;
44
51
 
45
- declare type Input_4 = Infer<typeof SalesforceDmlInputSchema>;
52
+ declare type Input_5 = Infer<typeof SalesforceDmlInputSchema>;
46
53
 
47
- declare type Input_5 = Infer<typeof SalesforceSoqlInputSchema>;
54
+ declare type Input_6 = Infer<typeof SalesforceSoqlInputSchema>;
48
55
 
49
- declare type Output = Infer<typeof SalesforceApexOutputsSchema>;
56
+ declare type Output = Infer<typeof SalesforceApexCodeOutputsSchema>;
50
57
 
51
- declare type Output_2 = Infer<typeof outputsSchema>;
58
+ declare type Output_2 = Infer<typeof SalesforceApexInvocationOutputsSchema>;
52
59
 
53
60
  declare type Output_3 = Infer<typeof SalesforceDescribeOutputsSchema>;
54
61
 
@@ -58,59 +65,95 @@ declare type Output_5 = Infer<typeof SalesforceSoqlOutputsSchema>;
58
65
 
59
66
  declare type Output_6 = Infer<typeof SalesforceStreamingOutputsSchema>;
60
67
 
61
- declare const outputsSchema: {
62
- record: Schema<{}>;
63
- jobCreated: Schema<{}>;
64
- };
65
-
66
- export declare class SalesforceApex extends IONode<Config, any, Input, Output> {
67
- static readonly type = "salesforce-apex";
68
+ export declare class SalesforceApexCode extends IONode<Config, any, Input, Output, Settings> {
69
+ static readonly type = "salesforce-apex-code";
68
70
  static readonly category = "salesforce";
69
71
  static readonly color: `#${string}`;
70
72
  static readonly configSchema: Schema;
71
73
  static readonly inputSchema: Schema;
72
74
  static readonly outputsSchema: Schema;
75
+ static readonly settingsSchema: Schema;
76
+ private deployed;
77
+ private getFullClassName;
78
+ private buildApexBody;
79
+ created(): Promise<void>;
73
80
  input(msg: Input): Promise<void>;
81
+ closed(removed?: boolean): Promise<void>;
82
+ }
83
+
84
+ export declare const SalesforceApexCodeConfigSchema: Schema< {
85
+ name: TString;
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>;
74
117
  }
75
118
 
76
- export declare const SalesforceApexConfigSchema: Schema< {
119
+ export declare const SalesforceApexInvocationConfigSchema: Schema< {
77
120
  name: TString;
78
121
  connection: TNodeRef<SalesforceConnection>;
122
+ apexType: TUnion<[TLiteral<"rest">, TLiteral<"invocable">]>;
79
123
  method: TUnion<[TLiteral<"GET">, TLiteral<"POST">, TLiteral<"PUT">, TLiteral<"PATCH">, TLiteral<"DELETE">]>;
80
124
  path: TTypedInput<string>;
125
+ actionName: TString;
81
126
  errorPort: TBoolean;
82
127
  completePort: TBoolean;
83
128
  statusPort: TBoolean;
84
129
  }>;
85
130
 
86
- export declare const SalesforceApexInputSchema: Schema< {
131
+ export declare const SalesforceApexInvocationInputSchema: Schema< {
87
132
  payload: TAny;
88
133
  }>;
89
134
 
90
- export declare const SalesforceApexOutputsSchema: Schema< {
135
+ export declare const SalesforceApexInvocationOutputsSchema: Schema< {
91
136
  payload: TAny;
92
137
  }>;
93
138
 
94
- export declare class SalesforceBulk extends IONode<Config_3, any, Input_2, Output_2> {
139
+ export declare class SalesforceBulk extends IONode<Config_4, any, Input_3> {
95
140
  static readonly type = "salesforce-bulk";
96
141
  static readonly category = "salesforce";
97
142
  static readonly color: `#${string}`;
98
143
  static readonly configSchema: Schema;
99
144
  static readonly inputSchema: Schema;
100
- static readonly outputsSchema: {
101
- record: Schema<{}>;
102
- jobCreated: Schema<{}>;
103
- };
104
- private sendRecord;
105
- private sendJobCreated;
106
- input(msg: Input_2): Promise<void>;
145
+ static readonly outputsSchema: Schema;
146
+ input(msg: Input_3): Promise<void>;
147
+ private executeQuery;
148
+ private executeIngest;
107
149
  }
108
150
 
109
151
  export declare const SalesforceBulkConfigSchema: Schema< {
110
152
  name: TString;
111
153
  connection: TNodeRef<SalesforceConnection>;
112
- 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">]>;
113
155
  sObjectType: TTypedInput<string>;
156
+ query: TTypedInput<string>;
114
157
  externalIdField: TOptional<TString>;
115
158
  assignmentRuleId: TOptional<TString>;
116
159
  columnDelimiter: TUnion<[TLiteral<"COMMA">, TLiteral<"TAB">, TLiteral<"PIPE">, TLiteral<"SEMICOLON">, TLiteral<"CARET">, TLiteral<"BACKQUOTE">]>;
@@ -126,6 +169,10 @@ export declare const SalesforceBulkInputSchema: Schema< {
126
169
  payload: TAny;
127
170
  }>;
128
171
 
172
+ export declare const SalesforceBulkOutputsSchema: Schema< {
173
+ payload: TAny;
174
+ }>;
175
+
129
176
  export declare class SalesforceConnection extends ConfigNode<Config_2, Credentials> {
130
177
  static readonly type = "salesforce-connection";
131
178
  static readonly configSchema: Schema;
@@ -152,14 +199,14 @@ refreshToken: TString;
152
199
  instanceUrl: TString;
153
200
  }>;
154
201
 
155
- export declare class SalesforceDescribe extends IONode<Config_4, any, Input_3, Output_3> {
202
+ export declare class SalesforceDescribe extends IONode<Config_5, any, Input_4, Output_3> {
156
203
  static readonly type = "salesforce-describe";
157
204
  static readonly category = "salesforce";
158
205
  static readonly color: `#${string}`;
159
206
  static readonly configSchema: Schema;
160
207
  static readonly inputSchema: Schema;
161
208
  static readonly outputsSchema: Schema;
162
- input(msg: Input_3): Promise<void>;
209
+ input(msg: Input_4): Promise<void>;
163
210
  }
164
211
 
165
212
  export declare const SalesforceDescribeConfigSchema: Schema< {
@@ -184,14 +231,14 @@ recordTypeInfos: TArray<TAny>;
184
231
  }>;
185
232
  }>;
186
233
 
187
- export declare class SalesforceDml extends IONode<Config_5, any, Input_4, Output_4> {
234
+ export declare class SalesforceDml extends IONode<Config_6, any, Input_5, Output_4> {
188
235
  static readonly type = "salesforce-dml";
189
236
  static readonly category = "salesforce";
190
237
  static readonly color: `#${string}`;
191
238
  static readonly configSchema: Schema;
192
239
  static readonly inputSchema: Schema;
193
240
  static readonly outputsSchema: Schema;
194
- input(msg: Input_4): Promise<void>;
241
+ input(msg: Input_5): Promise<void>;
195
242
  }
196
243
 
197
244
  export declare const SalesforceDmlConfigSchema: Schema< {
@@ -214,14 +261,14 @@ export declare const SalesforceDmlOutputsSchema: Schema< {
214
261
  payload: TAny;
215
262
  }>;
216
263
 
217
- export declare class SalesforceSoql extends IONode<Config_6, any, Input_5, Output_5> {
264
+ export declare class SalesforceSoql extends IONode<Config_7, any, Input_6, Output_5> {
218
265
  static readonly type = "salesforce-soql";
219
266
  static readonly category = "salesforce";
220
267
  static readonly color: `#${string}`;
221
268
  static readonly configSchema: Schema;
222
269
  static readonly inputSchema: Schema;
223
270
  static readonly outputsSchema: Schema;
224
- input(msg: Input_5): Promise<void>;
271
+ input(msg: Input_6): Promise<void>;
225
272
  }
226
273
 
227
274
  export declare const SalesforceSoqlConfigSchema: Schema< {
@@ -243,7 +290,7 @@ totalSize: TNumber;
243
290
  done: TBoolean;
244
291
  }>;
245
292
 
246
- export declare class SalesforceStreaming extends IONode<Config_7, any, any, Output_6> {
293
+ export declare class SalesforceStreaming extends IONode<Config_8, any, any, Output_6> {
247
294
  static readonly type = "salesforce-streaming";
248
295
  static readonly category = "salesforce";
249
296
  static readonly color: `#${string}`;
@@ -281,4 +328,6 @@ channel: TString;
281
328
  topic: TString;
282
329
  }>;
283
330
 
331
+ declare type Settings = Infer<typeof SalesforceApexCodeSettingsSchema>;
332
+
284
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.FDBQSjT7.js" defer></script>
66
+ <script type="module" src="resources/@bonsae/node-red-salesforce/index.dnWzY-T-.js" defer></script>