av6-core 1.5.19 → 1.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/dist/index.js +136 -43
- package/dist/index.mjs +136 -43
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2369,6 +2369,42 @@ var uinConfigService = (uinDeps) => {
|
|
|
2369
2369
|
};
|
|
2370
2370
|
};
|
|
2371
2371
|
|
|
2372
|
+
// src/providers/app.provider.ts
|
|
2373
|
+
var ExpoAppNotificationProvider = class {
|
|
2374
|
+
constructor(logger = console, url = "https://api.expo.dev/v2/push/send") {
|
|
2375
|
+
this.logger = logger;
|
|
2376
|
+
this.url = url;
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Bulk send: one HTTP request with many messages.
|
|
2380
|
+
*/
|
|
2381
|
+
async sendBulk(messages) {
|
|
2382
|
+
const payload = (messages ?? []).filter((m) => !!m?.to);
|
|
2383
|
+
if (!payload.length) return { ok: true, tickets: [] };
|
|
2384
|
+
try {
|
|
2385
|
+
const res = await fetch(this.url, {
|
|
2386
|
+
method: "POST",
|
|
2387
|
+
headers: { "Content-Type": "application/json" },
|
|
2388
|
+
body: JSON.stringify(payload)
|
|
2389
|
+
});
|
|
2390
|
+
const data = await res.json().catch(() => ({}));
|
|
2391
|
+
if (!res.ok) {
|
|
2392
|
+
return { ok: false, error: `Expo HTTP ${res.status} ${res.statusText}`, meta: data };
|
|
2393
|
+
}
|
|
2394
|
+
const tickets = data?.data ?? [];
|
|
2395
|
+
const anyError = Array.isArray(tickets) && tickets.some((t) => t?.status === "error");
|
|
2396
|
+
return {
|
|
2397
|
+
ok: !anyError,
|
|
2398
|
+
tickets,
|
|
2399
|
+
meta: data
|
|
2400
|
+
};
|
|
2401
|
+
} catch (e) {
|
|
2402
|
+
this.logger.error("[ExpoAppNotificationProvider] sendBulk failed", e);
|
|
2403
|
+
return { ok: false, error: e?.message ?? String(e) };
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2372
2408
|
// src/types/notification.ts
|
|
2373
2409
|
var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
|
|
2374
2410
|
TemplateType2["EMAIL"] = "EMAIL";
|
|
@@ -2379,33 +2415,6 @@ var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
|
|
|
2379
2415
|
return TemplateType2;
|
|
2380
2416
|
})(TemplateType || {});
|
|
2381
2417
|
|
|
2382
|
-
// src/providers/app.provider.ts
|
|
2383
|
-
var AppNotificationProvider = class {
|
|
2384
|
-
async send(args) {
|
|
2385
|
-
if (!args.recipient.appUserId) {
|
|
2386
|
-
return {
|
|
2387
|
-
ok: false,
|
|
2388
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2389
|
-
error: "Missing recipient.appUserId"
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
try {
|
|
2393
|
-
const fake = { id: "push-abc", status: "queued" };
|
|
2394
|
-
return {
|
|
2395
|
-
ok: true,
|
|
2396
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2397
|
-
externalId: fake.id
|
|
2398
|
-
};
|
|
2399
|
-
} catch (err) {
|
|
2400
|
-
return {
|
|
2401
|
-
ok: false,
|
|
2402
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2403
|
-
error: err?.message ?? String(err)
|
|
2404
|
-
};
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
};
|
|
2408
|
-
|
|
2409
2418
|
// src/providers/email.providers.ts
|
|
2410
2419
|
var import_nodemailer = __toESM(require("nodemailer"));
|
|
2411
2420
|
var EmailProvider = class {
|
|
@@ -3397,33 +3406,117 @@ var NotificationService = class {
|
|
|
3397
3406
|
});
|
|
3398
3407
|
}
|
|
3399
3408
|
}
|
|
3409
|
+
async getExpoTokensByUserIds(userIds) {
|
|
3410
|
+
if (!userIds.length) return /* @__PURE__ */ new Map();
|
|
3411
|
+
const rows = await this.prisma.session.findMany({
|
|
3412
|
+
where: {
|
|
3413
|
+
userId: { in: userIds },
|
|
3414
|
+
deviceNotificationToken: { not: null },
|
|
3415
|
+
logoutAt: null
|
|
3416
|
+
},
|
|
3417
|
+
select: { userId: true, deviceNotificationToken: true }
|
|
3418
|
+
});
|
|
3419
|
+
const map = /* @__PURE__ */ new Map();
|
|
3420
|
+
for (const r of rows) {
|
|
3421
|
+
const token = r.deviceNotificationToken?.trim();
|
|
3422
|
+
if (!token) continue;
|
|
3423
|
+
if (!map.has(r.userId)) map.set(r.userId, []);
|
|
3424
|
+
map.get(r.userId).push(token);
|
|
3425
|
+
}
|
|
3426
|
+
for (const [k, v] of map.entries()) map.set(k, Array.from(new Set(v)));
|
|
3427
|
+
return map;
|
|
3428
|
+
}
|
|
3400
3429
|
async processAppChannel(args) {
|
|
3401
3430
|
const { cfg, evt, deliveryId } = args;
|
|
3402
3431
|
const tpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationTemplateId } });
|
|
3403
3432
|
if (!tpl) return;
|
|
3404
|
-
|
|
3405
|
-
if (
|
|
3406
|
-
this.
|
|
3433
|
+
let appUrlTpl = null;
|
|
3434
|
+
if (cfg.allowAppNotification && cfg.serviceEvent.allowAppNotification && cfg.webNotificationUrlTemplateId) {
|
|
3435
|
+
appUrlTpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationUrlTemplateId } });
|
|
3436
|
+
}
|
|
3437
|
+
const userIds = (args.recipients ?? []).map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0);
|
|
3438
|
+
if (!userIds.length) {
|
|
3439
|
+
this.logger.info("[NotificationService] APP: no userIds resolved");
|
|
3407
3440
|
return;
|
|
3408
3441
|
}
|
|
3409
|
-
const
|
|
3442
|
+
const title = renderTemplate(tpl.subject ?? "", evt.data ?? {});
|
|
3410
3443
|
const body = renderTemplate(tpl.bodyText ?? "", evt.data ?? {});
|
|
3411
|
-
const
|
|
3412
|
-
await this.
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3444
|
+
const route = appUrlTpl ? renderTemplate(appUrlTpl.bodyText ?? "", evt.data ?? {}) : null;
|
|
3445
|
+
const tokensMap = await this.getExpoTokensByUserIds(userIds);
|
|
3446
|
+
const expoProvider = new ExpoAppNotificationProvider(
|
|
3447
|
+
this.logger,
|
|
3448
|
+
cfg.serviceEvent.appNotificationApiUrl ?? void 0
|
|
3449
|
+
);
|
|
3450
|
+
const priority = cfg.priority === "PRIMARY" ? "high" : cfg.priority === "SECONDARY" ? "normal" : "default";
|
|
3451
|
+
const channelId = cfg.channelId ?? "default";
|
|
3452
|
+
const messages = [];
|
|
3453
|
+
const tokenToUserId = /* @__PURE__ */ new Map();
|
|
3454
|
+
for (const userId of userIds) {
|
|
3455
|
+
const tokens = tokensMap.get(userId) ?? [];
|
|
3456
|
+
for (const to of tokens) {
|
|
3457
|
+
messages.push({
|
|
3458
|
+
to,
|
|
3459
|
+
title: title || void 0,
|
|
3421
3460
|
body,
|
|
3422
|
-
|
|
3461
|
+
channelId,
|
|
3462
|
+
priority,
|
|
3463
|
+
data: route ? { route } : void 0
|
|
3423
3464
|
});
|
|
3424
|
-
|
|
3465
|
+
tokenToUserId.set(to, userId);
|
|
3425
3466
|
}
|
|
3467
|
+
}
|
|
3468
|
+
if (!messages.length) {
|
|
3469
|
+
await this.prisma.eventDeliveryItem.createMany({
|
|
3470
|
+
data: userIds.map((uid) => ({
|
|
3471
|
+
deliveryId,
|
|
3472
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3473
|
+
recipient: String(uid),
|
|
3474
|
+
messageContent: body,
|
|
3475
|
+
isSent: false,
|
|
3476
|
+
sentAt: null,
|
|
3477
|
+
error: "No deviceNotificationToken found for user"
|
|
3478
|
+
}))
|
|
3479
|
+
});
|
|
3480
|
+
return;
|
|
3481
|
+
}
|
|
3482
|
+
const expoRes = await expoProvider.sendBulk(messages);
|
|
3483
|
+
const tickets = Array.isArray(expoRes.tickets) ? expoRes.tickets : [];
|
|
3484
|
+
const now = /* @__PURE__ */ new Date();
|
|
3485
|
+
const rows = messages.map((m, idx) => {
|
|
3486
|
+
const t = tickets[idx];
|
|
3487
|
+
const isOk = t?.status === "ok";
|
|
3488
|
+
const errMsg = isOk ? null : t?.message ?? t?.details?.error ?? expoRes.error ?? "Expo push failed";
|
|
3489
|
+
const externalId = isOk ? t?.id ?? null : null;
|
|
3490
|
+
return {
|
|
3491
|
+
deliveryId,
|
|
3492
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3493
|
+
recipient: m.to,
|
|
3494
|
+
// store token or store userId; token is more debuggable
|
|
3495
|
+
messageContent: body,
|
|
3496
|
+
thirdPartyResponse: t ?? void 0,
|
|
3497
|
+
isSent: !!isOk,
|
|
3498
|
+
sentAt: isOk ? now : null,
|
|
3499
|
+
externalId,
|
|
3500
|
+
error: errMsg
|
|
3501
|
+
};
|
|
3426
3502
|
});
|
|
3503
|
+
await this.prisma.eventDeliveryItem.createMany({ data: rows });
|
|
3504
|
+
const usersWithToken = /* @__PURE__ */ new Set();
|
|
3505
|
+
for (const to of tokenToUserId.keys()) usersWithToken.add(tokenToUserId.get(to));
|
|
3506
|
+
const missingUsers = userIds.filter((u) => !usersWithToken.has(u));
|
|
3507
|
+
if (missingUsers.length) {
|
|
3508
|
+
await this.prisma.eventDeliveryItem.createMany({
|
|
3509
|
+
data: missingUsers.map((uid) => ({
|
|
3510
|
+
deliveryId,
|
|
3511
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3512
|
+
recipient: String(uid),
|
|
3513
|
+
messageContent: body,
|
|
3514
|
+
isSent: false,
|
|
3515
|
+
sentAt: null,
|
|
3516
|
+
error: "No deviceNotificationToken found for user"
|
|
3517
|
+
}))
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3427
3520
|
}
|
|
3428
3521
|
async processWebChannel(args) {
|
|
3429
3522
|
const { cfg, evt, deliveryId } = args;
|
package/dist/index.mjs
CHANGED
|
@@ -2319,6 +2319,42 @@ var uinConfigService = (uinDeps) => {
|
|
|
2319
2319
|
};
|
|
2320
2320
|
};
|
|
2321
2321
|
|
|
2322
|
+
// src/providers/app.provider.ts
|
|
2323
|
+
var ExpoAppNotificationProvider = class {
|
|
2324
|
+
constructor(logger = console, url = "https://api.expo.dev/v2/push/send") {
|
|
2325
|
+
this.logger = logger;
|
|
2326
|
+
this.url = url;
|
|
2327
|
+
}
|
|
2328
|
+
/**
|
|
2329
|
+
* Bulk send: one HTTP request with many messages.
|
|
2330
|
+
*/
|
|
2331
|
+
async sendBulk(messages) {
|
|
2332
|
+
const payload = (messages ?? []).filter((m) => !!m?.to);
|
|
2333
|
+
if (!payload.length) return { ok: true, tickets: [] };
|
|
2334
|
+
try {
|
|
2335
|
+
const res = await fetch(this.url, {
|
|
2336
|
+
method: "POST",
|
|
2337
|
+
headers: { "Content-Type": "application/json" },
|
|
2338
|
+
body: JSON.stringify(payload)
|
|
2339
|
+
});
|
|
2340
|
+
const data = await res.json().catch(() => ({}));
|
|
2341
|
+
if (!res.ok) {
|
|
2342
|
+
return { ok: false, error: `Expo HTTP ${res.status} ${res.statusText}`, meta: data };
|
|
2343
|
+
}
|
|
2344
|
+
const tickets = data?.data ?? [];
|
|
2345
|
+
const anyError = Array.isArray(tickets) && tickets.some((t) => t?.status === "error");
|
|
2346
|
+
return {
|
|
2347
|
+
ok: !anyError,
|
|
2348
|
+
tickets,
|
|
2349
|
+
meta: data
|
|
2350
|
+
};
|
|
2351
|
+
} catch (e) {
|
|
2352
|
+
this.logger.error("[ExpoAppNotificationProvider] sendBulk failed", e);
|
|
2353
|
+
return { ok: false, error: e?.message ?? String(e) };
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
};
|
|
2357
|
+
|
|
2322
2358
|
// src/types/notification.ts
|
|
2323
2359
|
var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
|
|
2324
2360
|
TemplateType2["EMAIL"] = "EMAIL";
|
|
@@ -2329,33 +2365,6 @@ var TemplateType = /* @__PURE__ */ ((TemplateType2) => {
|
|
|
2329
2365
|
return TemplateType2;
|
|
2330
2366
|
})(TemplateType || {});
|
|
2331
2367
|
|
|
2332
|
-
// src/providers/app.provider.ts
|
|
2333
|
-
var AppNotificationProvider = class {
|
|
2334
|
-
async send(args) {
|
|
2335
|
-
if (!args.recipient.appUserId) {
|
|
2336
|
-
return {
|
|
2337
|
-
ok: false,
|
|
2338
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2339
|
-
error: "Missing recipient.appUserId"
|
|
2340
|
-
};
|
|
2341
|
-
}
|
|
2342
|
-
try {
|
|
2343
|
-
const fake = { id: "push-abc", status: "queued" };
|
|
2344
|
-
return {
|
|
2345
|
-
ok: true,
|
|
2346
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2347
|
-
externalId: fake.id
|
|
2348
|
-
};
|
|
2349
|
-
} catch (err) {
|
|
2350
|
-
return {
|
|
2351
|
-
ok: false,
|
|
2352
|
-
provider: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
2353
|
-
error: err?.message ?? String(err)
|
|
2354
|
-
};
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
};
|
|
2358
|
-
|
|
2359
2368
|
// src/providers/email.providers.ts
|
|
2360
2369
|
import nodemailer from "nodemailer";
|
|
2361
2370
|
var EmailProvider = class {
|
|
@@ -3347,33 +3356,117 @@ var NotificationService = class {
|
|
|
3347
3356
|
});
|
|
3348
3357
|
}
|
|
3349
3358
|
}
|
|
3359
|
+
async getExpoTokensByUserIds(userIds) {
|
|
3360
|
+
if (!userIds.length) return /* @__PURE__ */ new Map();
|
|
3361
|
+
const rows = await this.prisma.session.findMany({
|
|
3362
|
+
where: {
|
|
3363
|
+
userId: { in: userIds },
|
|
3364
|
+
deviceNotificationToken: { not: null },
|
|
3365
|
+
logoutAt: null
|
|
3366
|
+
},
|
|
3367
|
+
select: { userId: true, deviceNotificationToken: true }
|
|
3368
|
+
});
|
|
3369
|
+
const map = /* @__PURE__ */ new Map();
|
|
3370
|
+
for (const r of rows) {
|
|
3371
|
+
const token = r.deviceNotificationToken?.trim();
|
|
3372
|
+
if (!token) continue;
|
|
3373
|
+
if (!map.has(r.userId)) map.set(r.userId, []);
|
|
3374
|
+
map.get(r.userId).push(token);
|
|
3375
|
+
}
|
|
3376
|
+
for (const [k, v] of map.entries()) map.set(k, Array.from(new Set(v)));
|
|
3377
|
+
return map;
|
|
3378
|
+
}
|
|
3350
3379
|
async processAppChannel(args) {
|
|
3351
3380
|
const { cfg, evt, deliveryId } = args;
|
|
3352
3381
|
const tpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationTemplateId } });
|
|
3353
3382
|
if (!tpl) return;
|
|
3354
|
-
|
|
3355
|
-
if (
|
|
3356
|
-
this.
|
|
3383
|
+
let appUrlTpl = null;
|
|
3384
|
+
if (cfg.allowAppNotification && cfg.serviceEvent.allowAppNotification && cfg.webNotificationUrlTemplateId) {
|
|
3385
|
+
appUrlTpl = await this.prisma.template.findUnique({ where: { id: cfg.appNotificationUrlTemplateId } });
|
|
3386
|
+
}
|
|
3387
|
+
const userIds = (args.recipients ?? []).map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0);
|
|
3388
|
+
if (!userIds.length) {
|
|
3389
|
+
this.logger.info("[NotificationService] APP: no userIds resolved");
|
|
3357
3390
|
return;
|
|
3358
3391
|
}
|
|
3359
|
-
const
|
|
3392
|
+
const title = renderTemplate(tpl.subject ?? "", evt.data ?? {});
|
|
3360
3393
|
const body = renderTemplate(tpl.bodyText ?? "", evt.data ?? {});
|
|
3361
|
-
const
|
|
3362
|
-
await this.
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3394
|
+
const route = appUrlTpl ? renderTemplate(appUrlTpl.bodyText ?? "", evt.data ?? {}) : null;
|
|
3395
|
+
const tokensMap = await this.getExpoTokensByUserIds(userIds);
|
|
3396
|
+
const expoProvider = new ExpoAppNotificationProvider(
|
|
3397
|
+
this.logger,
|
|
3398
|
+
cfg.serviceEvent.appNotificationApiUrl ?? void 0
|
|
3399
|
+
);
|
|
3400
|
+
const priority = cfg.priority === "PRIMARY" ? "high" : cfg.priority === "SECONDARY" ? "normal" : "default";
|
|
3401
|
+
const channelId = cfg.channelId ?? "default";
|
|
3402
|
+
const messages = [];
|
|
3403
|
+
const tokenToUserId = /* @__PURE__ */ new Map();
|
|
3404
|
+
for (const userId of userIds) {
|
|
3405
|
+
const tokens = tokensMap.get(userId) ?? [];
|
|
3406
|
+
for (const to of tokens) {
|
|
3407
|
+
messages.push({
|
|
3408
|
+
to,
|
|
3409
|
+
title: title || void 0,
|
|
3371
3410
|
body,
|
|
3372
|
-
|
|
3411
|
+
channelId,
|
|
3412
|
+
priority,
|
|
3413
|
+
data: route ? { route } : void 0
|
|
3373
3414
|
});
|
|
3374
|
-
|
|
3415
|
+
tokenToUserId.set(to, userId);
|
|
3375
3416
|
}
|
|
3417
|
+
}
|
|
3418
|
+
if (!messages.length) {
|
|
3419
|
+
await this.prisma.eventDeliveryItem.createMany({
|
|
3420
|
+
data: userIds.map((uid) => ({
|
|
3421
|
+
deliveryId,
|
|
3422
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3423
|
+
recipient: String(uid),
|
|
3424
|
+
messageContent: body,
|
|
3425
|
+
isSent: false,
|
|
3426
|
+
sentAt: null,
|
|
3427
|
+
error: "No deviceNotificationToken found for user"
|
|
3428
|
+
}))
|
|
3429
|
+
});
|
|
3430
|
+
return;
|
|
3431
|
+
}
|
|
3432
|
+
const expoRes = await expoProvider.sendBulk(messages);
|
|
3433
|
+
const tickets = Array.isArray(expoRes.tickets) ? expoRes.tickets : [];
|
|
3434
|
+
const now = /* @__PURE__ */ new Date();
|
|
3435
|
+
const rows = messages.map((m, idx) => {
|
|
3436
|
+
const t = tickets[idx];
|
|
3437
|
+
const isOk = t?.status === "ok";
|
|
3438
|
+
const errMsg = isOk ? null : t?.message ?? t?.details?.error ?? expoRes.error ?? "Expo push failed";
|
|
3439
|
+
const externalId = isOk ? t?.id ?? null : null;
|
|
3440
|
+
return {
|
|
3441
|
+
deliveryId,
|
|
3442
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3443
|
+
recipient: m.to,
|
|
3444
|
+
// store token or store userId; token is more debuggable
|
|
3445
|
+
messageContent: body,
|
|
3446
|
+
thirdPartyResponse: t ?? void 0,
|
|
3447
|
+
isSent: !!isOk,
|
|
3448
|
+
sentAt: isOk ? now : null,
|
|
3449
|
+
externalId,
|
|
3450
|
+
error: errMsg
|
|
3451
|
+
};
|
|
3376
3452
|
});
|
|
3453
|
+
await this.prisma.eventDeliveryItem.createMany({ data: rows });
|
|
3454
|
+
const usersWithToken = /* @__PURE__ */ new Set();
|
|
3455
|
+
for (const to of tokenToUserId.keys()) usersWithToken.add(tokenToUserId.get(to));
|
|
3456
|
+
const missingUsers = userIds.filter((u) => !usersWithToken.has(u));
|
|
3457
|
+
if (missingUsers.length) {
|
|
3458
|
+
await this.prisma.eventDeliveryItem.createMany({
|
|
3459
|
+
data: missingUsers.map((uid) => ({
|
|
3460
|
+
deliveryId,
|
|
3461
|
+
notificationType: "APP_NOTIFICATION" /* APP_NOTIFICATION */,
|
|
3462
|
+
recipient: String(uid),
|
|
3463
|
+
messageContent: body,
|
|
3464
|
+
isSent: false,
|
|
3465
|
+
sentAt: null,
|
|
3466
|
+
error: "No deviceNotificationToken found for user"
|
|
3467
|
+
}))
|
|
3468
|
+
});
|
|
3469
|
+
}
|
|
3377
3470
|
}
|
|
3378
3471
|
async processWebChannel(args) {
|
|
3379
3472
|
const { cfg, evt, deliveryId } = args;
|