@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/index.mjs ADDED
@@ -0,0 +1,913 @@
1
+ var P = Object.defineProperty;
2
+ var J = (r, o, n) => o in r ? P(r, o, { enumerable: !0, configurable: !0, writable: !0, value: n }) : r[o] = n;
3
+ var f = (r, o) => P(r, "name", { value: o, configurable: !0 });
4
+ var i = (r, o, n) => J(r, typeof o != "symbol" ? o + "" : o, n);
5
+ import { fileURLToPath as V } from "url";
6
+ import { dirname as H } from "path";
7
+ import { registerTypes as Y } from "@bonsae/nrg/server";
8
+ import { defineSchema as h, SchemaType as t, ConfigNode as G, IONode as F, defineModule as K } from "@bonsae/nrg/server";
9
+ import W from "jsforce";
10
+ import N from "node:crypto";
11
+ var Q = V(import.meta.url), Lt = H(Q);
12
+ const X = h(
13
+ {
14
+ name: t.String({ default: "" }),
15
+ loginUrl: t.String({
16
+ default: "https://login.salesforce.com",
17
+ "x-nrg-form": { icon: "globe" }
18
+ }),
19
+ clientId: t.String({
20
+ default: "",
21
+ "x-nrg-form": { icon: "key" }
22
+ }),
23
+ apiVersion: t.Union(
24
+ [
25
+ t.Literal("62.0"),
26
+ t.Literal("61.0"),
27
+ t.Literal("60.0"),
28
+ t.Literal("59.0"),
29
+ t.Literal("58.0"),
30
+ t.Literal("57.0"),
31
+ t.Literal("56.0"),
32
+ t.Literal("55.0")
33
+ ],
34
+ { default: "62.0", "x-nrg-form": { icon: "code-fork" } }
35
+ ),
36
+ callbackUrl: t.Optional(
37
+ t.String({
38
+ default: "",
39
+ "x-nrg-form": { icon: "exchange" }
40
+ })
41
+ )
42
+ },
43
+ { $id: "salesforce-connection:config" }
44
+ ), Z = h(
45
+ {
46
+ accessToken: t.String({ default: "", format: "password" }),
47
+ refreshToken: t.String({ default: "", format: "password" }),
48
+ instanceUrl: t.String({ default: "" })
49
+ },
50
+ { $id: "salesforce-connection:credentials" }
51
+ ), z = 600 * 1e3, C = /* @__PURE__ */ new Map();
52
+ function B() {
53
+ return N.randomBytes(32).toString("base64url");
54
+ }
55
+ f(B, "generateCodeVerifier");
56
+ function D(r) {
57
+ return N.createHash("sha256").update(r).digest("base64url");
58
+ }
59
+ f(D, "generateCodeChallenge");
60
+ function _(r) {
61
+ const o = N.randomUUID(), n = B(), e = D(n);
62
+ C.set(o, {
63
+ codeVerifier: n,
64
+ nodeId: r.nodeId,
65
+ clientId: r.clientId,
66
+ loginUrl: r.loginUrl,
67
+ callbackUrl: r.callbackUrl,
68
+ timestamp: Date.now()
69
+ });
70
+ for (const [s, a] of C)
71
+ Date.now() - a.timestamp > z && C.delete(s);
72
+ return { state: o, codeChallenge: e };
73
+ }
74
+ f(_, "createAuthState");
75
+ function tt(r) {
76
+ const o = C.get(r);
77
+ return !o || (C.delete(r), Date.now() - o.timestamp > z) ? null : o;
78
+ }
79
+ f(tt, "consumeAuthState");
80
+ function et(r) {
81
+ return r.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
82
+ }
83
+ f(et, "escapeHtml");
84
+ function k(r, o = !0) {
85
+ const n = o ? "<script>setTimeout(function(){window.close()},3000)</script>" : "";
86
+ return `<html><body><h2>Authorization Failed</h2><p>${et(r)}</p>${n}</body></html>`;
87
+ }
88
+ f(k, "errorPage");
89
+ function nt(r) {
90
+ const o = (r.settings.httpAdminRoot || "").replace(
91
+ /\/$/,
92
+ ""
93
+ );
94
+ r.httpAdmin.post("/salesforce/auth/start", (n, e) => {
95
+ try {
96
+ const {
97
+ nodeId: s,
98
+ loginUrl: a,
99
+ clientId: l,
100
+ callbackUrl: d
101
+ } = n.body;
102
+ if (!s || !a || !l) {
103
+ e.status(400).json({ error: "nodeId, loginUrl, and clientId are required" });
104
+ return;
105
+ }
106
+ const c = d || `${n.protocol}://${n.get("host")}${o}/salesforce/auth/callback`, { state: g, codeChallenge: u } = _({
107
+ nodeId: s,
108
+ clientId: l,
109
+ loginUrl: a,
110
+ callbackUrl: c
111
+ }), p = new URLSearchParams({
112
+ response_type: "code",
113
+ client_id: l,
114
+ redirect_uri: c,
115
+ state: g,
116
+ code_challenge: u,
117
+ code_challenge_method: "S256"
118
+ });
119
+ e.json({
120
+ authorizationUrl: `${a}/services/oauth2/authorize?${p.toString()}`
121
+ });
122
+ } catch (s) {
123
+ r.log.error(
124
+ `salesforce-connection: auth/start error: ${s instanceof Error ? s.message : String(s)}`
125
+ ), e.status(500).json({ error: "Failed to start authorization" });
126
+ }
127
+ }), r.httpAdmin.get("/salesforce/auth/callback", async (n, e) => {
128
+ try {
129
+ const { code: s, state: a, error: l, error_description: d } = n.query;
130
+ if (l) {
131
+ r.log.error(
132
+ `salesforce-connection: OAuth error: ${l} - ${d}`
133
+ ), e.status(400).send(k(String(d || l)));
134
+ return;
135
+ }
136
+ if (!s || !a) {
137
+ e.status(400).send(k("Missing code or state parameter"));
138
+ return;
139
+ }
140
+ const c = tt(a);
141
+ if (!c) {
142
+ e.status(400).send(
143
+ k(
144
+ "Invalid or expired authorization state. Please try again."
145
+ )
146
+ );
147
+ return;
148
+ }
149
+ const g = await fetch(
150
+ `${c.loginUrl}/services/oauth2/token`,
151
+ {
152
+ method: "POST",
153
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
154
+ body: new URLSearchParams({
155
+ grant_type: "authorization_code",
156
+ code: s,
157
+ client_id: c.clientId,
158
+ redirect_uri: c.callbackUrl,
159
+ code_verifier: c.codeVerifier
160
+ })
161
+ }
162
+ );
163
+ if (!g.ok) {
164
+ const w = await g.text();
165
+ r.log.error(
166
+ `salesforce-connection: Token exchange failed: ${w}`
167
+ ), e.status(500).send(
168
+ k(
169
+ "Token exchange failed. Check the Node-RED logs for details."
170
+ )
171
+ );
172
+ return;
173
+ }
174
+ const u = await g.json();
175
+ r.nodes.addCredentials(c.nodeId, {
176
+ accessToken: u.access_token,
177
+ refreshToken: u.refresh_token,
178
+ instanceUrl: u.instance_url
179
+ }), r.log.info(
180
+ `salesforce-connection: Successfully authorized node ${c.nodeId} for ${u.instance_url}`
181
+ );
182
+ const p = JSON.stringify({
183
+ type: "salesforce-auth-success",
184
+ nodeId: c.nodeId,
185
+ accessToken: u.access_token,
186
+ refreshToken: u.refresh_token,
187
+ instanceUrl: u.instance_url
188
+ });
189
+ e.send(`<!DOCTYPE html>
190
+ <html>
191
+ <body>
192
+ <h2>Authorization Successful</h2>
193
+ <p>You can close this window.</p>
194
+ <script>
195
+ if (window.opener) {
196
+ window.opener.postMessage(${p}, "*");
197
+ }
198
+ setTimeout(function() { window.close(); }, 1500);
199
+ </script>
200
+ </body>
201
+ </html>`);
202
+ } catch (s) {
203
+ r.log.error(
204
+ `salesforce-connection: auth/callback error: ${s instanceof Error ? s.message : String(s)}`
205
+ ), e.status(500).send(k("An unexpected error occurred."));
206
+ }
207
+ }), r.httpAdmin.get("/salesforce/auth/status/:nodeId", (n, e) => {
208
+ try {
209
+ const s = r.nodes.getCredentials(n.params.nodeId), a = !!(s != null && s.accessToken && (s != null && s.instanceUrl));
210
+ e.json({
211
+ authenticated: a,
212
+ instanceUrl: a ? s.instanceUrl : void 0
213
+ });
214
+ } catch {
215
+ e.json({ authenticated: !1 });
216
+ }
217
+ });
218
+ }
219
+ f(nt, "initAuthRoutes");
220
+ function ot(r) {
221
+ nt(r);
222
+ }
223
+ f(ot, "initRoutes");
224
+ const L = class L extends G {
225
+ constructor() {
226
+ super(...arguments);
227
+ i(this, "conn", null);
228
+ }
229
+ static async registered(n) {
230
+ ot(n);
231
+ }
232
+ async getConnection() {
233
+ if (this.conn) return this.conn;
234
+ const n = this.credentials;
235
+ if (!(n != null && n.accessToken) || !(n != null && n.instanceUrl))
236
+ throw new Error(
237
+ "Salesforce connection not authorized. Please authorize in the node configuration."
238
+ );
239
+ return this.conn = new W.Connection({
240
+ oauth2: {
241
+ clientId: this.config.clientId,
242
+ loginUrl: this.config.loginUrl
243
+ },
244
+ instanceUrl: n.instanceUrl,
245
+ accessToken: n.accessToken,
246
+ refreshToken: n.refreshToken,
247
+ version: this.config.apiVersion
248
+ }), this.conn.on("refresh", (e) => {
249
+ this.RED.nodes.addCredentials(this.id, {
250
+ ...this.credentials,
251
+ accessToken: e
252
+ });
253
+ }), this.conn;
254
+ }
255
+ getAccessToken() {
256
+ var n;
257
+ return (n = this.credentials) == null ? void 0 : n.accessToken;
258
+ }
259
+ getInstanceUrl() {
260
+ var n;
261
+ return (n = this.credentials) == null ? void 0 : n.instanceUrl;
262
+ }
263
+ async closed() {
264
+ this.conn = null;
265
+ }
266
+ };
267
+ f(L, "SalesforceConnection"), i(L, "type", "salesforce-connection"), i(L, "configSchema", X), i(L, "credentialsSchema", Z);
268
+ let $ = L;
269
+ const it = h(
270
+ {
271
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
272
+ connection: t.NodeRef($, {
273
+ "x-nrg-form": { icon: "cloud" }
274
+ }),
275
+ query: t.TypedInput({
276
+ "x-nrg-form": {
277
+ icon: "search",
278
+ typedInputTypes: ["str", "msg", "flow", "global"]
279
+ }
280
+ })
281
+ },
282
+ { $id: "salesforce-soql:config" }
283
+ ), st = h(
284
+ {
285
+ payload: t.Any()
286
+ },
287
+ { $id: "salesforce-soql:input" }
288
+ ), rt = h(
289
+ {
290
+ payload: t.Array(t.Any()),
291
+ totalSize: t.Number(),
292
+ done: t.Boolean()
293
+ },
294
+ { $id: "salesforce-soql:output" }
295
+ ), m = class m extends F {
296
+ async input(o) {
297
+ const n = this.config.connection;
298
+ if (!n) {
299
+ this.error("No Salesforce connection configured", o);
300
+ return;
301
+ }
302
+ try {
303
+ this.status({ fill: "green", shape: "dot", text: "querying..." });
304
+ const e = await n.getConnection(), s = await this.config.query.resolve(o), a = await e.query(s);
305
+ this.status({
306
+ fill: "green",
307
+ shape: "dot",
308
+ text: `${a.totalSize} records`
309
+ }), this.send({
310
+ ...o,
311
+ payload: a.records,
312
+ totalSize: a.totalSize,
313
+ done: a.done
314
+ });
315
+ } catch (e) {
316
+ this.status({
317
+ fill: "red",
318
+ shape: "dot",
319
+ text: e instanceof Error ? e.message : String(e)
320
+ }), this.error(
321
+ `SOQL query failed: ${e instanceof Error ? e.message : String(e)}`,
322
+ o
323
+ );
324
+ }
325
+ }
326
+ };
327
+ f(m, "SalesforceSoql"), i(m, "type", "salesforce-soql"), i(m, "category", "salesforce"), i(m, "color", "#FFFFFF"), i(m, "inputs", 1), i(m, "outputs", 1), i(m, "configSchema", it), i(m, "inputSchema", st), i(m, "outputsSchema", rt);
328
+ let O = m;
329
+ const at = h(
330
+ {
331
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
332
+ connection: t.NodeRef($, {
333
+ "x-nrg-form": { icon: "cloud" }
334
+ }),
335
+ operation: t.Union(
336
+ [
337
+ t.Literal("create"),
338
+ t.Literal("read"),
339
+ t.Literal("update"),
340
+ t.Literal("delete"),
341
+ t.Literal("upsert")
342
+ ],
343
+ { default: "create", "x-nrg-form": { icon: "pencil" } }
344
+ ),
345
+ sObjectType: t.TypedInput({
346
+ "x-nrg-form": {
347
+ icon: "cube",
348
+ typedInputTypes: ["str", "msg"]
349
+ }
350
+ }),
351
+ record: t.TypedInput({
352
+ "x-nrg-form": {
353
+ icon: "file-code-o",
354
+ typedInputTypes: ["json", "msg"]
355
+ }
356
+ }),
357
+ externalIdField: t.Optional(
358
+ t.String({
359
+ default: "",
360
+ "x-nrg-form": { icon: "key" }
361
+ })
362
+ )
363
+ },
364
+ {
365
+ $id: "salesforce-dml:config",
366
+ if: t.Object({
367
+ operation: t.Literal("upsert")
368
+ }),
369
+ then: t.Object({
370
+ externalIdField: t.String({ minLength: 1 })
371
+ }),
372
+ errorMessage: {
373
+ properties: {
374
+ externalIdField: "External ID Field is required for upsert operations"
375
+ }
376
+ }
377
+ }
378
+ ), ct = h(
379
+ {
380
+ payload: t.Any()
381
+ },
382
+ { $id: "salesforce-dml:input" }
383
+ ), lt = h(
384
+ {
385
+ payload: t.Any()
386
+ },
387
+ { $id: "salesforce-dml:output" }
388
+ ), y = class y extends F {
389
+ async input(o) {
390
+ const n = this.config.connection;
391
+ if (!n) {
392
+ this.error("No Salesforce connection configured", o);
393
+ return;
394
+ }
395
+ try {
396
+ const e = this.config.operation;
397
+ this.status({ fill: "green", shape: "dot", text: `${e}...` });
398
+ const s = await n.getConnection(), a = await this.config.sObjectType.resolve(o), l = s.sobject(a), d = await this.config.record.resolve(o) ?? o.payload;
399
+ let c;
400
+ switch (e) {
401
+ case "create":
402
+ c = await l.create(d);
403
+ break;
404
+ case "read":
405
+ c = await l.retrieve(d);
406
+ break;
407
+ case "update":
408
+ c = await l.update(d);
409
+ break;
410
+ case "delete":
411
+ c = await l.destroy(d);
412
+ break;
413
+ case "upsert":
414
+ c = await l.upsert(d, this.config.externalIdField);
415
+ break;
416
+ default:
417
+ throw new Error(`Unknown operation: ${e}`);
418
+ }
419
+ this.status({ fill: "green", shape: "dot", text: `${e} done` }), this.send({ ...o, payload: c });
420
+ } catch (e) {
421
+ this.status({
422
+ fill: "red",
423
+ shape: "dot",
424
+ text: e instanceof Error ? e.message : String(e)
425
+ }), this.error(
426
+ `DML ${this.config.operation} failed: ${e instanceof Error ? e.message : String(e)}`,
427
+ o
428
+ );
429
+ }
430
+ }
431
+ };
432
+ f(y, "SalesforceDml"), i(y, "type", "salesforce-dml"), i(y, "category", "salesforce"), i(y, "color", "#FFFFFF"), i(y, "inputs", 1), i(y, "outputs", 1), i(y, "configSchema", at), i(y, "inputSchema", ct), i(y, "outputsSchema", lt);
433
+ let R = y;
434
+ const dt = h(
435
+ {
436
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
437
+ connection: t.NodeRef($, {
438
+ "x-nrg-form": { icon: "cloud" }
439
+ }),
440
+ operation: t.Union(
441
+ [
442
+ t.Literal("insert"),
443
+ t.Literal("update"),
444
+ t.Literal("upsert"),
445
+ t.Literal("delete"),
446
+ t.Literal("query")
447
+ ],
448
+ { default: "insert", "x-nrg-form": { icon: "database" } }
449
+ ),
450
+ sObjectType: t.TypedInput({
451
+ "x-nrg-form": {
452
+ icon: "cube",
453
+ typedInputTypes: ["str", "msg"]
454
+ }
455
+ }),
456
+ externalIdField: t.Optional(
457
+ t.String({
458
+ default: "",
459
+ "x-nrg-form": { icon: "key" }
460
+ })
461
+ ),
462
+ assignmentRuleId: t.Optional(
463
+ t.String({
464
+ default: "",
465
+ "x-nrg-form": { icon: "gavel" }
466
+ })
467
+ ),
468
+ columnDelimiter: t.Union(
469
+ [
470
+ t.Literal("COMMA"),
471
+ t.Literal("TAB"),
472
+ t.Literal("PIPE"),
473
+ t.Literal("SEMICOLON"),
474
+ t.Literal("CARET"),
475
+ t.Literal("BACKQUOTE")
476
+ ],
477
+ { default: "COMMA", "x-nrg-form": { icon: "columns" } }
478
+ ),
479
+ lineEnding: t.Union(
480
+ [t.Literal("LF"), t.Literal("CRLF")],
481
+ { default: "LF", "x-nrg-form": { icon: "level-down" } }
482
+ ),
483
+ pollInterval: t.Number({
484
+ default: 5e3,
485
+ minimum: 1e3,
486
+ "x-nrg-form": { icon: "clock-o" }
487
+ }),
488
+ pollTimeout: t.Number({
489
+ default: 6e4,
490
+ minimum: 5e3,
491
+ "x-nrg-form": { icon: "hourglass" }
492
+ }),
493
+ emitJobCreated: t.Boolean({
494
+ default: !1,
495
+ "x-nrg-form": { icon: "flag", toggle: !0 }
496
+ }),
497
+ outputs: t.Number({ default: 2 })
498
+ },
499
+ {
500
+ $id: "salesforce-bulk:config",
501
+ if: t.Object({
502
+ operation: t.Literal("upsert")
503
+ }),
504
+ then: t.Object({
505
+ externalIdField: t.String({ minLength: 1 })
506
+ }),
507
+ errorMessage: {
508
+ properties: {
509
+ externalIdField: "External ID Field is required for upsert operations"
510
+ }
511
+ }
512
+ }
513
+ ), ut = h(
514
+ {
515
+ payload: t.Any()
516
+ },
517
+ { $id: "salesforce-bulk:input" }
518
+ );
519
+ h(
520
+ {
521
+ payload: t.Array(t.Any())
522
+ },
523
+ { $id: "salesforce-bulk:output" }
524
+ );
525
+ const T = class T extends F {
526
+ sendRecord(o, n) {
527
+ const e = this.config.emitJobCreated ? 3 : 2, s = Array(e).fill(null);
528
+ s[0] = { ...o, payload: n }, this.send(s);
529
+ }
530
+ sendJobCreated(o, n) {
531
+ this.config.emitJobCreated && this.send([null, null, { ...o, payload: n }]);
532
+ }
533
+ sendComplete(o, n) {
534
+ const e = this.config.emitJobCreated ? 3 : 2, s = Array(e).fill(null);
535
+ s[1] = { ...o, payload: n }, this.send(s);
536
+ }
537
+ async input(o) {
538
+ const n = this.config.connection;
539
+ if (!n) {
540
+ this.error("No Salesforce connection configured", o);
541
+ return;
542
+ }
543
+ try {
544
+ const e = this.config.operation;
545
+ this.status({
546
+ fill: "green",
547
+ shape: "dot",
548
+ text: `bulk ${e}...`
549
+ });
550
+ const s = await n.getConnection(), a = await this.config.sObjectType.resolve(o);
551
+ let l = 0;
552
+ if (e === "query") {
553
+ const d = await s.bulk2.query(o.payload, {
554
+ pollTimeout: this.config.pollTimeout,
555
+ pollInterval: this.config.pollInterval,
556
+ columnDelimiter: this.config.columnDelimiter,
557
+ lineEnding: this.config.lineEnding
558
+ });
559
+ await new Promise((c, g) => {
560
+ d.on("data", (u) => {
561
+ l++, this.sendRecord(o, u);
562
+ }), d.on("end", () => c()), d.on("error", g);
563
+ }), this.status({
564
+ fill: "green",
565
+ shape: "dot",
566
+ text: `bulk ${e}: ${l} records`
567
+ }), this.sendComplete(o, { operation: e, sObjectType: a, totalRecords: l });
568
+ } else {
569
+ const d = o.payload, c = s.bulk2.createJob({
570
+ operation: e,
571
+ object: a,
572
+ columnDelimiter: this.config.columnDelimiter,
573
+ lineEnding: this.config.lineEnding,
574
+ ...e === "upsert" && this.config.externalIdField ? { externalIdFieldName: this.config.externalIdField } : {},
575
+ ...this.config.assignmentRuleId ? { assignmentRuleId: this.config.assignmentRuleId } : {}
576
+ });
577
+ await c.open(), this.sendJobCreated(o, {
578
+ jobId: c.id,
579
+ operation: e,
580
+ sObjectType: a,
581
+ state: "Open"
582
+ }), await c.uploadData(d), await c.close(), await c.poll(this.config.pollInterval, this.config.pollTimeout);
583
+ const g = await c.getAllResults(), u = g.successfulResults ?? [], p = g.failedResults ?? [], w = g.unprocessedRecords ?? [];
584
+ l = u.length + p.length + w.length;
585
+ for (const A of u)
586
+ this.sendRecord(o, A);
587
+ for (const A of p)
588
+ this.sendRecord(o, A);
589
+ const q = u.length, M = p.length;
590
+ this.status({
591
+ fill: M > 0 ? "red" : "green",
592
+ shape: "dot",
593
+ text: `bulk ${e}: ${l} records`
594
+ }), this.sendComplete(o, {
595
+ jobId: c.id,
596
+ operation: e,
597
+ sObjectType: a,
598
+ totalRecords: l,
599
+ successCount: q,
600
+ failureCount: M,
601
+ unprocessedCount: w.length
602
+ });
603
+ }
604
+ } catch (e) {
605
+ const s = e instanceof Error ? e.message : String(e);
606
+ this.status({ fill: "red", shape: "dot", text: s }), this.error(`Bulk ${this.config.operation} failed: ${s}`, o);
607
+ }
608
+ }
609
+ };
610
+ f(T, "SalesforceBulk"), i(T, "type", "salesforce-bulk"), i(T, "category", "salesforce"), i(T, "color", "#FFFFFF"), i(T, "inputs", 1), i(T, "outputs", 2), i(T, "configSchema", dt), i(T, "inputSchema", ut);
611
+ let S = T;
612
+ const ht = h(
613
+ {
614
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
615
+ connection: t.NodeRef($, {
616
+ "x-nrg-form": { icon: "cloud" }
617
+ }),
618
+ sObjectType: t.TypedInput({
619
+ "x-nrg-form": {
620
+ icon: "cube",
621
+ typedInputTypes: ["str", "msg"]
622
+ }
623
+ })
624
+ },
625
+ { $id: "salesforce-describe:config" }
626
+ ), pt = h(
627
+ {
628
+ payload: t.Any()
629
+ },
630
+ { $id: "salesforce-describe:input" }
631
+ ), ft = h(
632
+ {
633
+ payload: t.Object({
634
+ name: t.String(),
635
+ fields: t.Array(t.Any()),
636
+ childRelationships: t.Array(t.Any()),
637
+ recordTypeInfos: t.Array(t.Any())
638
+ })
639
+ },
640
+ { $id: "salesforce-describe:output" }
641
+ ), b = class b extends F {
642
+ async input(o) {
643
+ const n = this.config.connection;
644
+ if (!n) {
645
+ this.error("No Salesforce connection configured", o);
646
+ return;
647
+ }
648
+ try {
649
+ this.status({ fill: "green", shape: "dot", text: "describing..." });
650
+ const e = await n.getConnection(), s = await this.config.sObjectType.resolve(o), a = await e.sobject(s).describe();
651
+ this.status({
652
+ fill: "green",
653
+ shape: "dot",
654
+ text: `${a.name}: ${a.fields.length} fields`
655
+ }), this.send({
656
+ ...o,
657
+ payload: {
658
+ name: a.name,
659
+ fields: a.fields,
660
+ childRelationships: a.childRelationships,
661
+ recordTypeInfos: a.recordTypeInfos
662
+ }
663
+ });
664
+ } catch (e) {
665
+ this.status({
666
+ fill: "red",
667
+ shape: "dot",
668
+ text: e instanceof Error ? e.message : String(e)
669
+ }), this.error(
670
+ `Describe failed: ${e instanceof Error ? e.message : String(e)}`,
671
+ o
672
+ );
673
+ }
674
+ }
675
+ };
676
+ f(b, "SalesforceDescribe"), i(b, "type", "salesforce-describe"), i(b, "category", "salesforce"), i(b, "color", "#FFFFFF"), i(b, "inputs", 1), i(b, "outputs", 1), i(b, "configSchema", ht), i(b, "inputSchema", pt), i(b, "outputsSchema", ft);
677
+ let E = b;
678
+ const gt = h(
679
+ {
680
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
681
+ connection: t.NodeRef($, {
682
+ "x-nrg-form": { icon: "cloud" }
683
+ }),
684
+ channelName: t.String({
685
+ default: "",
686
+ "x-nrg-form": { icon: "rss" }
687
+ }),
688
+ subscribeType: t.Union(
689
+ [
690
+ t.Literal("LATEST"),
691
+ t.Literal("EARLIEST"),
692
+ t.Literal("CUSTOM")
693
+ ],
694
+ { default: "LATEST", "x-nrg-form": { icon: "history" } }
695
+ ),
696
+ replayId: t.Optional(
697
+ t.String({
698
+ default: "",
699
+ "x-nrg-form": { icon: "bookmark" }
700
+ })
701
+ ),
702
+ numRequested: t.Number({
703
+ default: 100,
704
+ minimum: 1,
705
+ maximum: 100,
706
+ "x-nrg-form": { icon: "sort-numeric-asc" }
707
+ })
708
+ },
709
+ {
710
+ $id: "salesforce-streaming:config",
711
+ if: t.Object({
712
+ subscribeType: t.Literal("CUSTOM")
713
+ }),
714
+ then: t.Object({
715
+ replayId: t.String({ minLength: 1 })
716
+ }),
717
+ errorMessage: {
718
+ properties: {
719
+ replayId: "Replay ID is required when Subscribe Type is CUSTOM"
720
+ }
721
+ }
722
+ }
723
+ ), mt = h(
724
+ {
725
+ payload: t.Any(),
726
+ replayId: t.Any(),
727
+ channel: t.String(),
728
+ topic: t.String()
729
+ },
730
+ { $id: "salesforce-streaming:output" }
731
+ ), I = class I extends F {
732
+ constructor() {
733
+ super(...arguments);
734
+ i(this, "client", null);
735
+ i(this, "reconnectAttempt", 0);
736
+ i(this, "maxReconnectDelay", 6e4);
737
+ }
738
+ async created() {
739
+ const n = this.config.connection;
740
+ if (!n) {
741
+ this.status({ fill: "red", shape: "dot", text: "no connection" }), this.error("No Salesforce connection configured");
742
+ return;
743
+ }
744
+ await this.subscribe(n);
745
+ }
746
+ async subscribe(n) {
747
+ try {
748
+ this.status({ fill: "green", shape: "dot", text: "connecting..." });
749
+ const e = n.getAccessToken(), s = n.getInstanceUrl();
750
+ if (!e || !s) {
751
+ this.status({ fill: "red", shape: "dot", text: "not authorized" }), this.error("Salesforce connection not authorized");
752
+ return;
753
+ }
754
+ const a = (await import("salesforce-pubsub-api-client")).default;
755
+ this.client = new a({
756
+ authType: "user-supplied",
757
+ accessToken: e,
758
+ instanceUrl: s
759
+ }), await this.client.connect();
760
+ const l = this.config.numRequested || null, d = this.config.channelName, c = /* @__PURE__ */ f((g, u, p) => {
761
+ if (u === "event" || u === "lastevent")
762
+ this.send({
763
+ payload: (p == null ? void 0 : p.payload) ?? p,
764
+ replayId: p == null ? void 0 : p.replayId,
765
+ channel: d,
766
+ topic: d
767
+ });
768
+ else if (u === "error") {
769
+ const w = p instanceof Error ? p.message : String(p ?? "stream error");
770
+ this.warn(`Streaming error: ${w}`), this.status({ fill: "red", shape: "dot", text: w }), this.scheduleReconnect(n);
771
+ } else u === "end" && (this.log("Streaming subscription ended"), this.status({ fill: "red", shape: "dot", text: "disconnected" }), this.scheduleReconnect(n));
772
+ }, "callback");
773
+ if (this.config.subscribeType === "EARLIEST")
774
+ this.client.subscribeFromEarliestEvent(
775
+ d,
776
+ c,
777
+ l
778
+ );
779
+ else if (this.config.subscribeType === "CUSTOM" && this.config.replayId) {
780
+ const g = parseInt(this.config.replayId, 10);
781
+ this.client.subscribeFromReplayId(
782
+ d,
783
+ c,
784
+ l,
785
+ g
786
+ );
787
+ } else
788
+ this.client.subscribe(d, c, l);
789
+ this.status({
790
+ fill: "green",
791
+ shape: "dot",
792
+ text: `subscribed: ${d}`
793
+ }), this.reconnectAttempt = 0;
794
+ } catch (e) {
795
+ this.status({
796
+ fill: "red",
797
+ shape: "dot",
798
+ text: e instanceof Error ? e.message : String(e)
799
+ }), this.error(
800
+ `Streaming subscription failed: ${e instanceof Error ? e.message : String(e)}`
801
+ ), this.scheduleReconnect(n);
802
+ }
803
+ }
804
+ scheduleReconnect(n) {
805
+ this.reconnectAttempt++;
806
+ const e = Math.min(
807
+ 1e3 * Math.pow(2, this.reconnectAttempt),
808
+ this.maxReconnectDelay
809
+ );
810
+ this.log(
811
+ `Scheduling reconnect in ${e}ms (attempt ${this.reconnectAttempt})`
812
+ ), this.status({
813
+ fill: "green",
814
+ shape: "dot",
815
+ text: `reconnecting in ${Math.round(e / 1e3)}s`
816
+ }), this.setTimeout(async () => {
817
+ await this.cleanup(), await this.subscribe(n);
818
+ }, e);
819
+ }
820
+ async cleanup() {
821
+ var n, e;
822
+ try {
823
+ this.client && (await ((e = (n = this.client).close) == null ? void 0 : e.call(n)), this.client = null);
824
+ } catch {
825
+ }
826
+ }
827
+ async input() {
828
+ }
829
+ async closed() {
830
+ await this.cleanup();
831
+ }
832
+ };
833
+ f(I, "SalesforceStreaming"), i(I, "type", "salesforce-streaming"), i(I, "category", "salesforce"), i(I, "color", "#FFFFFF"), i(I, "inputs", 0), i(I, "outputs", 1), i(I, "configSchema", gt), i(I, "outputsSchema", mt);
834
+ let j = I;
835
+ const yt = h(
836
+ {
837
+ name: t.String({ default: "", "x-nrg-form": { icon: "tag" } }),
838
+ connection: t.NodeRef($, {
839
+ "x-nrg-form": { icon: "cloud" }
840
+ }),
841
+ method: t.Union(
842
+ [
843
+ t.Literal("GET"),
844
+ t.Literal("POST"),
845
+ t.Literal("PUT"),
846
+ t.Literal("PATCH"),
847
+ t.Literal("DELETE")
848
+ ],
849
+ { default: "POST", "x-nrg-form": { icon: "random" } }
850
+ ),
851
+ path: t.TypedInput({
852
+ "x-nrg-form": {
853
+ icon: "link",
854
+ typedInputTypes: ["str", "msg"]
855
+ }
856
+ })
857
+ },
858
+ { $id: "salesforce-apex:config" }
859
+ ), bt = h(
860
+ {
861
+ payload: t.Any()
862
+ },
863
+ { $id: "salesforce-apex:input" }
864
+ ), xt = h(
865
+ {
866
+ payload: t.Any()
867
+ },
868
+ { $id: "salesforce-apex:output" }
869
+ ), x = class x extends F {
870
+ async input(o) {
871
+ const n = this.config.connection;
872
+ if (!n) {
873
+ this.error("No Salesforce connection configured", o);
874
+ return;
875
+ }
876
+ try {
877
+ const e = this.config.method;
878
+ this.status({ fill: "green", shape: "dot", text: `${e}...` });
879
+ const s = await n.getConnection(), a = await this.config.path.resolve(o);
880
+ let l;
881
+ const d = e.toLowerCase();
882
+ d === "get" || d === "delete" ? l = await s.apex[d](a) : l = await s.apex[d](a, o.payload), this.status({ fill: "green", shape: "dot", text: `${e} done` }), this.send({ ...o, payload: l });
883
+ } catch (e) {
884
+ this.status({
885
+ fill: "red",
886
+ shape: "dot",
887
+ text: e instanceof Error ? e.message : String(e)
888
+ }), this.error(
889
+ `Apex ${this.config.method} failed: ${e instanceof Error ? e.message : String(e)}`,
890
+ o
891
+ );
892
+ }
893
+ }
894
+ };
895
+ f(x, "SalesforceApex"), i(x, "type", "salesforce-apex"), i(x, "category", "salesforce"), i(x, "color", "#FFFFFF"), i(x, "inputs", 1), i(x, "outputs", 1), i(x, "configSchema", yt), i(x, "inputSchema", bt), i(x, "outputsSchema", xt);
896
+ let v = x;
897
+ const Tt = K({
898
+ nodes: [
899
+ $,
900
+ O,
901
+ R,
902
+ S,
903
+ E,
904
+ j,
905
+ v
906
+ ]
907
+ });
908
+ var U = Tt;
909
+ U && typeof U == "object" && Array.isArray(U.nodes) && (U = Y(U.nodes));
910
+ export {
911
+ U as default
912
+ };
913
+ //# sourceMappingURL=index.mjs.map