@bobfrankston/mailx-imap 0.1.173 → 0.1.175

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 -15
  2. package/package.json +7 -7
package/index.js CHANGED
@@ -6417,10 +6417,22 @@ export class ImapManager extends EventEmitter {
6417
6417
  return 0;
6418
6418
  let changed = 0;
6419
6419
  let nextPageToken;
6420
- const now = Date.now();
6421
6420
  // Per-account persisted sync token (survives restarts). Empty means
6422
6421
  // we've never completed an initial sync for this account.
6423
6422
  let syncToken = this.db.getKv("contacts", accountId) || "";
6423
+ // One-shot full pass (Claude Code 2026-09-06): google rows written
6424
+ // before upsertGoogleContact never had their names refreshed, and an
6425
+ // incremental sync only returns people who changed since the last
6426
+ // token, so a stale name would sit there until that contact was next
6427
+ // edited in Google. Drop the token once per account; the marker is set
6428
+ // only after the full pass completes, so a failed pass is retried.
6429
+ const RESYNC_MARK = "name_resync_v1";
6430
+ const resyncKey = `resync:${accountId}`;
6431
+ if (syncToken && this.db.getKv("contacts", resyncKey) !== RESYNC_MARK) {
6432
+ console.log(` [contacts] ${accountId}: one-time full resync so google rows pick up their current names`);
6433
+ this.db.setKv("contacts", accountId, null);
6434
+ syncToken = "";
6435
+ }
6424
6436
  try {
6425
6437
  do {
6426
6438
  const params = new URLSearchParams({
@@ -6502,21 +6514,15 @@ export class ImapManager extends EventEmitter {
6502
6514
  const email = emailEntry.value?.toLowerCase();
6503
6515
  if (!email)
6504
6516
  continue;
6505
- const existing = this.db.searchContacts(email, 1);
6506
- const wasNew = !(existing.length > 0 && existing[0].email === email);
6507
- this.db.recordSentAddress(name, email);
6508
- if (wasNew)
6517
+ // One store method owns the google row — name,
6518
+ // card and identity together. The inline
6519
+ // recordSentAddress + UPDATE-by-email this
6520
+ // replaces never refreshed the name and failed on
6521
+ // the UNIQUE constraint whenever a discovered
6522
+ // duplicate existed; see upsertGoogleContact.
6523
+ // (Claude Code 2026-09-06)
6524
+ if (this.db.upsertGoogleContact(googleId, name, email, card))
6509
6525
  changed++;
6510
- try {
6511
- this.db.db.prepare(`UPDATE contacts SET source = 'google', google_id = ?, organization = ?, title = ?,
6512
- phone = ?, address = ?, website = ?, notes = ?, birthday = ?, updated_at = ?
6513
- WHERE email = ?`).run(googleId, card.organization, card.title, card.phone, card.address, card.website, card.notes, card.birthday, now, email);
6514
- }
6515
- catch (e) {
6516
- // Loud: a schema drift here silently reverts the
6517
- // address book to name+email only.
6518
- console.error(` [contacts] field update failed for ${email}: ${e?.message || e}`);
6519
- }
6520
6526
  }
6521
6527
  }
6522
6528
  }
@@ -6529,6 +6535,7 @@ export class ImapManager extends EventEmitter {
6529
6535
  syncToken = data.nextSyncToken;
6530
6536
  }
6531
6537
  } while (nextPageToken);
6538
+ this.db.setKv("contacts", resyncKey, RESYNC_MARK);
6532
6539
  console.log(` [contacts] ${accountId}: ${changed} change(s) (${syncToken ? "incremental" : "full"})`);
6533
6540
  }
6534
6541
  catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx-imap",
3
- "version": "0.1.173",
3
+ "version": "0.1.175",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -9,9 +9,9 @@
9
9
  },
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "@bobfrankston/mailx-types": "^0.1.81",
13
- "@bobfrankston/mailx-settings": "^0.1.75",
14
- "@bobfrankston/mailx-store": "^0.1.111",
12
+ "@bobfrankston/mailx-types": "^0.1.82",
13
+ "@bobfrankston/mailx-settings": "^0.1.76",
14
+ "@bobfrankston/mailx-store": "^0.1.113",
15
15
  "@bobfrankston/iflow-direct": "^0.1.68",
16
16
  "@bobfrankston/tcp-transport": "^0.1.8",
17
17
  "@bobfrankston/smtp-direct": "^0.1.9",
@@ -37,9 +37,9 @@
37
37
  },
38
38
  ".transformedSnapshot": {
39
39
  "dependencies": {
40
- "@bobfrankston/mailx-types": "^0.1.81",
41
- "@bobfrankston/mailx-settings": "^0.1.75",
42
- "@bobfrankston/mailx-store": "^0.1.111",
40
+ "@bobfrankston/mailx-types": "^0.1.82",
41
+ "@bobfrankston/mailx-settings": "^0.1.76",
42
+ "@bobfrankston/mailx-store": "^0.1.113",
43
43
  "@bobfrankston/iflow-direct": "^0.1.68",
44
44
  "@bobfrankston/tcp-transport": "^0.1.8",
45
45
  "@bobfrankston/smtp-direct": "^0.1.9",