@bobfrankston/mailx-imap 0.1.48 → 0.1.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +22 -10
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -81,6 +81,14 @@ function toEmailAddress(addr) {
81
81
  address: addr?.address || ""
82
82
  };
83
83
  }
84
+ /** Coerce a message date to a finite epoch-ms for the `messages.date NOT NULL`
85
+ * column. An unparseable envelope date yields an *Invalid Date* — truthy and
86
+ * `instanceof Date`, but `.getTime()` is NaN, which binds as NULL and fails
87
+ * the constraint, aborting the whole sync batch. Default non-finite to now. */
88
+ function toFiniteDateMs(d) {
89
+ const ms = d instanceof Date ? d.getTime() : typeof d === "number" ? d : NaN;
90
+ return Number.isFinite(ms) ? ms : Date.now();
91
+ }
84
92
  /** Convert array of iflow addresses */
85
93
  function toEmailAddresses(addrs) {
86
94
  if (!addrs)
@@ -963,7 +971,7 @@ export class ImapManager extends EventEmitter {
963
971
  messageId: msg.messageId || "",
964
972
  inReplyTo: msg.inReplyTo || "",
965
973
  references: [],
966
- date: msg.date instanceof Date ? msg.date.getTime() : (typeof msg.date === "number" ? msg.date : Date.now()),
974
+ date: toFiniteDateMs(msg.date),
967
975
  subject: msg.subject || "",
968
976
  from: toEmailAddress(msg.from?.[0] || {}),
969
977
  to: toEmailAddresses(msg.to || []),
@@ -1475,7 +1483,7 @@ export class ImapManager extends EventEmitter {
1475
1483
  messageId: msg.messageId || "",
1476
1484
  inReplyTo: msg.inReplyTo || "",
1477
1485
  references: [],
1478
- date: msg.date instanceof Date ? msg.date.getTime() : (typeof msg.date === "number" ? msg.date : Date.now()),
1486
+ date: toFiniteDateMs(msg.date),
1479
1487
  subject: msg.subject || "",
1480
1488
  from: toEmailAddress(msg.from?.[0] || {}),
1481
1489
  to: toEmailAddresses(msg.to || []),
@@ -4301,16 +4309,20 @@ export class ImapManager extends EventEmitter {
4301
4309
  const res = await fetch(url, {
4302
4310
  headers: { Authorization: `Bearer ${token}` },
4303
4311
  });
4304
- if (res.status === 410) {
4305
- // Sync token expired (Google retains tokens for ~7 days).
4306
- // Drop the stored token and recurse for a full sync — the
4307
- // in-flight guard is on syncGoogleContacts (the public
4308
- // wrapper), not Impl, so recursion is safe.
4309
- this.db.setKv("contacts", accountId, null);
4310
- return this.syncGoogleContactsImpl(accountId);
4311
- }
4312
4312
  if (!res.ok) {
4313
4313
  const err = await res.text();
4314
+ // Expired sync token. The People API returns HTTP 400
4315
+ // FAILED_PRECONDITION with reason EXPIRED_SYNC_TOKEN
4316
+ // (older docs / older behavior said 410 — handle both
4317
+ // by inspecting the body). The documented recovery is:
4318
+ // drop the token and re-call WITHOUT it (full sync).
4319
+ // The `syncToken` guard prevents infinite recursion if a
4320
+ // tokenless full sync itself somehow returns this.
4321
+ if (syncToken && /EXPIRED_SYNC_TOKEN|sync token is expired/i.test(err)) {
4322
+ console.log(` [contacts] ${accountId}: sync token expired — clearing for full resync`);
4323
+ this.db.setKv("contacts", accountId, null);
4324
+ return this.syncGoogleContactsImpl(accountId);
4325
+ }
4314
4326
  console.error(` [contacts] API error for ${accountId}: ${res.status} ${err}`);
4315
4327
  return changed;
4316
4328
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-imap",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -11,7 +11,7 @@
11
11
  "dependencies": {
12
12
  "@bobfrankston/mailx-types": "^0.1.14",
13
13
  "@bobfrankston/mailx-settings": "^0.1.17",
14
- "@bobfrankston/mailx-store": "^0.1.27",
14
+ "@bobfrankston/mailx-store": "^0.1.28",
15
15
  "@bobfrankston/iflow-direct": "^0.1.50",
16
16
  "@bobfrankston/tcp-transport": "^0.1.6",
17
17
  "@bobfrankston/smtp-direct": "^0.1.8",
@@ -39,7 +39,7 @@
39
39
  "dependencies": {
40
40
  "@bobfrankston/mailx-types": "^0.1.14",
41
41
  "@bobfrankston/mailx-settings": "^0.1.17",
42
- "@bobfrankston/mailx-store": "^0.1.27",
42
+ "@bobfrankston/mailx-store": "^0.1.28",
43
43
  "@bobfrankston/iflow-direct": "^0.1.50",
44
44
  "@bobfrankston/tcp-transport": "^0.1.6",
45
45
  "@bobfrankston/smtp-direct": "^0.1.8",