@bonsae/node-red-salesforce 0.4.1 → 0.6.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/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
- var z = Object.defineProperty;
2
- var H = (a, o, n) => o in a ? z(a, o, { enumerable: !0, configurable: !0, writable: !0, value: n }) : a[o] = n;
3
- var f = (a, o) => z(a, "name", { value: o, configurable: !0 });
4
- var r = (a, o, n) => H(a, typeof o != "symbol" ? o + "" : o, n);
5
- import { fileURLToPath as q } from "url";
6
- import { dirname as J } from "path";
7
- import { registerTypes as G } from "@bonsae/nrg/server";
8
- import { defineSchema as h, SchemaType as e, ConfigNode as Q, IONode as k, defineModule as Y } from "@bonsae/nrg/server";
9
- import K from "jsforce";
10
- import N from "node:crypto";
11
- var V = q(import.meta.url), Ae = J(V);
12
- const W = h(
1
+ var V = Object.defineProperty;
2
+ var Q = (i, s, t) => s in i ? V(i, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[s] = t;
3
+ var h = (i, s) => V(i, "name", { value: s, configurable: !0 });
4
+ var a = (i, s, t) => Q(i, typeof s != "symbol" ? s + "" : s, t);
5
+ import { fileURLToPath as X } from "url";
6
+ import { dirname as W } from "path";
7
+ import { registerTypes as Z } from "@bonsae/nrg/server";
8
+ import { defineSchema as f, SchemaType as e, ConfigNode as _, IONode as C, defineModule as ee } from "@bonsae/nrg/server";
9
+ import Y from "jsforce";
10
+ import z from "node:crypto";
11
+ var K = X(import.meta.url), Ge = W(K);
12
+ const te = f(
13
13
  {
14
14
  name: e.String({ default: "" }),
15
15
  loginUrl: e.String({
@@ -41,152 +41,152 @@ const W = h(
41
41
  )
42
42
  },
43
43
  { $id: "salesforce-connection:config" }
44
- ), X = h(
44
+ ), ne = f(
45
45
  {
46
46
  accessToken: e.String({ default: "", format: "password" }),
47
47
  refreshToken: e.String({ default: "", format: "password" }),
48
48
  instanceUrl: e.String({ default: "" })
49
49
  },
50
50
  { $id: "salesforce-connection:credentials" }
51
- ), B = 600 * 1e3, U = /* @__PURE__ */ new Map();
52
- function Z() {
53
- return N.randomBytes(32).toString("base64url");
51
+ ), J = 600 * 1e3, U = /* @__PURE__ */ new Map();
52
+ function se() {
53
+ return z.randomBytes(32).toString("base64url");
54
54
  }
55
- f(Z, "generateCodeVerifier");
56
- function D(a) {
57
- return N.createHash("sha256").update(a).digest("base64url");
55
+ h(se, "generateCodeVerifier");
56
+ function oe(i) {
57
+ return z.createHash("sha256").update(i).digest("base64url");
58
58
  }
59
- f(D, "generateCodeChallenge");
60
- function _(a) {
61
- const o = N.randomUUID(), n = Z(), t = D(n);
62
- U.set(o, {
63
- codeVerifier: n,
64
- nodeId: a.nodeId,
65
- clientId: a.clientId,
66
- loginUrl: a.loginUrl,
67
- callbackUrl: a.callbackUrl,
59
+ h(oe, "generateCodeChallenge");
60
+ function re(i) {
61
+ const s = z.randomUUID(), t = se(), n = oe(t);
62
+ U.set(s, {
63
+ codeVerifier: t,
64
+ nodeId: i.nodeId,
65
+ clientId: i.clientId,
66
+ loginUrl: i.loginUrl,
67
+ callbackUrl: i.callbackUrl,
68
68
  timestamp: Date.now()
69
69
  });
70
- for (const [s, i] of U)
71
- Date.now() - i.timestamp > B && U.delete(s);
72
- return { state: o, codeChallenge: t };
70
+ for (const [o, r] of U)
71
+ Date.now() - r.timestamp > J && U.delete(o);
72
+ return { state: s, codeChallenge: n };
73
73
  }
74
- f(_, "createAuthState");
75
- function ee(a) {
76
- const o = U.get(a);
77
- return !o || (U.delete(a), Date.now() - o.timestamp > B) ? null : o;
74
+ h(re, "createAuthState");
75
+ function ae(i) {
76
+ const s = U.get(i);
77
+ return !s || (U.delete(i), Date.now() - s.timestamp > J) ? null : s;
78
78
  }
79
- f(ee, "consumeAuthState");
80
- function te(a) {
81
- return a.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
79
+ h(ae, "consumeAuthState");
80
+ function ie(i) {
81
+ return i.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
82
82
  }
83
- f(te, "escapeHtml");
84
- function A(a, o = !0) {
85
- const n = o ? "<script>setTimeout(function(){window.close()},3000)</script>" : "";
86
- return `<html><body><h2>Authorization Failed</h2><p>${te(a)}</p>${n}</body></html>`;
83
+ h(ie, "escapeHtml");
84
+ function v(i, s = !0) {
85
+ const t = s ? "<script>setTimeout(function(){window.close()},3000)</script>" : "";
86
+ return `<html><body><h2>Authorization Failed</h2><p>${ie(i)}</p>${t}</body></html>`;
87
87
  }
88
- f(A, "errorPage");
89
- function ne(a) {
90
- const o = (a.settings.httpAdminRoot || "").replace(
88
+ h(v, "errorPage");
89
+ function ce(i) {
90
+ const s = (i.settings.httpAdminRoot || "").replace(
91
91
  /\/$/,
92
92
  ""
93
93
  );
94
- a.httpAdmin.post("/salesforce/auth/start", (n, t) => {
94
+ i.httpAdmin.post("/salesforce/auth/start", (t, n) => {
95
95
  try {
96
96
  const {
97
- nodeId: s,
98
- loginUrl: i,
99
- clientId: l,
100
- callbackUrl: d
101
- } = n.body;
102
- if (!s || !i || !l) {
103
- t.status(400).json({ error: "nodeId, loginUrl, and clientId are required" });
97
+ nodeId: o,
98
+ loginUrl: r,
99
+ clientId: c,
100
+ callbackUrl: u
101
+ } = t.body;
102
+ if (!o || !r || !c) {
103
+ n.status(400).json({ error: "nodeId, loginUrl, and clientId are required" });
104
104
  return;
105
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: i,
110
- callbackUrl: c
106
+ const l = u || `${t.protocol}://${t.get("host")}${s}/salesforce/auth/callback`, { state: p, codeChallenge: d } = re({
107
+ nodeId: o,
108
+ clientId: c,
109
+ loginUrl: r,
110
+ callbackUrl: l
111
111
  }), m = new URLSearchParams({
112
112
  response_type: "code",
113
- client_id: l,
114
- redirect_uri: c,
115
- state: g,
116
- code_challenge: u,
113
+ client_id: c,
114
+ redirect_uri: l,
115
+ state: p,
116
+ code_challenge: d,
117
117
  code_challenge_method: "S256"
118
118
  });
119
- t.json({
120
- authorizationUrl: `${i}/services/oauth2/authorize?${m.toString()}`
119
+ n.json({
120
+ authorizationUrl: `${r}/services/oauth2/authorize?${m.toString()}`
121
121
  });
122
- } catch (s) {
123
- a.log.error(
124
- `salesforce-connection: auth/start error: ${s instanceof Error ? s.message : String(s)}`
125
- ), t.status(500).json({ error: "Failed to start authorization" });
122
+ } catch (o) {
123
+ i.log.error(
124
+ `salesforce-connection: auth/start error: ${o instanceof Error ? o.message : String(o)}`
125
+ ), n.status(500).json({ error: "Failed to start authorization" });
126
126
  }
127
- }), a.httpAdmin.get("/salesforce/auth/callback", async (n, t) => {
127
+ }), i.httpAdmin.get("/salesforce/auth/callback", async (t, n) => {
128
128
  try {
129
- const { code: s, state: i, error: l, error_description: d } = n.query;
130
- if (l) {
131
- a.log.error(
132
- `salesforce-connection: OAuth error: ${l} - ${d}`
133
- ), t.status(400).send(A(String(d || l)));
129
+ const { code: o, state: r, error: c, error_description: u } = t.query;
130
+ if (c) {
131
+ i.log.error(
132
+ `salesforce-connection: OAuth error: ${c} - ${u}`
133
+ ), n.status(400).send(v(String(u || c)));
134
134
  return;
135
135
  }
136
- if (!s || !i) {
137
- t.status(400).send(A("Missing code or state parameter"));
136
+ if (!o || !r) {
137
+ n.status(400).send(v("Missing code or state parameter"));
138
138
  return;
139
139
  }
140
- const c = ee(i);
141
- if (!c) {
142
- t.status(400).send(
143
- A(
140
+ const l = ae(r);
141
+ if (!l) {
142
+ n.status(400).send(
143
+ v(
144
144
  "Invalid or expired authorization state. Please try again."
145
145
  )
146
146
  );
147
147
  return;
148
148
  }
149
- const g = await fetch(
150
- `${c.loginUrl}/services/oauth2/token`,
149
+ const p = await fetch(
150
+ `${l.loginUrl}/services/oauth2/token`,
151
151
  {
152
152
  method: "POST",
153
153
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
154
154
  body: new URLSearchParams({
155
155
  grant_type: "authorization_code",
156
- code: s,
157
- client_id: c.clientId,
158
- redirect_uri: c.callbackUrl,
159
- code_verifier: c.codeVerifier
156
+ code: o,
157
+ client_id: l.clientId,
158
+ redirect_uri: l.callbackUrl,
159
+ code_verifier: l.codeVerifier
160
160
  })
161
161
  }
162
162
  );
163
- if (!g.ok) {
164
- const p = await g.text();
165
- a.log.error(
166
- `salesforce-connection: Token exchange failed: ${p}`
167
- ), t.status(500).send(
168
- A(
163
+ if (!p.ok) {
164
+ const g = await p.text();
165
+ i.log.error(
166
+ `salesforce-connection: Token exchange failed: ${g}`
167
+ ), n.status(500).send(
168
+ v(
169
169
  "Token exchange failed. Check the Node-RED logs for details."
170
170
  )
171
171
  );
172
172
  return;
173
173
  }
174
- const u = await g.json();
175
- a.nodes.addCredentials(c.nodeId, {
176
- accessToken: u.access_token,
177
- refreshToken: u.refresh_token,
178
- instanceUrl: u.instance_url
179
- }), a.log.info(
180
- `salesforce-connection: Successfully authorized node ${c.nodeId} for ${u.instance_url}`
174
+ const d = await p.json();
175
+ i.nodes.addCredentials(l.nodeId, {
176
+ accessToken: d.access_token,
177
+ refreshToken: d.refresh_token,
178
+ instanceUrl: d.instance_url
179
+ }), i.log.info(
180
+ `salesforce-connection: Successfully authorized node ${l.nodeId} for ${d.instance_url}`
181
181
  );
182
182
  const m = JSON.stringify({
183
183
  type: "salesforce-auth-success",
184
- nodeId: c.nodeId,
185
- accessToken: u.access_token,
186
- refreshToken: u.refresh_token,
187
- instanceUrl: u.instance_url
184
+ nodeId: l.nodeId,
185
+ accessToken: d.access_token,
186
+ refreshToken: d.refresh_token,
187
+ instanceUrl: d.instance_url
188
188
  });
189
- t.send(`<!DOCTYPE html>
189
+ n.send(`<!DOCTYPE html>
190
190
  <html>
191
191
  <body>
192
192
  <h2>Authorization Successful</h2>
@@ -199,77 +199,318 @@ function ne(a) {
199
199
  </script>
200
200
  </body>
201
201
  </html>`);
202
- } catch (s) {
203
- a.log.error(
204
- `salesforce-connection: auth/callback error: ${s instanceof Error ? s.message : String(s)}`
205
- ), t.status(500).send(A("An unexpected error occurred."));
202
+ } catch (o) {
203
+ i.log.error(
204
+ `salesforce-connection: auth/callback error: ${o instanceof Error ? o.message : String(o)}`
205
+ ), n.status(500).send(v("An unexpected error occurred."));
206
206
  }
207
- }), a.httpAdmin.get("/salesforce/auth/status/:nodeId", (n, t) => {
207
+ }), i.httpAdmin.get("/salesforce/auth/status/:nodeId", (t, n) => {
208
208
  try {
209
- const s = a.nodes.getCredentials(n.params.nodeId), i = !!(s != null && s.accessToken && (s != null && s.instanceUrl));
210
- t.json({
211
- authenticated: i,
212
- instanceUrl: i ? s.instanceUrl : void 0
209
+ const o = i.nodes.getCredentials(t.params.nodeId), r = !!(o != null && o.accessToken && (o != null && o.instanceUrl));
210
+ n.json({
211
+ authenticated: r,
212
+ instanceUrl: r ? o.instanceUrl : void 0
213
213
  });
214
214
  } catch {
215
- t.json({ authenticated: !1 });
215
+ n.json({ authenticated: !1 });
216
216
  }
217
217
  });
218
218
  }
219
- f(ne, "initAuthRoutes");
220
- function oe(a) {
221
- ne(a);
219
+ h(ce, "initAuthRoutes");
220
+ function P(i, s) {
221
+ const t = i.nodes.getCredentials(s);
222
+ if (!(t != null && t.accessToken) || !(t != null && t.instanceUrl))
223
+ throw new Error("Connection not authenticated");
224
+ return new Y.Connection({
225
+ instanceUrl: t.instanceUrl,
226
+ accessToken: t.accessToken
227
+ });
228
+ }
229
+ h(P, "getConnection");
230
+ const T = class T {
231
+ constructor(s) {
232
+ a(this, "conn");
233
+ this.conn = s;
234
+ }
235
+ // --- Apex REST ---
236
+ async invoke(s, t) {
237
+ const n = this.conn.version || "62.0", r = (await this.conn.request({
238
+ method: "POST",
239
+ url: `/services/data/v${n}/actions/custom/apex/${s}`,
240
+ body: JSON.stringify({
241
+ inputs: [{ payload: JSON.stringify(t) }]
242
+ }),
243
+ headers: { "Content-Type": "application/json" }
244
+ }))[0];
245
+ if (!r.isSuccess) {
246
+ const c = r.errors.map((u) => u.message).join("; ");
247
+ throw new Error(`Invocable action failed: ${c}`);
248
+ }
249
+ return r;
250
+ }
251
+ async post(s, t) {
252
+ return await this.conn.apex.post(
253
+ s,
254
+ t
255
+ );
256
+ }
257
+ async get(s) {
258
+ return await this.conn.apex.get(s);
259
+ }
260
+ async put(s, t) {
261
+ return await this.conn.apex.put(
262
+ s,
263
+ t
264
+ );
265
+ }
266
+ async patch(s, t) {
267
+ return await this.conn.apex.patch(
268
+ s,
269
+ t
270
+ );
271
+ }
272
+ async delete(s) {
273
+ return await this.conn.apex.delete(s);
274
+ }
275
+ // --- Tooling API ---
276
+ async queryApexClassesByName(s) {
277
+ const t = s.map((r) => `'${r}'`).join(","), n = await this.conn.tooling.query(
278
+ `SELECT Id, Name, Body FROM ApexClass WHERE Name IN (${t})`
279
+ ), o = /* @__PURE__ */ new Map();
280
+ for (const r of n.records)
281
+ o.set(r.Name, {
282
+ Id: r.Id,
283
+ Name: r.Name,
284
+ Body: r.Body
285
+ });
286
+ return o;
287
+ }
288
+ async createApexClass(s, t) {
289
+ return this.withRetry(async () => {
290
+ var o;
291
+ const n = await this.conn.tooling.create("ApexClass", {
292
+ Name: s,
293
+ Body: t
294
+ });
295
+ if (!n.success) {
296
+ const r = (o = n.errors) == null ? void 0 : o.map((c) => c.message).join("; ");
297
+ throw new Error(`Apex create failed: ${r}`);
298
+ }
299
+ return { id: n.id };
300
+ }, `create ${s}`);
301
+ }
302
+ async deleteApexClass(s) {
303
+ await this.withRetry(
304
+ () => this.conn.tooling.destroy("ApexClass", s),
305
+ `delete ${s}`
306
+ );
307
+ }
308
+ async queryApexRestAndInvocableClasses() {
309
+ var o, r;
310
+ const s = await this.conn.tooling.query(
311
+ "SELECT Name, Body FROM ApexClass ORDER BY Name"
312
+ ), t = [], n = [];
313
+ for (const c of s.records) {
314
+ if ((o = c.Body) != null && o.includes("@RestResource")) {
315
+ const u = c.Body.match(
316
+ /@RestResource\s*\(\s*urlMapping\s*=\s*'([^']+)'/
317
+ );
318
+ t.push({ name: c.Name, urlMapping: u ? u[1] : void 0 });
319
+ }
320
+ (r = c.Body) != null && r.includes("@InvocableMethod") && n.push({ name: c.Name });
321
+ }
322
+ return { rest: t, invocable: n };
323
+ }
324
+ // --- Streaming ---
325
+ async queryStreamingChannels() {
326
+ const s = await this.conn.describeGlobal(), t = [];
327
+ for (const n of s.sobjects)
328
+ n.name.endsWith("__e") ? t.push({
329
+ value: `/event/${n.name}`,
330
+ label: `${n.label} (${n.name})`,
331
+ group: "Platform Events"
332
+ }) : n.name.endsWith("ChangeEvent") && t.push({
333
+ value: `/data/${n.name}`,
334
+ label: `${n.label} (${n.name})`,
335
+ group: "Change Data Capture"
336
+ });
337
+ return t.push({
338
+ value: "/data/ChangeEvents",
339
+ label: "All Change Events",
340
+ group: "Change Data Capture"
341
+ }), t;
342
+ }
343
+ // --- Retry ---
344
+ async withRetry(s, t) {
345
+ for (let n = 1; n <= T.MAX_RETRIES; n++)
346
+ try {
347
+ return await s();
348
+ } catch (o) {
349
+ if (n === T.MAX_RETRIES) throw o;
350
+ const r = T.RETRY_DELAY_MS * n;
351
+ console.warn(
352
+ `[SalesforceClient] ${t} failed (attempt ${n}/${T.MAX_RETRIES}), retrying in ${r}ms...`
353
+ ), await new Promise((c) => setTimeout(c, r));
354
+ }
355
+ throw new Error("unreachable");
356
+ }
357
+ };
358
+ h(T, "SalesforceClient"), a(T, "MAX_RETRIES", 3), a(T, "RETRY_DELAY_MS", 1e3);
359
+ let R = T;
360
+ function le(i) {
361
+ switch (i) {
362
+ case "boolean":
363
+ return "Boolean";
364
+ case "int":
365
+ return "Integer";
366
+ case "long":
367
+ return "Long";
368
+ case "double":
369
+ return "Double";
370
+ case "currency":
371
+ case "percent":
372
+ return "Decimal";
373
+ case "date":
374
+ return "Date";
375
+ case "datetime":
376
+ return "Datetime";
377
+ case "time":
378
+ return "Time";
379
+ case "id":
380
+ return "Id";
381
+ case "reference":
382
+ return "Id";
383
+ case "base64":
384
+ return "Blob";
385
+ case "location":
386
+ return "Location";
387
+ case "address":
388
+ return "Address";
389
+ default:
390
+ return "String";
391
+ }
392
+ }
393
+ h(le, "sfTypeToApex");
394
+ function ue(i) {
395
+ const s = [`global class ${i.name} {`];
396
+ for (const t of i.fields) {
397
+ const n = le(t.type);
398
+ s.push(` global ${n} ${t.name};`);
399
+ }
400
+ return s.push("}"), s.join(`
401
+ `);
402
+ }
403
+ h(ue, "buildFauxClass");
404
+ function de(i) {
405
+ i.httpAdmin.get(
406
+ "/salesforce/list-apex-classes/:nodeId",
407
+ async (s, t) => {
408
+ try {
409
+ const n = P(i, s.params.nodeId), o = new R(n);
410
+ t.json(await o.queryApexRestAndInvocableClasses());
411
+ } catch (n) {
412
+ const o = n instanceof Error ? n.message : String(n);
413
+ t.status(500).json({ error: o });
414
+ }
415
+ }
416
+ ), i.httpAdmin.get(
417
+ "/salesforce/describe-sobjects/:nodeId",
418
+ async (s, t) => {
419
+ try {
420
+ const n = P(i, s.params.nodeId), o = s.params.nodeId, r = G.get(o);
421
+ if (r && Date.now() - r.timestamp < pe) {
422
+ t.json({ sobjects: r.data });
423
+ return;
424
+ }
425
+ const u = (await n.describeGlobal()).sobjects.filter((d) => d.queryable).map((d) => d.name), l = 25, p = {};
426
+ for (let d = 0; d < u.length; d += l) {
427
+ const m = u.slice(d, d + l), g = await Promise.all(
428
+ m.map((x) => n.describe(x).catch(() => null))
429
+ );
430
+ for (const x of g)
431
+ x && (p[x.name] = ue(x));
432
+ }
433
+ G.set(o, {
434
+ data: p,
435
+ timestamp: Date.now()
436
+ }), t.json({ sobjects: p });
437
+ } catch (n) {
438
+ const o = n instanceof Error ? n.message : String(n);
439
+ t.status(500).json({ error: o });
440
+ }
441
+ }
442
+ );
443
+ }
444
+ h(de, "initApexRoutes");
445
+ const pe = 1800 * 1e3, G = /* @__PURE__ */ new Map();
446
+ function he(i) {
447
+ i.httpAdmin.get(
448
+ "/salesforce/list-streaming-channels/:nodeId",
449
+ async (s, t) => {
450
+ try {
451
+ const n = P(i, s.params.nodeId), o = new R(n);
452
+ t.json(await o.queryStreamingChannels());
453
+ } catch (n) {
454
+ const o = n instanceof Error ? n.message : String(n);
455
+ t.status(500).json({ error: o });
456
+ }
457
+ }
458
+ );
459
+ }
460
+ h(he, "initStreamingRoutes");
461
+ function fe(i) {
462
+ ce(i), de(i), he(i);
222
463
  }
223
- f(oe, "initRoutes");
224
- const L = class L extends Q {
464
+ h(fe, "initRoutes");
465
+ const F = class F extends _ {
225
466
  constructor() {
226
467
  super(...arguments);
227
- r(this, "conn", null);
468
+ a(this, "conn", null);
228
469
  }
229
- static async registered(n) {
230
- oe(n);
470
+ static async registered(t) {
471
+ fe(t);
231
472
  }
232
473
  async getConnection() {
233
474
  if (this.conn) return this.conn;
234
- const n = this.credentials;
235
- if (!(n != null && n.accessToken) || !(n != null && n.instanceUrl))
475
+ const t = this.credentials;
476
+ if (!(t != null && t.accessToken) || !(t != null && t.instanceUrl))
236
477
  throw new Error(
237
478
  "Salesforce connection not authorized. Please authorize in the node configuration."
238
479
  );
239
- return this.conn = new K.Connection({
480
+ return this.conn = new Y.Connection({
240
481
  oauth2: {
241
482
  clientId: this.config.clientId,
242
483
  loginUrl: this.config.loginUrl
243
484
  },
244
- instanceUrl: n.instanceUrl,
245
- accessToken: n.accessToken,
246
- refreshToken: n.refreshToken,
485
+ instanceUrl: t.instanceUrl,
486
+ accessToken: t.accessToken,
487
+ refreshToken: t.refreshToken,
247
488
  version: this.config.apiVersion
248
- }), this.conn.on("refresh", (t) => {
489
+ }), this.conn.on("refresh", (n) => {
249
490
  this.RED.nodes.addCredentials(this.id, {
250
491
  ...this.credentials,
251
- accessToken: t
492
+ accessToken: n
252
493
  });
253
494
  }), this.conn;
254
495
  }
255
496
  getAccessToken() {
256
- var n;
257
- return (n = this.credentials) == null ? void 0 : n.accessToken;
497
+ var t;
498
+ return (t = this.credentials) == null ? void 0 : t.accessToken;
258
499
  }
259
500
  getInstanceUrl() {
260
- var n;
261
- return (n = this.credentials) == null ? void 0 : n.instanceUrl;
501
+ var t;
502
+ return (t = this.credentials) == null ? void 0 : t.instanceUrl;
262
503
  }
263
504
  async closed() {
264
505
  this.conn = null;
265
506
  }
266
507
  };
267
- f(L, "SalesforceConnection"), r(L, "type", "salesforce-connection"), r(L, "configSchema", W), r(L, "credentialsSchema", X);
268
- let $ = L;
269
- const re = h(
508
+ h(F, "SalesforceConnection"), a(F, "type", "salesforce-connection"), a(F, "configSchema", te), a(F, "credentialsSchema", ne);
509
+ let w = F;
510
+ const ge = f(
270
511
  {
271
512
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
272
- connection: e.NodeRef($, {
513
+ connection: e.NodeRef(w, {
273
514
  "x-nrg-form": { icon: "cloud" }
274
515
  }),
275
516
  query: e.TypedInput({
@@ -283,56 +524,56 @@ const re = h(
283
524
  statusPort: e.Boolean({ default: !1 })
284
525
  },
285
526
  { $id: "salesforce-soql:config" }
286
- ), se = h(
527
+ ), me = f(
287
528
  {
288
529
  payload: e.Any()
289
530
  },
290
531
  { $id: "salesforce-soql:input" }
291
- ), ie = h(
532
+ ), ye = f(
292
533
  {
293
534
  payload: e.Array(e.Any()),
294
535
  totalSize: e.Number(),
295
536
  done: e.Boolean()
296
537
  },
297
538
  { $id: "salesforce-soql:output" }
298
- ), y = class y extends k {
299
- async input(o) {
300
- const n = this.config.connection;
301
- if (!n) {
302
- this.error("No Salesforce connection configured", o);
539
+ ), $ = class $ extends C {
540
+ async input(s) {
541
+ const t = this.config.connection;
542
+ if (!t) {
543
+ this.error("No Salesforce connection configured", s);
303
544
  return;
304
545
  }
305
546
  try {
306
547
  this.status({ fill: "green", shape: "dot", text: "querying..." });
307
- const t = await n.getConnection(), s = await this.config.query.resolve(o), i = await t.query(s);
548
+ const n = await t.getConnection(), o = await this.config.query.resolve(s), r = await n.query(o);
308
549
  this.status({
309
550
  fill: "green",
310
551
  shape: "dot",
311
- text: `${i.totalSize} records`
552
+ text: `${r.totalSize} records`
312
553
  }), this.send({
313
- ...o,
314
- payload: i.records,
315
- totalSize: i.totalSize,
316
- done: i.done
554
+ ...s,
555
+ payload: r.records,
556
+ totalSize: r.totalSize,
557
+ done: r.done
317
558
  });
318
- } catch (t) {
559
+ } catch (n) {
319
560
  this.status({
320
561
  fill: "red",
321
562
  shape: "dot",
322
- text: t instanceof Error ? t.message : String(t)
563
+ text: n instanceof Error ? n.message : String(n)
323
564
  }), this.error(
324
- `SOQL query failed: ${t instanceof Error ? t.message : String(t)}`,
325
- o
565
+ `SOQL query failed: ${n instanceof Error ? n.message : String(n)}`,
566
+ s
326
567
  );
327
568
  }
328
569
  }
329
570
  };
330
- f(y, "SalesforceSoql"), r(y, "type", "salesforce-soql"), r(y, "category", "salesforce"), r(y, "color", "#FFFFFF"), r(y, "configSchema", re), r(y, "inputSchema", se), r(y, "outputsSchema", ie);
331
- let E = y;
332
- const ae = h(
571
+ h($, "SalesforceSoql"), a($, "type", "salesforce-soql"), a($, "category", "salesforce"), a($, "color", "#FFFFFF"), a($, "configSchema", ge), a($, "inputSchema", me), a($, "outputsSchema", ye);
572
+ let k = $;
573
+ const xe = f(
333
574
  {
334
575
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
335
- connection: e.NodeRef($, {
576
+ connection: e.NodeRef(w, {
336
577
  "x-nrg-form": { icon: "cloud" }
337
578
  }),
338
579
  operation: e.Union(
@@ -381,66 +622,66 @@ const ae = h(
381
622
  }
382
623
  }
383
624
  }
384
- ), ce = h(
625
+ ), be = f(
385
626
  {
386
627
  payload: e.Any()
387
628
  },
388
629
  { $id: "salesforce-dml:input" }
389
- ), le = h(
630
+ ), we = f(
390
631
  {
391
632
  payload: e.Any()
392
633
  },
393
634
  { $id: "salesforce-dml:output" }
394
- ), x = class x extends k {
395
- async input(o) {
396
- const n = this.config.connection;
397
- if (!n) {
398
- this.error("No Salesforce connection configured", o);
635
+ ), I = class I extends C {
636
+ async input(s) {
637
+ const t = this.config.connection;
638
+ if (!t) {
639
+ this.error("No Salesforce connection configured", s);
399
640
  return;
400
641
  }
401
642
  try {
402
- const t = this.config.operation;
403
- this.status({ fill: "green", shape: "dot", text: `${t}...` });
404
- const s = await n.getConnection(), i = await this.config.sObjectType.resolve(o), l = s.sobject(i), d = await this.config.record.resolve(o) ?? o.payload;
405
- let c;
406
- switch (t) {
643
+ const n = this.config.operation;
644
+ this.status({ fill: "green", shape: "dot", text: `${n}...` });
645
+ const o = await t.getConnection(), r = await this.config.sObjectType.resolve(s), c = o.sobject(r), u = await this.config.record.resolve(s) ?? s.payload;
646
+ let l;
647
+ switch (n) {
407
648
  case "create":
408
- c = await l.create(d);
649
+ l = await c.create(u);
409
650
  break;
410
651
  case "read":
411
- c = await l.retrieve(d);
652
+ l = await c.retrieve(u);
412
653
  break;
413
654
  case "update":
414
- c = await l.update(d);
655
+ l = await c.update(u);
415
656
  break;
416
657
  case "delete":
417
- c = await l.destroy(d);
658
+ l = await c.destroy(u);
418
659
  break;
419
660
  case "upsert":
420
- c = await l.upsert(d, this.config.externalIdField);
661
+ l = await c.upsert(u, this.config.externalIdField);
421
662
  break;
422
663
  default:
423
- throw new Error(`Unknown operation: ${t}`);
664
+ throw new Error(`Unknown operation: ${n}`);
424
665
  }
425
- this.status({ fill: "green", shape: "dot", text: `${t} done` }), this.send({ ...o, payload: c });
426
- } catch (t) {
666
+ this.status({ fill: "green", shape: "dot", text: `${n} done` }), this.send({ ...s, payload: l });
667
+ } catch (n) {
427
668
  this.status({
428
669
  fill: "red",
429
670
  shape: "dot",
430
- text: t instanceof Error ? t.message : String(t)
671
+ text: n instanceof Error ? n.message : String(n)
431
672
  }), this.error(
432
- `DML ${this.config.operation} failed: ${t instanceof Error ? t.message : String(t)}`,
433
- o
673
+ `DML ${this.config.operation} failed: ${n instanceof Error ? n.message : String(n)}`,
674
+ s
434
675
  );
435
676
  }
436
677
  }
437
678
  };
438
- f(x, "SalesforceDml"), r(x, "type", "salesforce-dml"), r(x, "category", "salesforce"), r(x, "color", "#FFFFFF"), r(x, "configSchema", ae), r(x, "inputSchema", ce), r(x, "outputsSchema", le);
439
- let C = x;
440
- const de = h(
679
+ h(I, "SalesforceDml"), a(I, "type", "salesforce-dml"), a(I, "category", "salesforce"), a(I, "color", "#FFFFFF"), a(I, "configSchema", xe), a(I, "inputSchema", be), a(I, "outputsSchema", we);
680
+ let j = I;
681
+ const Te = f(
441
682
  {
442
683
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
443
- connection: e.NodeRef($, {
684
+ connection: e.NodeRef(w, {
444
685
  "x-nrg-form": { icon: "cloud" }
445
686
  }),
446
687
  operation: e.Union(
@@ -449,6 +690,7 @@ const de = h(
449
690
  e.Literal("update"),
450
691
  e.Literal("upsert"),
451
692
  e.Literal("delete"),
693
+ e.Literal("hardDelete"),
452
694
  e.Literal("query")
453
695
  ],
454
696
  { default: "insert", "x-nrg-form": { icon: "database" } }
@@ -459,6 +701,12 @@ const de = h(
459
701
  typedInputTypes: ["str", "msg"]
460
702
  }
461
703
  }),
704
+ query: e.TypedInput({
705
+ "x-nrg-form": {
706
+ icon: "search",
707
+ typedInputTypes: ["str", "msg", "jsonata"]
708
+ }
709
+ }),
462
710
  externalIdField: e.Optional(
463
711
  e.String({
464
712
  default: "",
@@ -497,7 +745,7 @@ const de = h(
497
745
  "x-nrg-form": { icon: "hourglass" }
498
746
  }),
499
747
  errorPort: e.Boolean({ default: !1 }),
500
- completePort: e.Boolean({ default: !0 }),
748
+ completePort: e.Boolean({ default: !1 }),
501
749
  statusPort: e.Boolean({ default: !1 })
502
750
  },
503
751
  {
@@ -514,119 +762,99 @@ const de = h(
514
762
  }
515
763
  }
516
764
  }
517
- ), ue = h(
765
+ ), $e = f(
518
766
  {
519
- payload: e.Any()
767
+ payload: e.Any({
768
+ description: "Records array, CSV string, readable stream (ingest) or SOQL string (query)"
769
+ })
520
770
  },
521
771
  { $id: "salesforce-bulk:input" }
522
- );
523
- h(
772
+ ), Ie = f(
524
773
  {
525
- payload: e.Array(e.Any())
774
+ payload: e.Any({
775
+ description: "Query: individual record. Ingest: { successfulResults, failedResults, unprocessedRecords }"
776
+ })
526
777
  },
527
778
  { $id: "salesforce-bulk:output" }
528
- );
529
- const he = h(
530
- {},
531
- { $id: "salesforce-bulk:record-output" }
532
- ), pe = h(
533
- {},
534
- { $id: "salesforce-bulk:job-created-output" }
535
- ), fe = {
536
- record: he,
537
- jobCreated: pe
538
- }, b = class b extends k {
539
- sendRecord(o, n) {
540
- this.sendToPort("record", { ...o, payload: n });
541
- }
542
- sendJobCreated(o, n) {
543
- this.sendToPort("jobCreated", { ...o, payload: n });
544
- }
545
- async input(o) {
546
- const n = this.config.connection;
547
- if (!n) {
548
- this.error("No Salesforce connection configured", o);
549
- return;
550
- }
779
+ ), S = class S extends C {
780
+ async input(s) {
551
781
  try {
552
- const t = this.config.operation;
553
- this.status({
554
- fill: "green",
555
- shape: "dot",
556
- text: `bulk ${t}...`
557
- });
558
- const s = await n.getConnection(), i = await this.config.sObjectType.resolve(o);
559
- let l = 0;
560
- if (t === "query") {
561
- const d = await s.bulk2.query(o.payload, {
562
- pollTimeout: this.config.pollTimeout,
563
- pollInterval: this.config.pollInterval,
564
- columnDelimiter: this.config.columnDelimiter,
565
- lineEnding: this.config.lineEnding
566
- });
567
- await new Promise((c, g) => {
568
- d.on("data", (u) => {
569
- l++, this.sendRecord(o, u);
570
- }), d.on("end", () => c()), d.on("error", g);
571
- }), this.status({
782
+ const t = this.config.connection;
783
+ if (!t)
784
+ throw new Error("No Salesforce connection configured");
785
+ const n = await t.getConnection(), o = this.config.operation;
786
+ o === "query" ? await this.executeQuery(n, s) : await this.executeIngest(n, s, o);
787
+ } catch (t) {
788
+ const n = t instanceof Error ? t.message : String(t);
789
+ throw this.status({ fill: "red", shape: "dot", text: n }), t;
790
+ }
791
+ }
792
+ async executeQuery(s, t) {
793
+ this.status({ fill: "green", shape: "dot", text: "query starting..." });
794
+ const n = await this.config.query.resolve(t), o = await s.bulk2.query(n, {
795
+ pollTimeout: this.config.pollTimeout,
796
+ pollInterval: this.config.pollInterval,
797
+ columnDelimiter: this.config.columnDelimiter,
798
+ lineEnding: this.config.lineEnding
799
+ });
800
+ let r = 0;
801
+ await new Promise((c, u) => {
802
+ o.on("data", (l) => {
803
+ r++, this.send({ ...t, payload: l }), r % 1e3 === 0 && this.status({
572
804
  fill: "green",
573
805
  shape: "dot",
574
- text: `bulk ${t}: ${l} records`
575
- }), this.sendToPort("complete", {
576
- ...o,
577
- payload: { operation: t, sObjectType: i, totalRecords: l }
578
- });
579
- } else {
580
- const d = o.payload, c = s.bulk2.createJob({
581
- operation: t,
582
- object: i,
583
- columnDelimiter: this.config.columnDelimiter,
584
- lineEnding: this.config.lineEnding,
585
- ...t === "upsert" && this.config.externalIdField ? { externalIdFieldName: this.config.externalIdField } : {},
586
- ...this.config.assignmentRuleId ? { assignmentRuleId: this.config.assignmentRuleId } : {}
587
- });
588
- await c.open(), this.sendJobCreated(o, {
589
- jobId: c.id,
590
- operation: t,
591
- sObjectType: i,
592
- state: "Open"
593
- }), await c.uploadData(d), await c.close(), await c.poll(this.config.pollInterval, this.config.pollTimeout);
594
- const g = await c.getAllResults(), u = g.successfulResults ?? [], m = g.failedResults ?? [], p = g.unprocessedRecords ?? [];
595
- l = u.length + m.length + p.length;
596
- for (const R of u)
597
- this.sendRecord(o, R);
598
- for (const R of m)
599
- this.sendRecord(o, R);
600
- const S = u.length, M = m.length;
601
- this.status({
602
- fill: M > 0 ? "red" : "green",
603
- shape: "dot",
604
- text: `bulk ${t}: ${l} records`
605
- }), this.sendToPort("complete", {
606
- ...o,
607
- payload: {
608
- jobId: c.id,
609
- operation: t,
610
- sObjectType: i,
611
- totalRecords: l,
612
- successCount: S,
613
- failureCount: M,
614
- unprocessedCount: p.length
615
- }
806
+ text: `query: ${r} records...`
616
807
  });
617
- }
618
- } catch (t) {
619
- const s = t instanceof Error ? t.message : String(t);
620
- this.status({ fill: "red", shape: "dot", text: s }), this.error(`Bulk ${this.config.operation} failed: ${s}`, o);
621
- }
808
+ }), o.on("end", () => c()), o.on("error", u);
809
+ }), this.status({
810
+ fill: "green",
811
+ shape: "dot",
812
+ text: `query complete: ${r} records`
813
+ });
814
+ }
815
+ async executeIngest(s, t, n) {
816
+ var d, m, g;
817
+ const o = await this.config.sObjectType.resolve(t);
818
+ this.status({
819
+ fill: "green",
820
+ shape: "dot",
821
+ text: `creating ${n} job...`
822
+ });
823
+ const r = s.bulk2.createJob({
824
+ operation: n,
825
+ object: o,
826
+ columnDelimiter: this.config.columnDelimiter,
827
+ lineEnding: this.config.lineEnding,
828
+ ...n === "upsert" && this.config.externalIdField ? { externalIdFieldName: this.config.externalIdField } : {},
829
+ ...this.config.assignmentRuleId ? { assignmentRuleId: this.config.assignmentRuleId } : {}
830
+ });
831
+ await r.open(), this.status({
832
+ fill: "green",
833
+ shape: "dot",
834
+ text: "uploading data..."
835
+ }), await r.uploadData(t.payload), this.status({
836
+ fill: "green",
837
+ shape: "dot",
838
+ text: "processing..."
839
+ }), await r.close(), await r.poll(this.config.pollInterval, this.config.pollTimeout), this.status({
840
+ fill: "green",
841
+ shape: "dot",
842
+ text: "retrieving results..."
843
+ });
844
+ const c = await r.getAllResults(), u = ((d = c.successfulResults) == null ? void 0 : d.length) ?? 0, l = ((m = c.failedResults) == null ? void 0 : m.length) ?? 0, p = u + l + (((g = c.unprocessedRecords) == null ? void 0 : g.length) ?? 0);
845
+ this.send({ ...t, payload: c }), this.status({
846
+ fill: l > 0 ? "red" : "green",
847
+ shape: "dot",
848
+ text: `${n} complete: ${u} ok, ${l} failed, ${p} total`
849
+ });
622
850
  }
623
851
  };
624
- f(b, "SalesforceBulk"), r(b, "type", "salesforce-bulk"), r(b, "category", "salesforce"), r(b, "color", "#FFFFFF"), r(b, "configSchema", de), r(b, "inputSchema", ue), r(b, "outputsSchema", fe);
625
- let O = b;
626
- const ge = h(
852
+ h(S, "SalesforceBulk"), a(S, "type", "salesforce-bulk"), a(S, "category", "salesforce"), a(S, "color", "#FFFFFF"), a(S, "configSchema", Te), a(S, "inputSchema", $e), a(S, "outputsSchema", Ie);
853
+ let M = S;
854
+ const Se = f(
627
855
  {
628
856
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
629
- connection: e.NodeRef($, {
857
+ connection: e.NodeRef(w, {
630
858
  "x-nrg-form": { icon: "cloud" }
631
859
  }),
632
860
  sObjectType: e.TypedInput({
@@ -640,12 +868,12 @@ const ge = h(
640
868
  statusPort: e.Boolean({ default: !1 })
641
869
  },
642
870
  { $id: "salesforce-describe:config" }
643
- ), me = h(
871
+ ), Ee = f(
644
872
  {
645
873
  payload: e.Any()
646
874
  },
647
875
  { $id: "salesforce-describe:input" }
648
- ), ye = h(
876
+ ), Le = f(
649
877
  {
650
878
  payload: e.Object({
651
879
  name: e.String(),
@@ -655,47 +883,47 @@ const ge = h(
655
883
  })
656
884
  },
657
885
  { $id: "salesforce-describe:output" }
658
- ), T = class T extends k {
659
- async input(o) {
660
- const n = this.config.connection;
661
- if (!n) {
662
- this.error("No Salesforce connection configured", o);
886
+ ), E = class E extends C {
887
+ async input(s) {
888
+ const t = this.config.connection;
889
+ if (!t) {
890
+ this.error("No Salesforce connection configured", s);
663
891
  return;
664
892
  }
665
893
  try {
666
894
  this.status({ fill: "green", shape: "dot", text: "describing..." });
667
- const t = await n.getConnection(), s = await this.config.sObjectType.resolve(o), i = await t.sobject(s).describe();
895
+ const n = await t.getConnection(), o = await this.config.sObjectType.resolve(s), r = await n.sobject(o).describe();
668
896
  this.status({
669
897
  fill: "green",
670
898
  shape: "dot",
671
- text: `${i.name}: ${i.fields.length} fields`
899
+ text: `${r.name}: ${r.fields.length} fields`
672
900
  }), this.send({
673
- ...o,
901
+ ...s,
674
902
  payload: {
675
- name: i.name,
676
- fields: i.fields,
677
- childRelationships: i.childRelationships,
678
- recordTypeInfos: i.recordTypeInfos
903
+ name: r.name,
904
+ fields: r.fields,
905
+ childRelationships: r.childRelationships,
906
+ recordTypeInfos: r.recordTypeInfos
679
907
  }
680
908
  });
681
- } catch (t) {
909
+ } catch (n) {
682
910
  this.status({
683
911
  fill: "red",
684
912
  shape: "dot",
685
- text: t instanceof Error ? t.message : String(t)
913
+ text: n instanceof Error ? n.message : String(n)
686
914
  }), this.error(
687
- `Describe failed: ${t instanceof Error ? t.message : String(t)}`,
688
- o
915
+ `Describe failed: ${n instanceof Error ? n.message : String(n)}`,
916
+ s
689
917
  );
690
918
  }
691
919
  }
692
920
  };
693
- f(T, "SalesforceDescribe"), r(T, "type", "salesforce-describe"), r(T, "category", "salesforce"), r(T, "color", "#FFFFFF"), r(T, "configSchema", ge), r(T, "inputSchema", me), r(T, "outputsSchema", ye);
694
- let P = T;
695
- const xe = h(
921
+ h(E, "SalesforceDescribe"), a(E, "type", "salesforce-describe"), a(E, "category", "salesforce"), a(E, "color", "#FFFFFF"), a(E, "configSchema", Se), a(E, "inputSchema", Ee), a(E, "outputsSchema", Le);
922
+ let B = E;
923
+ const Ae = f(
696
924
  {
697
925
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
698
- connection: e.NodeRef($, {
926
+ connection: e.NodeRef(w, {
699
927
  "x-nrg-form": { icon: "cloud" }
700
928
  }),
701
929
  channelName: e.String({
@@ -740,7 +968,7 @@ const xe = h(
740
968
  }
741
969
  }
742
970
  }
743
- ), be = h(
971
+ ), Re = f(
744
972
  {
745
973
  payload: e.Any(),
746
974
  replayId: e.Any(),
@@ -748,57 +976,57 @@ const xe = h(
748
976
  topic: e.String()
749
977
  },
750
978
  { $id: "salesforce-streaming:output" }
751
- ), w = class w extends k {
979
+ ), A = class A extends C {
752
980
  constructor() {
753
981
  super(...arguments);
754
- r(this, "client", null);
755
- r(this, "reconnectAttempt", 0);
756
- r(this, "maxReconnectDelay", 6e4);
757
- r(this, "maxReconnectAttempts", 10);
758
- r(this, "grpcErrorHandler", null);
759
- r(this, "stopped", !1);
982
+ a(this, "client", null);
983
+ a(this, "reconnectAttempt", 0);
984
+ a(this, "maxReconnectDelay", 6e4);
985
+ a(this, "maxReconnectAttempts", 10);
986
+ a(this, "grpcErrorHandler", null);
987
+ a(this, "stopped", !1);
760
988
  }
761
989
  async created() {
762
- const n = this.config.connection;
763
- if (!n) {
990
+ const t = this.config.connection;
991
+ if (!t) {
764
992
  this.status({ fill: "red", shape: "dot", text: "no connection" }), this.error("No Salesforce connection configured");
765
993
  return;
766
994
  }
767
- await this.subscribe(n);
995
+ await this.subscribe(t);
768
996
  }
769
- async subscribe(n) {
997
+ async subscribe(t) {
770
998
  if (!this.stopped)
771
999
  try {
772
1000
  this.status({ fill: "green", shape: "dot", text: "connecting..." });
773
- let t;
1001
+ let n;
774
1002
  try {
775
- t = await n.getConnection(), await t.identity();
1003
+ n = await t.getConnection(), await n.identity();
776
1004
  } catch {
777
1005
  this.status({ fill: "red", shape: "dot", text: "auth expired" }), this.error("Salesforce token expired. Re-authorize the connection.");
778
1006
  return;
779
1007
  }
780
- const s = n.getAccessToken(), i = n.getInstanceUrl();
781
- if (!s || !i) {
1008
+ const o = n.accessToken, r = n.instanceUrl;
1009
+ if (!o || !r) {
782
1010
  this.status({ fill: "red", shape: "dot", text: "not authorized" }), this.error("Salesforce connection not authorized");
783
1011
  return;
784
1012
  }
785
- const l = (await import("salesforce-pubsub-api-client")).default;
786
- this.client = new l({
1013
+ const c = (await import("salesforce-pubsub-api-client")).default;
1014
+ this.client = new c({
787
1015
  authType: "user-supplied",
788
- accessToken: s,
789
- instanceUrl: i
1016
+ accessToken: o,
1017
+ instanceUrl: r
790
1018
  }), await this.client.connect();
791
- const d = this.config.numRequested || null, c = this.config.channelName, g = /* @__PURE__ */ f((u, m, p) => {
1019
+ const u = this.config.numRequested || null, l = this.config.channelName, p = /* @__PURE__ */ h((d, m, g) => {
792
1020
  if (m === "event" || m === "lastevent")
793
1021
  this.send({
794
- payload: (p == null ? void 0 : p.payload) ?? p,
795
- replayId: p == null ? void 0 : p.replayId,
796
- channel: c,
797
- topic: c
1022
+ payload: (g == null ? void 0 : g.payload) ?? g,
1023
+ replayId: g == null ? void 0 : g.replayId,
1024
+ channel: l,
1025
+ topic: l
798
1026
  });
799
1027
  else if (m === "error") {
800
- const S = p instanceof Error ? p.message : String(p ?? "stream error");
801
- if (this.warn(`Streaming error: ${S}`), S.includes("UNAUTHENTICATED") || S.includes("authentication")) {
1028
+ const x = g instanceof Error ? g.message : String(g ?? "stream error");
1029
+ if (this.warn(`Streaming error: ${x}`), x.includes("UNAUTHENTICATED") || x.includes("authentication")) {
802
1030
  this.stopped = !0, this.status({
803
1031
  fill: "red",
804
1032
  shape: "dot",
@@ -808,51 +1036,51 @@ const xe = h(
808
1036
  ), this.cleanup();
809
1037
  return;
810
1038
  }
811
- this.status({ fill: "red", shape: "dot", text: S }), this.scheduleReconnect(n);
1039
+ this.status({ fill: "red", shape: "dot", text: x }), this.scheduleReconnect(t);
812
1040
  } else if (m === "end") {
813
1041
  if (this.stopped) return;
814
- this.log("Streaming subscription ended"), this.status({ fill: "red", shape: "dot", text: "disconnected" }), this.scheduleReconnect(n);
1042
+ this.log("Streaming subscription ended"), this.status({ fill: "red", shape: "dot", text: "disconnected" }), this.scheduleReconnect(t);
815
1043
  }
816
1044
  }, "callback");
817
- if (this.grpcErrorHandler && process.removeListener("uncaughtException", this.grpcErrorHandler), this.grpcErrorHandler = (u) => {
818
- var m, p;
819
- ((m = u.message) != null && m.includes("UNAUTHENTICATED") || (p = u.message) != null && p.includes("authentication")) && (this.stopped = !0, this.warn(`Caught gRPC auth error: ${u.message}`), this.status({
1045
+ if (this.grpcErrorHandler && process.removeListener("uncaughtException", this.grpcErrorHandler), this.grpcErrorHandler = (d) => {
1046
+ var m, g;
1047
+ ((m = d.message) != null && m.includes("UNAUTHENTICATED") || (g = d.message) != null && g.includes("authentication")) && (this.stopped = !0, this.warn(`Caught gRPC auth error: ${d.message}`), this.status({
820
1048
  fill: "red",
821
1049
  shape: "dot",
822
1050
  text: "auth expired — re-authorize"
823
1051
  }), this.cleanup());
824
1052
  }, process.on("uncaughtException", this.grpcErrorHandler), this.config.subscribeType === "EARLIEST")
825
1053
  this.client.subscribeFromEarliestEvent(
826
- c,
827
- g,
828
- d
1054
+ l,
1055
+ p,
1056
+ u
829
1057
  );
830
1058
  else if (this.config.subscribeType === "CUSTOM" && this.config.replayId) {
831
- const u = parseInt(this.config.replayId, 10);
1059
+ const d = parseInt(this.config.replayId, 10);
832
1060
  this.client.subscribeFromReplayId(
833
- c,
834
- g,
835
- d,
836
- u
1061
+ l,
1062
+ p,
1063
+ u,
1064
+ d
837
1065
  );
838
1066
  } else
839
- this.client.subscribe(c, g, d);
1067
+ this.client.subscribe(l, p, u);
840
1068
  this.status({
841
1069
  fill: "green",
842
1070
  shape: "dot",
843
- text: `subscribed: ${c}`
1071
+ text: `subscribed: ${l}`
844
1072
  }), this.reconnectAttempt = 0;
845
- } catch (t) {
1073
+ } catch (n) {
846
1074
  this.status({
847
1075
  fill: "red",
848
1076
  shape: "dot",
849
- text: t instanceof Error ? t.message : String(t)
1077
+ text: n instanceof Error ? n.message : String(n)
850
1078
  }), this.error(
851
- `Streaming subscription failed: ${t instanceof Error ? t.message : String(t)}`
852
- ), this.scheduleReconnect(n);
1079
+ `Streaming subscription failed: ${n instanceof Error ? n.message : String(n)}`
1080
+ ), this.scheduleReconnect(t);
853
1081
  }
854
1082
  }
855
- scheduleReconnect(n) {
1083
+ scheduleReconnect(t) {
856
1084
  if (this.stopped) return;
857
1085
  if (this.reconnectAttempt++, this.reconnectAttempt > this.maxReconnectAttempts) {
858
1086
  this.error(
@@ -864,24 +1092,24 @@ const xe = h(
864
1092
  });
865
1093
  return;
866
1094
  }
867
- const t = Math.min(
1095
+ const n = Math.min(
868
1096
  1e3 * Math.pow(2, this.reconnectAttempt),
869
1097
  this.maxReconnectDelay
870
1098
  );
871
1099
  this.log(
872
- `Scheduling reconnect in ${t}ms (attempt ${this.reconnectAttempt}/${this.maxReconnectAttempts})`
1100
+ `Scheduling reconnect in ${n}ms (attempt ${this.reconnectAttempt}/${this.maxReconnectAttempts})`
873
1101
  ), this.status({
874
1102
  fill: "green",
875
1103
  shape: "dot",
876
- text: `reconnecting in ${Math.round(t / 1e3)}s`
1104
+ text: `reconnecting in ${Math.round(n / 1e3)}s`
877
1105
  }), this.setTimeout(async () => {
878
- await this.cleanup(), await this.subscribe(n);
879
- }, t);
1106
+ await this.cleanup(), await this.subscribe(t);
1107
+ }, n);
880
1108
  }
881
1109
  async cleanup() {
882
- var n, t;
1110
+ var t, n;
883
1111
  try {
884
- this.grpcErrorHandler && (process.removeListener("uncaughtException", this.grpcErrorHandler), this.grpcErrorHandler = null), this.client && (await ((t = (n = this.client).close) == null ? void 0 : t.call(n)), this.client = null);
1112
+ this.grpcErrorHandler && (process.removeListener("uncaughtException", this.grpcErrorHandler), this.grpcErrorHandler = null), this.client && (await ((n = (t = this.client).close) == null ? void 0 : n.call(t)), this.client = null);
885
1113
  } catch {
886
1114
  }
887
1115
  }
@@ -889,14 +1117,19 @@ const xe = h(
889
1117
  await this.cleanup();
890
1118
  }
891
1119
  };
892
- f(w, "SalesforceStreaming"), r(w, "type", "salesforce-streaming"), r(w, "category", "salesforce"), r(w, "color", "#FFFFFF"), r(w, "configSchema", xe), r(w, "outputsSchema", be);
893
- let j = w;
894
- const Te = h(
1120
+ h(A, "SalesforceStreaming"), a(A, "type", "salesforce-streaming"), a(A, "category", "salesforce"), a(A, "color", "#FFFFFF"), a(A, "configSchema", Ae), a(A, "outputsSchema", Re);
1121
+ let H = A;
1122
+ const Ce = f(
895
1123
  {
896
1124
  name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
897
- connection: e.NodeRef($, {
1125
+ connection: e.NodeRef(w, {
898
1126
  "x-nrg-form": { icon: "cloud" }
899
1127
  }),
1128
+ apexType: e.Union(
1129
+ [e.Literal("rest"), e.Literal("invocable")],
1130
+ { default: "rest", "x-nrg-form": { icon: "cog" } }
1131
+ ),
1132
+ // REST fields
900
1133
  method: e.Union(
901
1134
  [
902
1135
  e.Literal("GET"),
@@ -913,63 +1146,329 @@ const Te = h(
913
1146
  typedInputTypes: ["str", "msg"]
914
1147
  }
915
1148
  }),
1149
+ // Invocable field
1150
+ actionName: e.String({
1151
+ default: "",
1152
+ "x-nrg-form": { icon: "bolt" }
1153
+ }),
916
1154
  errorPort: e.Boolean({ default: !1 }),
917
1155
  completePort: e.Boolean({ default: !1 }),
918
1156
  statusPort: e.Boolean({ default: !1 })
919
1157
  },
920
- { $id: "salesforce-apex:config" }
921
- ), Ie = h(
1158
+ { $id: "salesforce-apex-invocation:config" }
1159
+ ), Fe = f(
1160
+ { payload: e.Any() },
1161
+ { $id: "salesforce-apex-invocation:input" }
1162
+ ), ve = f(
1163
+ { payload: e.Any() },
1164
+ { $id: "salesforce-apex-invocation:output" }
1165
+ ), L = class L extends C {
1166
+ async input(s) {
1167
+ const t = this.config.connection;
1168
+ if (!t) {
1169
+ this.error("No Salesforce connection configured", s);
1170
+ return;
1171
+ }
1172
+ try {
1173
+ const n = await t.getConnection();
1174
+ if (this.status({ fill: "green", shape: "dot", text: "executing..." }), this.config.apexType === "rest") {
1175
+ const o = await this.config.path.resolve(s), r = this.config.method.toLowerCase();
1176
+ let c;
1177
+ r === "get" || r === "delete" ? c = await n.apex[r](o) : c = await n.apex[r](o, s.payload), this.status({
1178
+ fill: "green",
1179
+ shape: "dot",
1180
+ text: `${this.config.method} done`
1181
+ }), this.send({ ...s, payload: c });
1182
+ } else {
1183
+ const r = await new R(n).invoke(this.config.actionName, s.payload);
1184
+ this.status({ fill: "green", shape: "dot", text: "done" }), this.send({ ...s, payload: r.outputValues });
1185
+ }
1186
+ } catch (n) {
1187
+ const o = n instanceof Error ? n.message : String(n);
1188
+ this.status({ fill: "red", shape: "dot", text: o }), this.error(`Apex failed: ${o}`, s);
1189
+ }
1190
+ }
1191
+ };
1192
+ h(L, "SalesforceApex"), a(L, "type", "salesforce-apex-invocation"), a(L, "category", "salesforce"), a(L, "color", "#FFFFFF"), a(L, "configSchema", Ce), a(L, "inputSchema", Fe), a(L, "outputsSchema", ve);
1193
+ let q = L;
1194
+ const Oe = `private static Object run(String payload) {
1195
+ // Your code here
1196
+ return payload;
1197
+ }`;
1198
+ function Ue(i, s) {
1199
+ return `public class ${i} {
1200
+ public class Input {
1201
+ @InvocableVariable(required=true)
1202
+ public String payload;
1203
+ }
1204
+
1205
+ public class Output {
1206
+ @InvocableVariable
1207
+ public String result;
1208
+ }
1209
+
1210
+ @InvocableMethod(label='${i}' description='Generated by NRG')
1211
+ public static List<Output> execute(List<Input> inputs) {
1212
+ Output out = new Output();
1213
+ Object returnValue = run(inputs[0].payload);
1214
+ out.result = returnValue instanceof String
1215
+ ? (String) returnValue
1216
+ : JSON.serialize(returnValue);
1217
+ return new List<Output>{ out };
1218
+ }
1219
+
1220
+ ${s}
1221
+ }`;
1222
+ }
1223
+ h(Ue, "buildInvocableClass");
1224
+ const Ne = {
1225
+ HttpGet: "doGet",
1226
+ HttpPost: "doPost",
1227
+ HttpPut: "doPut",
1228
+ HttpPatch: "doPatch",
1229
+ HttpDelete: "doDelete"
1230
+ }, Pe = {
1231
+ HttpGet: !1,
1232
+ HttpPost: !0,
1233
+ HttpPut: !0,
1234
+ HttpPatch: !0,
1235
+ HttpDelete: !1
1236
+ };
1237
+ function ke(i, s, t, n) {
1238
+ const o = Ne[t], c = Pe[t] ? ` String payload = RestContext.request.requestBody != null
1239
+ ? RestContext.request.requestBody.toString()
1240
+ : null;` : ` String payload = RestContext.request.params != null
1241
+ ? JSON.serialize(RestContext.request.params)
1242
+ : null;`;
1243
+ return `@RestResource(urlMapping='${s}')
1244
+ global class ${i} {
1245
+ @${t}
1246
+ global static String ${o}() {
1247
+ ${c}
1248
+ Object returnValue = run(payload);
1249
+ return returnValue instanceof String
1250
+ ? (String) returnValue
1251
+ : JSON.serialize(returnValue);
1252
+ }
1253
+
1254
+ ${n}
1255
+ }`;
1256
+ }
1257
+ h(ke, "buildRestClass");
1258
+ const je = f(
922
1259
  {
923
- payload: e.Any()
1260
+ name: e.String({ default: "", "x-nrg-form": { icon: "tag" } }),
1261
+ connection: e.NodeRef(w, {
1262
+ "x-nrg-form": { icon: "cloud" }
1263
+ }),
1264
+ apexType: e.Union(
1265
+ [e.Literal("invocable"), e.Literal("rest")],
1266
+ { default: "invocable", "x-nrg-form": { icon: "cog" } }
1267
+ ),
1268
+ className: e.String({
1269
+ default: "",
1270
+ "x-nrg-form": { icon: "file-code-o" }
1271
+ }),
1272
+ urlMapping: e.String({
1273
+ default: "",
1274
+ "x-nrg-form": { icon: "link" }
1275
+ }),
1276
+ httpMethod: e.Union(
1277
+ [
1278
+ e.Literal("HttpGet"),
1279
+ e.Literal("HttpPost"),
1280
+ e.Literal("HttpPut"),
1281
+ e.Literal("HttpPatch"),
1282
+ e.Literal("HttpDelete")
1283
+ ],
1284
+ { default: "HttpPost", "x-nrg-form": { icon: "random" } }
1285
+ ),
1286
+ code: e.String({
1287
+ default: Oe,
1288
+ "x-nrg-form": { editorLanguage: "apex" }
1289
+ }),
1290
+ errorPort: e.Boolean({ default: !1 }),
1291
+ completePort: e.Boolean({ default: !1 }),
1292
+ statusPort: e.Boolean({ default: !1 })
924
1293
  },
925
- { $id: "salesforce-apex:input" }
926
- ), $e = h(
1294
+ { $id: "salesforce-apex-code:config" }
1295
+ ), Me = f(
927
1296
  {
928
- payload: e.Any()
1297
+ classPrefix: e.String({ default: "NRG_" }),
1298
+ languageServerUrl: e.String({
1299
+ default: "",
1300
+ exportable: !0
1301
+ })
929
1302
  },
930
- { $id: "salesforce-apex:output" }
931
- ), I = class I extends k {
932
- async input(o) {
1303
+ { $id: "salesforce-apex-code:settings" }
1304
+ ), Be = f(
1305
+ { payload: e.Any() },
1306
+ { $id: "salesforce-apex-code:input" }
1307
+ ), He = f(
1308
+ { payload: e.Any() },
1309
+ { $id: "salesforce-apex-code:output" }
1310
+ ), y = class y {
1311
+ constructor(s) {
1312
+ a(this, "pendingDeploys", /* @__PURE__ */ new Map());
1313
+ a(this, "pendingDeletes", /* @__PURE__ */ new Set());
1314
+ a(this, "flushTimer", null);
1315
+ a(this, "connectionProvider");
1316
+ this.connectionProvider = s;
1317
+ }
1318
+ static getInstance(s, t) {
1319
+ return y.instances.has(s) || y.instances.set(
1320
+ s,
1321
+ new y(t)
1322
+ ), y.instances.get(s);
1323
+ }
1324
+ static removeInstance(s) {
1325
+ y.instances.delete(s);
1326
+ }
1327
+ register(s, t) {
1328
+ return this.pendingDeletes.delete(s), new Promise((n, o) => {
1329
+ this.pendingDeploys.set(s, { className: s, body: t, resolve: n, reject: o }), this.scheduleFlush();
1330
+ });
1331
+ }
1332
+ unregister(s) {
1333
+ const t = this.pendingDeploys.get(s);
1334
+ t && (t.reject(new Error("Deploy cancelled — node was removed")), this.pendingDeploys.delete(s)), this.pendingDeletes.add(s), this.scheduleFlush();
1335
+ }
1336
+ scheduleFlush() {
1337
+ this.flushTimer || (this.flushTimer = setTimeout(() => {
1338
+ this.flushTimer = null, this.flush().catch((s) => {
1339
+ console.error("[ApexClassManager] flush error:", s);
1340
+ });
1341
+ }, y.FLUSH_DELAY_MS));
1342
+ }
1343
+ async flush() {
1344
+ const s = new Set(this.pendingDeletes), t = new Map(this.pendingDeploys);
1345
+ if (this.pendingDeletes.clear(), this.pendingDeploys.clear(), s.size === 0 && t.size === 0) return;
1346
+ const n = await this.connectionProvider.getConnection(), o = new R(n), r = [...s, ...t.keys()], c = await o.queryApexClassesByName(r);
1347
+ for (const u of s) {
1348
+ const l = c.get(u);
1349
+ if (l)
1350
+ try {
1351
+ await o.deleteApexClass(l.Id);
1352
+ } catch (p) {
1353
+ console.error(`[ApexClassManager] Failed to delete ${u}:`, p);
1354
+ }
1355
+ }
1356
+ for (const [u, l] of t)
1357
+ try {
1358
+ const p = c.get(u);
1359
+ if (p) {
1360
+ if (p.Body === l.body) {
1361
+ l.resolve({ id: p.Id });
1362
+ continue;
1363
+ }
1364
+ await o.deleteApexClass(p.Id);
1365
+ }
1366
+ const { id: d } = await o.createApexClass(u, l.body);
1367
+ l.resolve({ id: d });
1368
+ } catch (p) {
1369
+ l.reject(p instanceof Error ? p : new Error(String(p)));
1370
+ }
1371
+ }
1372
+ };
1373
+ h(y, "ApexClassManager"), a(y, "instances", /* @__PURE__ */ new Map()), a(y, "FLUSH_DELAY_MS", 500);
1374
+ let N = y;
1375
+ const b = class b extends C {
1376
+ constructor() {
1377
+ super(...arguments);
1378
+ a(this, "deployed", !1);
1379
+ }
1380
+ getFullClassName() {
1381
+ return `${this.settings.classPrefix}${this.config.className}`;
1382
+ }
1383
+ buildApexBody() {
1384
+ const t = this.getFullClassName();
1385
+ return this.config.apexType === "rest" ? ke(
1386
+ t,
1387
+ this.config.urlMapping,
1388
+ this.config.httpMethod,
1389
+ this.config.code
1390
+ ) : Ue(t, this.config.code);
1391
+ }
1392
+ async created() {
1393
+ const t = this.config.connection;
1394
+ if (!t) {
1395
+ this.status({ fill: "red", shape: "dot", text: "no connection" });
1396
+ return;
1397
+ }
1398
+ if (!this.config.className) {
1399
+ this.status({ fill: "red", shape: "dot", text: "class name required" });
1400
+ return;
1401
+ }
1402
+ const n = N.getInstance(
1403
+ t.id,
1404
+ t
1405
+ );
1406
+ this.status({ fill: "green", shape: "dot", text: "deploying..." }), n.register(this.getFullClassName(), this.buildApexBody()).then(() => {
1407
+ this.deployed = !0, this.status({ fill: "green", shape: "dot", text: "deployed" });
1408
+ }).catch((o) => {
1409
+ const r = o instanceof Error ? o.message : String(o);
1410
+ this.status({ fill: "red", shape: "dot", text: r }), this.error(`Apex deploy failed: ${r}`);
1411
+ });
1412
+ }
1413
+ async input(t) {
1414
+ if (!this.deployed) {
1415
+ this.error(
1416
+ "Apex class not yet deployed — wait for deployment to complete",
1417
+ t
1418
+ );
1419
+ return;
1420
+ }
933
1421
  const n = this.config.connection;
934
1422
  if (!n) {
935
- this.error("No Salesforce connection configured", o);
1423
+ this.error("No Salesforce connection configured", t);
936
1424
  return;
937
1425
  }
938
1426
  try {
939
- const t = this.config.method;
940
- this.status({ fill: "green", shape: "dot", text: `${t}...` });
941
- const s = await n.getConnection(), i = await this.config.path.resolve(o);
942
- let l;
943
- const d = t.toLowerCase();
944
- d === "get" || d === "delete" ? l = await s.apex[d](i) : l = await s.apex[d](i, o.payload), this.status({ fill: "green", shape: "dot", text: `${t} done` }), this.send({ ...o, payload: l });
945
- } catch (t) {
946
- this.status({
947
- fill: "red",
948
- shape: "dot",
949
- text: t instanceof Error ? t.message : String(t)
950
- }), this.error(
951
- `Apex ${this.config.method} failed: ${t instanceof Error ? t.message : String(t)}`,
952
- o
953
- );
1427
+ const o = await n.getConnection(), r = new R(o);
1428
+ if (this.status({ fill: "green", shape: "dot", text: "executing..." }), this.config.apexType === "invocable") {
1429
+ const c = await r.invoke(
1430
+ this.getFullClassName(),
1431
+ t.payload
1432
+ );
1433
+ this.status({ fill: "green", shape: "dot", text: "done" }), this.send({ ...t, payload: c.outputValues });
1434
+ } else {
1435
+ const c = this.config.urlMapping, u = this.config.httpMethod;
1436
+ let l;
1437
+ u === "HttpGet" || u === "HttpDelete" ? l = u === "HttpGet" ? await r.get(c) : await r.delete(c) : l = await r[u === "HttpPut" ? "put" : u === "HttpPatch" ? "patch" : "post"](c, t.payload), this.status({ fill: "green", shape: "dot", text: "done" }), this.send({ ...t, payload: l });
1438
+ }
1439
+ } catch (o) {
1440
+ const r = o instanceof Error ? o.message : String(o);
1441
+ this.status({ fill: "red", shape: "dot", text: r }), this.error(`Apex execution failed: ${r}`, t);
1442
+ }
1443
+ }
1444
+ async closed(t) {
1445
+ if (t) {
1446
+ const n = this.config.connection;
1447
+ n && N.getInstance(
1448
+ n.id,
1449
+ n
1450
+ ).unregister(this.getFullClassName());
954
1451
  }
1452
+ this.deployed = !1;
955
1453
  }
956
1454
  };
957
- f(I, "SalesforceApex"), r(I, "type", "salesforce-apex"), r(I, "category", "salesforce"), r(I, "color", "#FFFFFF"), r(I, "configSchema", Te), r(I, "inputSchema", Ie), r(I, "outputsSchema", $e);
958
- let v = I;
959
- const we = Y({
1455
+ h(b, "SalesforceApexCode"), a(b, "type", "salesforce-apex-code"), a(b, "category", "salesforce"), a(b, "color", "#FFFFFF"), a(b, "configSchema", je), a(b, "inputSchema", Be), a(b, "outputsSchema", He), a(b, "settingsSchema", Me);
1456
+ let D = b;
1457
+ const qe = ee({
960
1458
  nodes: [
961
- $,
962
- E,
963
- C,
964
- O,
965
- P,
1459
+ w,
1460
+ k,
966
1461
  j,
967
- v
1462
+ M,
1463
+ B,
1464
+ H,
1465
+ q,
1466
+ D
968
1467
  ]
969
1468
  });
970
- var F = we;
971
- F && typeof F == "object" && Array.isArray(F.nodes) && (F = G(F.nodes));
1469
+ var O = qe;
1470
+ O && typeof O == "object" && Array.isArray(O.nodes) && (O = Z(O.nodes));
972
1471
  export {
973
- F as default
1472
+ O as default
974
1473
  };
975
1474
  //# sourceMappingURL=index.mjs.map