@ductape/sdk 0.0.6 → 0.0.7
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/dist/apps/services/app.service.js +14 -5
- package/dist/apps/services/app.service.js.map +1 -1
- package/dist/apps/utils/string.utils.d.ts +7 -0
- package/dist/apps/utils/string.utils.js +33 -1
- package/dist/apps/utils/string.utils.js.map +1 -1
- package/dist/apps/validators/joi-validators/create.appEnv.validator.js +1 -0
- package/dist/apps/validators/joi-validators/create.appEnv.validator.js.map +1 -1
- package/dist/apps/validators/joi-validators/update.appEnv.validator.js +1 -0
- package/dist/apps/validators/joi-validators/update.appEnv.validator.js.map +1 -1
- package/dist/brokers/brokers.service.d.ts +4 -1
- package/dist/brokers/brokers.service.js +104 -20
- package/dist/brokers/brokers.service.js.map +1 -1
- package/dist/database/databases.service.d.ts +15 -0
- package/dist/database/databases.service.js +183 -14
- package/dist/database/databases.service.js.map +1 -1
- package/dist/graph/graphs.service.d.ts +6 -0
- package/dist/graph/graphs.service.js +155 -35
- package/dist/graph/graphs.service.js.map +1 -1
- package/dist/index.d.ts +28 -10
- package/dist/index.js +88 -10
- package/dist/index.js.map +1 -1
- package/dist/processor/services/processor.service.d.ts +15 -2
- package/dist/processor/services/processor.service.js +246 -28
- package/dist/processor/services/processor.service.js.map +1 -1
- package/dist/products/services/products.service.js +23 -24
- package/dist/products/services/products.service.js.map +1 -1
- package/dist/types/appBuilder.types.d.ts +6 -0
- package/dist/vector/vector-database.service.d.ts +6 -0
- package/dist/vector/vector-database.service.js +138 -31
- package/dist/vector/vector-database.service.js.map +1 -1
- package/dist/workflows/workflow-executor.js +99 -44
- package/dist/workflows/workflow-executor.js.map +1 -1
- package/dist/workflows/workflows.service.js +63 -20
- package/dist/workflows/workflows.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -73,6 +73,7 @@ const app_service_1 = __importDefault(require("../../apps/services/app.service")
|
|
|
73
73
|
const utils_1 = require("../../apps/utils");
|
|
74
74
|
const credential_manager_1 = require("../../apps/utils/credential-manager");
|
|
75
75
|
const oauth_manager_1 = require("../../apps/utils/oauth-manager");
|
|
76
|
+
const string_utils_2 = require("../../apps/utils/string.utils");
|
|
76
77
|
const secrets_1 = require("../../secrets");
|
|
77
78
|
async function loadBrokerService() {
|
|
78
79
|
if (typeof window === 'undefined') {
|
|
@@ -91,16 +92,37 @@ async function loadJWT() {
|
|
|
91
92
|
/** Only log when DUCTAPE_DEBUG is set to avoid sync I/O and serialization cost in hot path */
|
|
92
93
|
const _processorDebug = typeof process !== 'undefined' && (((_a = process.env) === null || _a === void 0 ? void 0 : _a.DUCTAPE_DEBUG) === 'true' || ((_b = process.env) === null || _b === void 0 ? void 0 : _b.DUCTAPE_DEBUG) === '1');
|
|
93
94
|
const debugLog = _processorDebug ? (...args) => console.log(...args) : () => { };
|
|
95
|
+
/** Shared mail (SMTP) transporters: one per workspace+product+poolKey. Not exported. */
|
|
96
|
+
const sharedMailRegistry = new Map();
|
|
97
|
+
const sharedMailInFlight = new Map();
|
|
98
|
+
function getSharedMailKey(workspaceId, product, poolKey) {
|
|
99
|
+
return `mail:${workspaceId}:${product}:${poolKey}`;
|
|
100
|
+
}
|
|
101
|
+
/** Shared Firebase apps: one per workspace+product+projectId. Not exported. */
|
|
102
|
+
const sharedFirebaseRegistry = new Map();
|
|
103
|
+
const sharedFirebaseInFlight = new Map();
|
|
104
|
+
function getSharedFirebaseKey(workspaceId, product, projectId) {
|
|
105
|
+
return `firebase:${workspaceId}:${product}:${projectId}`;
|
|
106
|
+
}
|
|
107
|
+
/** Shared SMS clients: one per workspace+product+poolKey. Not exported. */
|
|
108
|
+
const sharedSmsRegistry = new Map();
|
|
109
|
+
const sharedSmsInFlight = new Map();
|
|
110
|
+
function getSharedSmsKey(workspaceId, product, poolKey) {
|
|
111
|
+
return `sms:${workspaceId}:${product}:${poolKey}`;
|
|
112
|
+
}
|
|
94
113
|
class ProcessorService {
|
|
95
114
|
constructor({ workspace_id, public_key, user_id, token, env_type, private_key, access_key, redis_client, queues, preInitializedProductBuilder }) {
|
|
96
115
|
/** Reuse broker connections when multiple produce steps use the same broker (avoids ~1–3s connection setup per step). Never logged or exposed. */
|
|
97
116
|
this.brokerServicePool = new Map();
|
|
98
117
|
/** Reuse SMTP transporter so we don't open a new connection per email (avoids multi-second handshake per send). Never logged or exposed. */
|
|
99
118
|
this.mailTransporterPool = new Map();
|
|
119
|
+
this.mailPoolKeyToSharedKey = new Map();
|
|
100
120
|
/** Reuse Firebase Admin app per project (avoids re-init per push). Never logged or exposed. */
|
|
101
121
|
this.firebaseAppPool = new Map();
|
|
122
|
+
this.firebasePoolKeyToSharedKey = new Map();
|
|
102
123
|
/** Reuse SMS client per config (Twilio/Nexmo/Plivo). Never logged or exposed. */
|
|
103
124
|
this.smsClientPool = new Map();
|
|
125
|
+
this.smsPoolKeyToSharedKey = new Map();
|
|
104
126
|
this.workspace_id = workspace_id;
|
|
105
127
|
this.public_key = public_key;
|
|
106
128
|
this.user_id = user_id;
|
|
@@ -223,12 +245,72 @@ class ProcessorService {
|
|
|
223
245
|
}
|
|
224
246
|
/**
|
|
225
247
|
* Get or create a mail transporter so we reuse the same SMTP connection instead of opening a new one per send.
|
|
248
|
+
* When scope.workspaceId and scope.product are provided, uses shared registry across instances.
|
|
226
249
|
*/
|
|
227
|
-
async getMailTransporter(auth) {
|
|
250
|
+
async getMailTransporter(auth, scope) {
|
|
251
|
+
var _a, _b;
|
|
228
252
|
const key = this.getMailTransporterPoolKey(auth);
|
|
229
253
|
const existing = this.mailTransporterPool.get(key);
|
|
230
254
|
if (existing)
|
|
231
255
|
return existing;
|
|
256
|
+
const workspaceId = (_a = scope === null || scope === void 0 ? void 0 : scope.workspaceId) !== null && _a !== void 0 ? _a : '';
|
|
257
|
+
const product = (_b = scope === null || scope === void 0 ? void 0 : scope.product) !== null && _b !== void 0 ? _b : '';
|
|
258
|
+
const useShared = workspaceId !== '' && product !== '';
|
|
259
|
+
if (useShared) {
|
|
260
|
+
const sharedKey = getSharedMailKey(workspaceId, product, key);
|
|
261
|
+
const existingShared = sharedMailRegistry.get(sharedKey);
|
|
262
|
+
if (existingShared) {
|
|
263
|
+
this.mailTransporterPool.set(key, existingShared);
|
|
264
|
+
this.mailPoolKeyToSharedKey.set(key, sharedKey);
|
|
265
|
+
return existingShared;
|
|
266
|
+
}
|
|
267
|
+
const inFlight = sharedMailInFlight.get(sharedKey);
|
|
268
|
+
if (inFlight) {
|
|
269
|
+
const transporter = await inFlight;
|
|
270
|
+
this.mailTransporterPool.set(key, transporter);
|
|
271
|
+
this.mailPoolKeyToSharedKey.set(key, sharedKey);
|
|
272
|
+
return transporter;
|
|
273
|
+
}
|
|
274
|
+
const createPromise = (async () => {
|
|
275
|
+
const existingInRegistry = sharedMailRegistry.get(sharedKey);
|
|
276
|
+
if (existingInRegistry) {
|
|
277
|
+
try {
|
|
278
|
+
const close = existingInRegistry.close;
|
|
279
|
+
if (typeof close === 'function')
|
|
280
|
+
await close();
|
|
281
|
+
}
|
|
282
|
+
catch (_a) {
|
|
283
|
+
// Non-fatal
|
|
284
|
+
}
|
|
285
|
+
sharedMailRegistry.delete(sharedKey);
|
|
286
|
+
}
|
|
287
|
+
const transporter = await (0, processor_utils_1.mailerClient)(auth);
|
|
288
|
+
const raceExisting = sharedMailRegistry.get(sharedKey);
|
|
289
|
+
if (raceExisting) {
|
|
290
|
+
try {
|
|
291
|
+
const close = raceExisting.close;
|
|
292
|
+
if (typeof close === 'function')
|
|
293
|
+
await close();
|
|
294
|
+
}
|
|
295
|
+
catch (_b) {
|
|
296
|
+
// Non-fatal
|
|
297
|
+
}
|
|
298
|
+
sharedMailRegistry.delete(sharedKey);
|
|
299
|
+
}
|
|
300
|
+
sharedMailRegistry.set(sharedKey, transporter);
|
|
301
|
+
return transporter;
|
|
302
|
+
})();
|
|
303
|
+
sharedMailInFlight.set(sharedKey, createPromise);
|
|
304
|
+
try {
|
|
305
|
+
const transporter = await createPromise;
|
|
306
|
+
this.mailTransporterPool.set(key, transporter);
|
|
307
|
+
this.mailPoolKeyToSharedKey.set(key, sharedKey);
|
|
308
|
+
return transporter;
|
|
309
|
+
}
|
|
310
|
+
finally {
|
|
311
|
+
sharedMailInFlight.delete(sharedKey);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
232
314
|
const transporter = await (0, processor_utils_1.mailerClient)(auth);
|
|
233
315
|
this.mailTransporterPool.set(key, transporter);
|
|
234
316
|
return transporter;
|
|
@@ -237,7 +319,7 @@ class ProcessorService {
|
|
|
237
319
|
* Close all pooled mail transporters (e.g. at end of workflow run). Safe if pool is empty.
|
|
238
320
|
*/
|
|
239
321
|
async disconnectMailTransporters() {
|
|
240
|
-
for (const transporter of this.mailTransporterPool.
|
|
322
|
+
for (const [key, transporter] of this.mailTransporterPool.entries()) {
|
|
241
323
|
try {
|
|
242
324
|
const close = transporter.close;
|
|
243
325
|
if (typeof close === 'function')
|
|
@@ -246,26 +328,96 @@ class ProcessorService {
|
|
|
246
328
|
catch (_a) {
|
|
247
329
|
// Non-fatal
|
|
248
330
|
}
|
|
331
|
+
const sharedKey = this.mailPoolKeyToSharedKey.get(key);
|
|
332
|
+
if (sharedKey)
|
|
333
|
+
sharedMailRegistry.delete(sharedKey);
|
|
249
334
|
}
|
|
250
335
|
this.mailTransporterPool.clear();
|
|
336
|
+
this.mailPoolKeyToSharedKey.clear();
|
|
251
337
|
}
|
|
252
338
|
/**
|
|
253
339
|
* Get or create Firebase Admin app by project_id so we reuse the same app per project (Expo client is already module-level singleton).
|
|
340
|
+
* When scope.workspaceId and scope.product are provided, uses shared registry across instances.
|
|
254
341
|
*/
|
|
255
|
-
async getFirebaseApp(credentials) {
|
|
256
|
-
var _a, _b;
|
|
342
|
+
async getFirebaseApp(credentials, scope) {
|
|
343
|
+
var _a, _b, _c, _d;
|
|
257
344
|
const creds = typeof credentials === 'string' ? JSON.parse(credentials) : credentials;
|
|
258
345
|
const projectId = (_a = creds === null || creds === void 0 ? void 0 : creds.project_id) !== null && _a !== void 0 ? _a : `fb-${String((_b = creds === null || creds === void 0 ? void 0 : creds.client_email) !== null && _b !== void 0 ? _b : '').slice(0, 20)}`;
|
|
259
346
|
const existing = this.firebaseAppPool.get(projectId);
|
|
260
347
|
if (existing)
|
|
261
348
|
return existing;
|
|
349
|
+
const workspaceId = (_c = scope === null || scope === void 0 ? void 0 : scope.workspaceId) !== null && _c !== void 0 ? _c : '';
|
|
350
|
+
const product = (_d = scope === null || scope === void 0 ? void 0 : scope.product) !== null && _d !== void 0 ? _d : '';
|
|
351
|
+
const useShared = workspaceId !== '' && product !== '';
|
|
352
|
+
if (useShared) {
|
|
353
|
+
const sharedKey = getSharedFirebaseKey(workspaceId, product, projectId);
|
|
354
|
+
const existingShared = sharedFirebaseRegistry.get(sharedKey);
|
|
355
|
+
if (existingShared) {
|
|
356
|
+
this.firebaseAppPool.set(projectId, existingShared);
|
|
357
|
+
this.firebasePoolKeyToSharedKey.set(projectId, sharedKey);
|
|
358
|
+
return existingShared;
|
|
359
|
+
}
|
|
360
|
+
const inFlight = sharedFirebaseInFlight.get(sharedKey);
|
|
361
|
+
if (inFlight) {
|
|
362
|
+
const app = await inFlight;
|
|
363
|
+
this.firebaseAppPool.set(projectId, app);
|
|
364
|
+
this.firebasePoolKeyToSharedKey.set(projectId, sharedKey);
|
|
365
|
+
return app;
|
|
366
|
+
}
|
|
367
|
+
const createPromise = (async () => {
|
|
368
|
+
const existingInRegistry = sharedFirebaseRegistry.get(sharedKey);
|
|
369
|
+
if (existingInRegistry) {
|
|
370
|
+
try {
|
|
371
|
+
const del = existingInRegistry.delete;
|
|
372
|
+
if (typeof del === 'function')
|
|
373
|
+
await del();
|
|
374
|
+
}
|
|
375
|
+
catch (_a) {
|
|
376
|
+
// Non-fatal
|
|
377
|
+
}
|
|
378
|
+
sharedFirebaseRegistry.delete(sharedKey);
|
|
379
|
+
}
|
|
380
|
+
const admin = require('firebase-admin');
|
|
381
|
+
let app;
|
|
382
|
+
try {
|
|
383
|
+
app = admin.app(projectId);
|
|
384
|
+
}
|
|
385
|
+
catch (_b) {
|
|
386
|
+
app = admin.initializeApp({ credential: admin.credential.cert(credentials) }, projectId);
|
|
387
|
+
}
|
|
388
|
+
const raceExisting = sharedFirebaseRegistry.get(sharedKey);
|
|
389
|
+
if (raceExisting) {
|
|
390
|
+
try {
|
|
391
|
+
const del = raceExisting.delete;
|
|
392
|
+
if (typeof del === 'function')
|
|
393
|
+
await del();
|
|
394
|
+
}
|
|
395
|
+
catch (_c) {
|
|
396
|
+
// Non-fatal
|
|
397
|
+
}
|
|
398
|
+
sharedFirebaseRegistry.delete(sharedKey);
|
|
399
|
+
}
|
|
400
|
+
sharedFirebaseRegistry.set(sharedKey, app);
|
|
401
|
+
return app;
|
|
402
|
+
})();
|
|
403
|
+
sharedFirebaseInFlight.set(sharedKey, createPromise);
|
|
404
|
+
try {
|
|
405
|
+
const app = await createPromise;
|
|
406
|
+
this.firebaseAppPool.set(projectId, app);
|
|
407
|
+
this.firebasePoolKeyToSharedKey.set(projectId, sharedKey);
|
|
408
|
+
return app;
|
|
409
|
+
}
|
|
410
|
+
finally {
|
|
411
|
+
sharedFirebaseInFlight.delete(sharedKey);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
262
414
|
const admin = require('firebase-admin');
|
|
263
415
|
try {
|
|
264
416
|
const app = admin.app(projectId);
|
|
265
417
|
this.firebaseAppPool.set(projectId, app);
|
|
266
418
|
return app;
|
|
267
419
|
}
|
|
268
|
-
catch (
|
|
420
|
+
catch (_e) {
|
|
269
421
|
const app = admin.initializeApp({ credential: admin.credential.cert(credentials) }, projectId);
|
|
270
422
|
this.firebaseAppPool.set(projectId, app);
|
|
271
423
|
return app;
|
|
@@ -275,7 +427,7 @@ class ProcessorService {
|
|
|
275
427
|
* Close all pooled Firebase apps (e.g. at end of workflow run). Safe if pool is empty.
|
|
276
428
|
*/
|
|
277
429
|
async disconnectFirebaseApps() {
|
|
278
|
-
for (const app of this.firebaseAppPool.
|
|
430
|
+
for (const [projectId, app] of this.firebaseAppPool.entries()) {
|
|
279
431
|
try {
|
|
280
432
|
const del = app.delete;
|
|
281
433
|
if (typeof del === 'function')
|
|
@@ -284,8 +436,12 @@ class ProcessorService {
|
|
|
284
436
|
catch (_a) {
|
|
285
437
|
// Non-fatal
|
|
286
438
|
}
|
|
439
|
+
const sharedKey = this.firebasePoolKeyToSharedKey.get(projectId);
|
|
440
|
+
if (sharedKey)
|
|
441
|
+
sharedFirebaseRegistry.delete(sharedKey);
|
|
287
442
|
}
|
|
288
443
|
this.firebaseAppPool.clear();
|
|
444
|
+
this.firebasePoolKeyToSharedKey.clear();
|
|
289
445
|
}
|
|
290
446
|
/**
|
|
291
447
|
* Pool key for SMS client (provider + identifier + sender; no secrets). Same config => reuse client.
|
|
@@ -299,12 +455,55 @@ class ProcessorService {
|
|
|
299
455
|
}
|
|
300
456
|
/**
|
|
301
457
|
* Get or create SMS client so we reuse Twilio/Nexmo/Plivo client per config.
|
|
458
|
+
* When scope.workspaceId and scope.product are provided, uses shared registry across instances.
|
|
302
459
|
*/
|
|
303
|
-
async getSmsClient(config) {
|
|
460
|
+
async getSmsClient(config, scope) {
|
|
461
|
+
var _a, _b;
|
|
304
462
|
const key = this.getSmsClientPoolKey(config);
|
|
305
463
|
const existing = this.smsClientPool.get(key);
|
|
306
464
|
if (existing)
|
|
307
465
|
return existing;
|
|
466
|
+
const workspaceId = (_a = scope === null || scope === void 0 ? void 0 : scope.workspaceId) !== null && _a !== void 0 ? _a : '';
|
|
467
|
+
const product = (_b = scope === null || scope === void 0 ? void 0 : scope.product) !== null && _b !== void 0 ? _b : '';
|
|
468
|
+
const useShared = workspaceId !== '' && product !== '';
|
|
469
|
+
if (useShared) {
|
|
470
|
+
const sharedKey = getSharedSmsKey(workspaceId, product, key);
|
|
471
|
+
const existingShared = sharedSmsRegistry.get(sharedKey);
|
|
472
|
+
if (existingShared) {
|
|
473
|
+
this.smsClientPool.set(key, existingShared);
|
|
474
|
+
this.smsPoolKeyToSharedKey.set(key, sharedKey);
|
|
475
|
+
return existingShared;
|
|
476
|
+
}
|
|
477
|
+
const inFlight = sharedSmsInFlight.get(sharedKey);
|
|
478
|
+
if (inFlight) {
|
|
479
|
+
const client = await inFlight;
|
|
480
|
+
this.smsClientPool.set(key, client);
|
|
481
|
+
this.smsPoolKeyToSharedKey.set(key, sharedKey);
|
|
482
|
+
return client;
|
|
483
|
+
}
|
|
484
|
+
const createPromise = (async () => {
|
|
485
|
+
sharedSmsRegistry.delete(sharedKey);
|
|
486
|
+
const SmsClientClass = await (0, sms_repo_1.loadSMSClient)();
|
|
487
|
+
if (!SmsClientClass)
|
|
488
|
+
throw new Error('SMS client not loaded (e.g. browser).');
|
|
489
|
+
const client = new SmsClientClass(config);
|
|
490
|
+
const raceExisting = sharedSmsRegistry.get(sharedKey);
|
|
491
|
+
if (raceExisting)
|
|
492
|
+
sharedSmsRegistry.delete(sharedKey);
|
|
493
|
+
sharedSmsRegistry.set(sharedKey, client);
|
|
494
|
+
return client;
|
|
495
|
+
})();
|
|
496
|
+
sharedSmsInFlight.set(sharedKey, createPromise);
|
|
497
|
+
try {
|
|
498
|
+
const client = await createPromise;
|
|
499
|
+
this.smsClientPool.set(key, client);
|
|
500
|
+
this.smsPoolKeyToSharedKey.set(key, sharedKey);
|
|
501
|
+
return client;
|
|
502
|
+
}
|
|
503
|
+
finally {
|
|
504
|
+
sharedSmsInFlight.delete(sharedKey);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
308
507
|
const SmsClientClass = await (0, sms_repo_1.loadSMSClient)();
|
|
309
508
|
if (!SmsClientClass)
|
|
310
509
|
throw new Error('SMS client not loaded (e.g. browser).');
|
|
@@ -316,7 +515,13 @@ class ProcessorService {
|
|
|
316
515
|
* Clear pooled SMS clients (e.g. at end of workflow run). Safe if pool is empty.
|
|
317
516
|
*/
|
|
318
517
|
async disconnectSmsClients() {
|
|
518
|
+
for (const [key] of this.smsClientPool.entries()) {
|
|
519
|
+
const sharedKey = this.smsPoolKeyToSharedKey.get(key);
|
|
520
|
+
if (sharedKey)
|
|
521
|
+
sharedSmsRegistry.delete(sharedKey);
|
|
522
|
+
}
|
|
319
523
|
this.smsClientPool.clear();
|
|
524
|
+
this.smsPoolKeyToSharedKey.clear();
|
|
320
525
|
}
|
|
321
526
|
/**
|
|
322
527
|
* Pre-warm broker connections for the given product/env and broker tags.
|
|
@@ -2327,6 +2532,7 @@ class ProcessorService {
|
|
|
2327
2532
|
return (0, processor_utils_1.generateIndexes)(operator, iter, init, valueValue);
|
|
2328
2533
|
}
|
|
2329
2534
|
async runAction(event, additional_logs, returnValue = true, bootstrapData) {
|
|
2535
|
+
var _a, _b, _c;
|
|
2330
2536
|
try {
|
|
2331
2537
|
const { event: action_tag, app: access_tag, condition, cache: cache_tag } = event;
|
|
2332
2538
|
let indexes = [];
|
|
@@ -2346,6 +2552,8 @@ class ProcessorService {
|
|
|
2346
2552
|
let app_active;
|
|
2347
2553
|
let app_id = '';
|
|
2348
2554
|
let app_env_slug = '';
|
|
2555
|
+
/** Product app env mapping (includes variables for base_url resolution). */
|
|
2556
|
+
let envMapping = null;
|
|
2349
2557
|
// Use bootstrap data if provided, otherwise fetch via API
|
|
2350
2558
|
if (bootstrapData) {
|
|
2351
2559
|
action = bootstrapData.action;
|
|
@@ -2354,6 +2562,7 @@ class ProcessorService {
|
|
|
2354
2562
|
recipient_workspace_id = bootstrapData.recipient_workspace_id;
|
|
2355
2563
|
app_active = bootstrapData.app_active;
|
|
2356
2564
|
app_env_slug = env.slug;
|
|
2565
|
+
envMapping = (_a = bootstrapData.product_env_mapping) !== null && _a !== void 0 ? _a : null;
|
|
2357
2566
|
additional_logs.app_env = app_env_slug;
|
|
2358
2567
|
}
|
|
2359
2568
|
else {
|
|
@@ -2362,7 +2571,7 @@ class ProcessorService {
|
|
|
2362
2571
|
const { actions, envs: appEnvs, retries: appRetries, workspace_id: appWorkspaceId, active } = appData;
|
|
2363
2572
|
const productApp = await this.productBuilderService.fetchApp(access_tag);
|
|
2364
2573
|
const { envs: productEnvs } = productApp;
|
|
2365
|
-
|
|
2574
|
+
envMapping = (_b = productEnvs.find((item) => item.product_env_slug === this.processEnv.slug)) !== null && _b !== void 0 ? _b : null;
|
|
2366
2575
|
app_env_slug = (envMapping === null || envMapping === void 0 ? void 0 : envMapping.app_env_slug) || '';
|
|
2367
2576
|
additional_logs.app_env = app_env_slug;
|
|
2368
2577
|
env = appEnvs.find((item) => item.slug === app_env_slug);
|
|
@@ -2392,6 +2601,10 @@ class ProcessorService {
|
|
|
2392
2601
|
request_base_url = actionEnv.base_url;
|
|
2393
2602
|
}
|
|
2394
2603
|
}
|
|
2604
|
+
// Resolve {{variable}} and :variable in base_url with product env variables
|
|
2605
|
+
if ((_c = envMapping === null || envMapping === void 0 ? void 0 : envMapping.variables) === null || _c === void 0 ? void 0 : _c.length) {
|
|
2606
|
+
request_base_url = (0, string_utils_2.resolveBaseUrlVariables)(request_base_url, envMapping.variables);
|
|
2607
|
+
}
|
|
2395
2608
|
const samples = {
|
|
2396
2609
|
query: (query === null || query === void 0 ? void 0 : query.data) || [],
|
|
2397
2610
|
headers: (headers === null || headers === void 0 ? void 0 : headers.data) || [],
|
|
@@ -3317,7 +3530,7 @@ class ProcessorService {
|
|
|
3317
3530
|
throw e;
|
|
3318
3531
|
}
|
|
3319
3532
|
}
|
|
3320
|
-
async sendFirebaseNotification(payload, device_tokens, credentials) {
|
|
3533
|
+
async sendFirebaseNotification(payload, device_tokens, credentials, scope) {
|
|
3321
3534
|
const message = {
|
|
3322
3535
|
notification: {
|
|
3323
3536
|
title: payload.title,
|
|
@@ -3326,7 +3539,7 @@ class ProcessorService {
|
|
|
3326
3539
|
tokens: device_tokens,
|
|
3327
3540
|
};
|
|
3328
3541
|
try {
|
|
3329
|
-
const app = await this.getFirebaseApp(credentials);
|
|
3542
|
+
const app = await this.getFirebaseApp(credentials, scope);
|
|
3330
3543
|
await app.messaging().sendEachForMulticast(message);
|
|
3331
3544
|
}
|
|
3332
3545
|
catch (e) {
|
|
@@ -3347,7 +3560,7 @@ class ProcessorService {
|
|
|
3347
3560
|
await this.sendExpoNotification({ title, body, data }, payload.device_tokens);
|
|
3348
3561
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: logType, message: 'Send Expo notification - success', data: { title, body, data }, status: types_1.LogEventStatus.SUCCESS }));
|
|
3349
3562
|
}
|
|
3350
|
-
async ProcessFirebaseNotification(notification, template, payload, additional_logs, logType = types_1.LogEventTypes.PUSH) {
|
|
3563
|
+
async ProcessFirebaseNotification(notification, template, payload, additional_logs, logType = types_1.LogEventTypes.PUSH, scope) {
|
|
3351
3564
|
var _a, _b;
|
|
3352
3565
|
debugLog('[ProcessFirebaseNotification] ENTRY', { deviceTokens: (_a = payload === null || payload === void 0 ? void 0 : payload.device_tokens) === null || _a === void 0 ? void 0 : _a.length, logType });
|
|
3353
3566
|
(0, processor_utils_1.validateNotification)(template, payload);
|
|
@@ -3356,11 +3569,11 @@ class ProcessorService {
|
|
|
3356
3569
|
debugLog('[ProcessFirebaseNotification] Template generated', { title: (_b = title === null || title === void 0 ? void 0 : title.slice) === null || _b === void 0 ? void 0 : _b.call(title, 0, 40), bodyLength: body === null || body === void 0 ? void 0 : body.length });
|
|
3357
3570
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: logType, message: 'Generate Firebase notification template - success', data: { title, body, data }, status: types_1.LogEventStatus.SUCCESS }));
|
|
3358
3571
|
debugLog('[ProcessFirebaseNotification] Sending to Firebase');
|
|
3359
|
-
await this.sendFirebaseNotification({ title, body, data }, payload.device_tokens, notification.credentials);
|
|
3572
|
+
await this.sendFirebaseNotification({ title, body, data }, payload.device_tokens, notification.credentials, scope);
|
|
3360
3573
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: logType, message: 'Send Firebase notification - success', data: { title, body, data }, status: types_1.LogEventStatus.SUCCESS }));
|
|
3361
3574
|
}
|
|
3362
3575
|
async runNotification(notification, additional_logs, bootstrapData) {
|
|
3363
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
3576
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
3364
3577
|
const { event } = notification;
|
|
3365
3578
|
const input = notification.input;
|
|
3366
3579
|
const logMessageLog = (channelType, status, err) => {
|
|
@@ -3423,6 +3636,10 @@ class ProcessorService {
|
|
|
3423
3636
|
}
|
|
3424
3637
|
}
|
|
3425
3638
|
const { push_notification: push, email, callback, sms } = message;
|
|
3639
|
+
const notifScope = {
|
|
3640
|
+
workspaceId: (_d = this.workspace_id) !== null && _d !== void 0 ? _d : '',
|
|
3641
|
+
product: (_f = (_e = bootstrapData === null || bootstrapData === void 0 ? void 0 : bootstrapData.product_tag) !== null && _e !== void 0 ? _e : this.productTag) !== null && _f !== void 0 ? _f : '',
|
|
3642
|
+
};
|
|
3426
3643
|
debugLog('[runNotification] Message template flags', { push: !!push, email: !!email, callback: !!callback, sms: !!sms });
|
|
3427
3644
|
debugLog('[runNotification] Input channels present', {
|
|
3428
3645
|
push_notification: !!input.push_notification,
|
|
@@ -3473,7 +3690,7 @@ class ProcessorService {
|
|
|
3473
3690
|
debugLog('[runNotification] PUSH: processing Firebase');
|
|
3474
3691
|
this.lastNotificationFailureType = types_1.LogEventTypes.PUSH;
|
|
3475
3692
|
try {
|
|
3476
|
-
await this.ProcessFirebaseNotification(notifications, message, input.push_notification, additional_logs);
|
|
3693
|
+
await this.ProcessFirebaseNotification(notifications, message, input.push_notification, additional_logs, undefined, notifScope);
|
|
3477
3694
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: types_1.LogEventTypes.PUSH, successful_execution: true, message: 'Processing Firebase notification - success', data: { notification }, status: types_1.LogEventStatus.SUCCESS }));
|
|
3478
3695
|
logMessageLog('push', 'sent');
|
|
3479
3696
|
debugLog('[runNotification] PUSH (Firebase): success');
|
|
@@ -3514,9 +3731,9 @@ class ProcessorService {
|
|
|
3514
3731
|
subject,
|
|
3515
3732
|
template,
|
|
3516
3733
|
};
|
|
3517
|
-
debugLog('[runNotification] EMAIL: sending mail', { to: (
|
|
3734
|
+
debugLog('[runNotification] EMAIL: sending mail', { to: (_g = mailOptions.to) === null || _g === void 0 ? void 0 : _g.length, subject: (_j = (_h = mailOptions.subject) === null || _h === void 0 ? void 0 : _h.slice) === null || _j === void 0 ? void 0 : _j.call(_h, 0, 50) });
|
|
3518
3735
|
try {
|
|
3519
|
-
const transporter = await this.getMailTransporter(auth);
|
|
3736
|
+
const transporter = await this.getMailTransporter(auth, notifScope);
|
|
3520
3737
|
await transporter.sendMail(mailOptions);
|
|
3521
3738
|
logMessageLog('email', 'sent');
|
|
3522
3739
|
}
|
|
@@ -3538,10 +3755,10 @@ class ProcessorService {
|
|
|
3538
3755
|
debugLog('[runNotification] CALLBACK: processing', { url: callbacks.url, method: callbacks.method });
|
|
3539
3756
|
this.lastNotificationFailureType = types_1.LogEventTypes.CALLBACKS;
|
|
3540
3757
|
const payload = {
|
|
3541
|
-
query: Object.assign(Object.assign({}, (
|
|
3542
|
-
headers: Object.assign(Object.assign({}, (
|
|
3543
|
-
params: Object.assign(Object.assign({}, (
|
|
3544
|
-
body: Object.assign(Object.assign({}, (
|
|
3758
|
+
query: Object.assign(Object.assign({}, (_k = input.callback) === null || _k === void 0 ? void 0 : _k.query), (_l = callbacks.auth) === null || _l === void 0 ? void 0 : _l.query),
|
|
3759
|
+
headers: Object.assign(Object.assign({}, (_m = input.callback) === null || _m === void 0 ? void 0 : _m.headers), (_o = callbacks.auth) === null || _o === void 0 ? void 0 : _o.headers),
|
|
3760
|
+
params: Object.assign(Object.assign({}, (_p = input.callback) === null || _p === void 0 ? void 0 : _p.params), (_q = callbacks.auth) === null || _q === void 0 ? void 0 : _q.params),
|
|
3761
|
+
body: Object.assign(Object.assign({}, (_r = input.callback) === null || _r === void 0 ? void 0 : _r.body), (_s = callbacks.auth) === null || _s === void 0 ? void 0 : _s.body),
|
|
3545
3762
|
};
|
|
3546
3763
|
input.callback.body = await this.generatePayload(payload.body, notification, additional_logs, message.callback_data.filter((data) => data.parent_key === 'body'));
|
|
3547
3764
|
input.callback.query = await this.generatePayload(payload.query, notification, additional_logs, message.callback_data.filter((data) => data.parent_key === 'query'));
|
|
@@ -3558,10 +3775,10 @@ class ProcessorService {
|
|
|
3558
3775
|
}
|
|
3559
3776
|
const url = new URL(callbackUrl);
|
|
3560
3777
|
const requestPayload = {
|
|
3561
|
-
query: Object.assign(Object.assign({}, (
|
|
3562
|
-
headers: Object.assign(Object.assign({}, (
|
|
3563
|
-
params: Object.assign(Object.assign({}, (
|
|
3564
|
-
body: Object.assign(Object.assign({}, (
|
|
3778
|
+
query: Object.assign(Object.assign({}, (_t = input.callback) === null || _t === void 0 ? void 0 : _t.query), (_u = callbacks.auth) === null || _u === void 0 ? void 0 : _u.query),
|
|
3779
|
+
headers: Object.assign(Object.assign({}, (_v = input.callback) === null || _v === void 0 ? void 0 : _v.headers), (_w = callbacks.auth) === null || _w === void 0 ? void 0 : _w.headers),
|
|
3780
|
+
params: Object.assign(Object.assign({}, (_x = input.callback) === null || _x === void 0 ? void 0 : _x.params), (_y = callbacks.auth) === null || _y === void 0 ? void 0 : _y.params),
|
|
3781
|
+
body: Object.assign(Object.assign({}, (_z = input.callback) === null || _z === void 0 ? void 0 : _z.body), (_0 = callbacks.auth) === null || _0 === void 0 ? void 0 : _0.body),
|
|
3565
3782
|
};
|
|
3566
3783
|
try {
|
|
3567
3784
|
await this.sendActionRequest(url.origin, url.pathname, requestPayload, callbacks.method, '');
|
|
@@ -3584,11 +3801,11 @@ class ProcessorService {
|
|
|
3584
3801
|
debugLog('[runNotification] SMS: skipped (no input.sms)');
|
|
3585
3802
|
}
|
|
3586
3803
|
if (sms && smses && input.sms) {
|
|
3587
|
-
debugLog('[runNotification] SMS: processing', { recipients: (
|
|
3804
|
+
debugLog('[runNotification] SMS: processing', { recipients: (_1 = input.sms.recipients) === null || _1 === void 0 ? void 0 : _1.length });
|
|
3588
3805
|
this.lastNotificationFailureType = types_1.LogEventTypes.SMS;
|
|
3589
3806
|
try {
|
|
3590
3807
|
input.sms.body = (await (0, processor_utils_1.replacePlaceholderString)(sms, input.sms.body));
|
|
3591
|
-
const smsClient = await this.getSmsClient(smses);
|
|
3808
|
+
const smsClient = await this.getSmsClient(smses, notifScope);
|
|
3592
3809
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: types_1.LogEventTypes.SMS, name: 'Send sms - initiated', data: { message: input.sms.body, config: smses }, status: types_1.LogEventStatus.SUCCESS }));
|
|
3593
3810
|
const res = await smsClient.sendMessage(input.sms.body, input.sms.recipients);
|
|
3594
3811
|
if (res && res.success !== undefined && !res.success) {
|
|
@@ -3604,7 +3821,7 @@ class ProcessorService {
|
|
|
3604
3821
|
logMessageLog('sms', 'failed', e);
|
|
3605
3822
|
}
|
|
3606
3823
|
}
|
|
3607
|
-
debugLog('[runNotification] DONE: all channels processed', { lastChannelType: (
|
|
3824
|
+
debugLog('[runNotification] DONE: all channels processed', { lastChannelType: (_2 = this.lastNotificationFailureType) !== null && _2 !== void 0 ? _2 : 'NOTIFICATIONS' });
|
|
3608
3825
|
// Only add aggregate success log when we have a subtype (no NOTIFICATIONS-typed logs)
|
|
3609
3826
|
/*if (this.lastNotificationFailureType != null) {
|
|
3610
3827
|
this.logService.add({
|
|
@@ -3618,7 +3835,7 @@ class ProcessorService {
|
|
|
3618
3835
|
}*/
|
|
3619
3836
|
}
|
|
3620
3837
|
catch (e) {
|
|
3621
|
-
debugLog('[runNotification] ERROR', { error: e, lastChannelType: (
|
|
3838
|
+
debugLog('[runNotification] ERROR', { error: e, lastChannelType: (_3 = this.lastNotificationFailureType) !== null && _3 !== void 0 ? _3 : 'NOTIFICATIONS' });
|
|
3622
3839
|
// Only add aggregate failure log when we have a subtype (no NOTIFICATIONS-typed logs)
|
|
3623
3840
|
if (this.lastNotificationFailureType != null) {
|
|
3624
3841
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { type: this.lastNotificationFailureType, failed_execution: true, message: 'Attempt notification - failed', data: { e: e.toString() }, status: types_1.LogEventStatus.FAIL }));
|
|
@@ -4304,6 +4521,7 @@ class ProcessorService {
|
|
|
4304
4521
|
retries: bootstrapData.retries,
|
|
4305
4522
|
app_active: bootstrapData.app_active,
|
|
4306
4523
|
recipient_workspace_id: bootstrapData.recipient_workspace_id,
|
|
4524
|
+
product_env_mapping: bootstrapData.product_env_mapping,
|
|
4307
4525
|
});
|
|
4308
4526
|
this.end = Date.now();
|
|
4309
4527
|
this.logService.add(Object.assign(Object.assign(Object.assign({}, this.baseLogs), additional_logs), { message: 'Execute action - success', data: { input: (0, processor_utils_1.anonymizeObject)(input), result: (0, processor_utils_1.anonymizeObject)(result) }, status: types_1.LogEventStatus.SUCCESS }));
|