@objectstack/service-messaging 10.0.0 → 10.3.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.cjs +39 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -11
- package/dist/index.d.ts +139 -11
- package/dist/index.js +39 -18
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -963,6 +963,19 @@ function classifyDeliveryAttempt(result, errorClass, attemptsSoFar, now = Date.n
|
|
|
963
963
|
return { success: false, error: result.error, nextAttemptAt: now + delay };
|
|
964
964
|
}
|
|
965
965
|
|
|
966
|
+
// src/audit-timestamp.ts
|
|
967
|
+
function toEpochMs(value) {
|
|
968
|
+
if (typeof value === "number") return value;
|
|
969
|
+
if (value instanceof Date) return value.getTime();
|
|
970
|
+
if (typeof value === "string") {
|
|
971
|
+
const parsed = Date.parse(value);
|
|
972
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
973
|
+
const numeric = Number(value);
|
|
974
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
975
|
+
}
|
|
976
|
+
return 0;
|
|
977
|
+
}
|
|
978
|
+
|
|
966
979
|
// src/sql-outbox.ts
|
|
967
980
|
var DELIVERY_OBJECT = "sys_notification_delivery";
|
|
968
981
|
var SqlNotificationOutbox = class {
|
|
@@ -981,7 +994,7 @@ var SqlNotificationOutbox = class {
|
|
|
981
994
|
const existing = await this.engine.findOne(this.objectName, { where: dedup, fields: ["id"] });
|
|
982
995
|
if (existing?.id) return String(existing.id);
|
|
983
996
|
const id = (0, import_node_crypto.randomUUID)();
|
|
984
|
-
const now = Date
|
|
997
|
+
const now = /* @__PURE__ */ new Date();
|
|
985
998
|
const row = {
|
|
986
999
|
id,
|
|
987
1000
|
notification_id: input.notificationId,
|
|
@@ -1142,8 +1155,8 @@ var SqlNotificationOutbox = class {
|
|
|
1142
1155
|
lastAttemptedAt: r.last_attempted_at ?? void 0,
|
|
1143
1156
|
error: r.error ?? void 0,
|
|
1144
1157
|
digestKey: r.digest_key ?? void 0,
|
|
1145
|
-
createdAt: r.created_at,
|
|
1146
|
-
updatedAt: r.updated_at
|
|
1158
|
+
createdAt: toEpochMs(r.created_at),
|
|
1159
|
+
updatedAt: toEpochMs(r.updated_at)
|
|
1147
1160
|
};
|
|
1148
1161
|
}
|
|
1149
1162
|
};
|
|
@@ -1272,8 +1285,11 @@ var HttpDelivery = import_data.ObjectSchema.create({
|
|
|
1272
1285
|
response_code: import_data.Field.number({ label: "HTTP Status", required: false }),
|
|
1273
1286
|
response_body: import_data.Field.textarea({ label: "Response Body (capped)", required: false }),
|
|
1274
1287
|
error: import_data.Field.textarea({ label: "Error", required: false }),
|
|
1275
|
-
|
|
1276
|
-
|
|
1288
|
+
// Builtin audit columns are native TIMESTAMP columns (Postgres/MySQL),
|
|
1289
|
+
// so declare them `datetime` and write `Date`s (not epoch-ms numbers,
|
|
1290
|
+
// which a real timestamp column rejects). See SqlHttpOutbox.
|
|
1291
|
+
created_at: import_data.Field.datetime({ label: "Created At", required: true }),
|
|
1292
|
+
updated_at: import_data.Field.datetime({ label: "Updated At", required: true })
|
|
1277
1293
|
},
|
|
1278
1294
|
indexes: [
|
|
1279
1295
|
{ fields: ["source", "dedup_key"], unique: true },
|
|
@@ -1303,7 +1319,7 @@ var SqlHttpOutbox = class {
|
|
|
1303
1319
|
});
|
|
1304
1320
|
if (existing?.id) return existing.id;
|
|
1305
1321
|
const id = (0, import_node_crypto2.randomUUID)();
|
|
1306
|
-
const now = Date
|
|
1322
|
+
const now = /* @__PURE__ */ new Date();
|
|
1307
1323
|
const row = {
|
|
1308
1324
|
id,
|
|
1309
1325
|
source: input.source,
|
|
@@ -1472,8 +1488,8 @@ var SqlHttpOutbox = class {
|
|
|
1472
1488
|
responseCode: r.response_code ?? void 0,
|
|
1473
1489
|
responseBody: r.response_body ?? void 0,
|
|
1474
1490
|
error: r.error ?? void 0,
|
|
1475
|
-
createdAt: r.created_at,
|
|
1476
|
-
updatedAt: r.updated_at
|
|
1491
|
+
createdAt: toEpochMs(r.created_at),
|
|
1492
|
+
updatedAt: toEpochMs(r.updated_at)
|
|
1477
1493
|
};
|
|
1478
1494
|
}
|
|
1479
1495
|
};
|
|
@@ -1947,10 +1963,10 @@ function stableNodeOffset2(nodeId, partitionCount) {
|
|
|
1947
1963
|
// src/retention.ts
|
|
1948
1964
|
var DEFAULT_NOTIFICATION_RETENTION_DAYS = 90;
|
|
1949
1965
|
var DEFAULT_RETENTION_TARGETS = [
|
|
1950
|
-
{ object: RECEIPT_OBJECT, tsField: "created_at"
|
|
1951
|
-
{ object: INBOX_OBJECT, tsField: "created_at"
|
|
1952
|
-
{ object: DELIVERY_OBJECT, tsField: "created_at"
|
|
1953
|
-
{ object: NOTIFICATION_EVENT_OBJECT, tsField: "created_at"
|
|
1966
|
+
{ object: RECEIPT_OBJECT, tsField: "created_at" },
|
|
1967
|
+
{ object: INBOX_OBJECT, tsField: "created_at" },
|
|
1968
|
+
{ object: DELIVERY_OBJECT, tsField: "created_at" },
|
|
1969
|
+
{ object: NOTIFICATION_EVENT_OBJECT, tsField: "created_at" }
|
|
1954
1970
|
];
|
|
1955
1971
|
var NotificationRetention = class {
|
|
1956
1972
|
constructor(opts) {
|
|
@@ -1973,14 +1989,15 @@ var NotificationRetention = class {
|
|
|
1973
1989
|
this.opts.logger.warn(`[messaging] retention: invalid retentionDays=${retentionDays}; prune skipped`);
|
|
1974
1990
|
return [];
|
|
1975
1991
|
}
|
|
1976
|
-
const
|
|
1977
|
-
const cutoffIso = new Date(cutoffMs).toISOString();
|
|
1992
|
+
const cutoffIso = new Date(this.now() - retentionDays * 864e5).toISOString();
|
|
1978
1993
|
const outcomes = [];
|
|
1979
1994
|
for (const t of this.targets) {
|
|
1980
|
-
const cutoff = t.format === "epoch" ? cutoffMs : cutoffIso;
|
|
1981
1995
|
try {
|
|
1982
1996
|
const res = await data.delete(t.object, {
|
|
1983
|
-
|
|
1997
|
+
// ISO-8601 cutoff for every target: `created_at` is a native
|
|
1998
|
+
// timestamp column, which rejects a bare epoch-ms number on
|
|
1999
|
+
// Postgres. The driver coerces this per dialect on the way down.
|
|
2000
|
+
where: { [t.tsField]: { $lt: cutoffIso } },
|
|
1984
2001
|
multi: true,
|
|
1985
2002
|
// System context: retention is an operator policy that spans
|
|
1986
2003
|
// tenants, so it must not be scoped by the caller's RLS.
|
|
@@ -2332,8 +2349,12 @@ var NotificationDelivery = import_data4.ObjectSchema.create({
|
|
|
2332
2349
|
next_attempt_at: import_data4.Field.number({ label: "Next Attempt At (ms)" }),
|
|
2333
2350
|
last_attempted_at: import_data4.Field.number({ label: "Last Attempted At (ms)" }),
|
|
2334
2351
|
error: import_data4.Field.textarea({ label: "Error" }),
|
|
2335
|
-
|
|
2336
|
-
updated_at
|
|
2352
|
+
// Builtin audit columns: the SQL driver provisions `created_at` /
|
|
2353
|
+
// `updated_at` as native TIMESTAMP columns (Postgres/MySQL), so they are
|
|
2354
|
+
// declared `datetime` and written as `Date`s — a bare epoch-ms number is
|
|
2355
|
+
// rejected by a real timestamp column. See SqlNotificationOutbox.
|
|
2356
|
+
created_at: import_data4.Field.datetime({ label: "Created At", readonly: true }),
|
|
2357
|
+
updated_at: import_data4.Field.datetime({ label: "Updated At" })
|
|
2337
2358
|
},
|
|
2338
2359
|
indexes: [
|
|
2339
2360
|
// Dedup: one delivery per (event, recipient, channel).
|