@bobfrankston/mailx-settings 0.1.24 → 0.1.26
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/cloud.d.ts.map +1 -1
- package/cloud.js +46 -0
- package/index.d.ts.map +1 -1
- package/index.js +20 -2
- package/package.json +1 -1
package/cloud.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;
|
|
1
|
+
{"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AA+RH;;;;;;;;;oDASoD;AACpD,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA8BnF;AAcD;;;;;;;;;;;;;;;;;6CAiB6C;AAC7C,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBvE;AA6FD,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,SAAS;IACtB,kFAAkF;IAClF,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC/C,uGAAuG;IACvG,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,8BAA8B;IAC9B,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAuBtF;AAED;;;;2DAI2D;AAC3D,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAoBvG"}
|
package/cloud.js
CHANGED
|
@@ -75,6 +75,7 @@ function archiveStaleTokenDirs(activeDirs) {
|
|
|
75
75
|
return;
|
|
76
76
|
const archiveRoot = path.join(tokensDir, ".archive");
|
|
77
77
|
let archived = 0;
|
|
78
|
+
let migrated = 0;
|
|
78
79
|
try {
|
|
79
80
|
for (const entry of fs.readdirSync(tokensDir)) {
|
|
80
81
|
// Preserve: special sub-dirs, the archive itself, all active entries.
|
|
@@ -92,6 +93,48 @@ function archiveStaleTokenDirs(activeDirs) {
|
|
|
92
93
|
catch {
|
|
93
94
|
continue;
|
|
94
95
|
}
|
|
96
|
+
// MIGRATE before archive: older builds wrote the token dir with
|
|
97
|
+
// different casing (Pascal vs. lowercase) or different dot handling.
|
|
98
|
+
// If this dir's lowercased name matches an active dir, it's the
|
|
99
|
+
// same account's tokens under an obsolete naming convention —
|
|
100
|
+
// moving the token file to the canonical dir lets the user keep
|
|
101
|
+
// signing in instead of being thrown back to Google's consent
|
|
102
|
+
// screen for the third time (Bob 2026-05-26 "why authenticating
|
|
103
|
+
// again"). The migration preserves the oauth-token.json file; the
|
|
104
|
+
// now-empty source dir falls through to archive below.
|
|
105
|
+
const entryLc = entry.toLowerCase();
|
|
106
|
+
if (activeDirs.has(entryLc) && entryLc !== entry) {
|
|
107
|
+
const tokenFile = path.join(src, "oauth-token.json");
|
|
108
|
+
if (fs.existsSync(tokenFile)) {
|
|
109
|
+
const dstDir = path.join(tokensDir, entryLc);
|
|
110
|
+
const dstTokenFile = path.join(dstDir, "oauth-token.json");
|
|
111
|
+
try {
|
|
112
|
+
if (fs.existsSync(dstTokenFile)) {
|
|
113
|
+
// Target dir already has a token — pick the newer one.
|
|
114
|
+
const srcMtime = fs.statSync(tokenFile).mtimeMs;
|
|
115
|
+
const dstMtime = fs.statSync(dstTokenFile).mtimeMs;
|
|
116
|
+
if (srcMtime > dstMtime) {
|
|
117
|
+
fs.copyFileSync(tokenFile, dstTokenFile);
|
|
118
|
+
console.log(` [cloud] Migrated newer token from ${entry} → ${entryLc} (replacing older)`);
|
|
119
|
+
migrated++;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
console.log(` [cloud] Skipped migrating ${entry} → ${entryLc} (target token is newer)`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
fs.mkdirSync(dstDir, { recursive: true });
|
|
127
|
+
fs.copyFileSync(tokenFile, dstTokenFile);
|
|
128
|
+
console.log(` [cloud] Migrated token from ${entry} → ${entryLc}`);
|
|
129
|
+
migrated++;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
console.error(` [cloud] Token migration ${entry} → ${entryLc} failed: ${e?.message || e}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Fall through to archive — the source dir is now an artifact.
|
|
137
|
+
}
|
|
95
138
|
const stamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
96
139
|
const dst = path.join(archiveRoot, `${stamp}-${entry}`);
|
|
97
140
|
try {
|
|
@@ -108,6 +151,9 @@ function archiveStaleTokenDirs(activeDirs) {
|
|
|
108
151
|
catch (e) {
|
|
109
152
|
console.error(` [cloud] tokens dir scan failed: ${e?.message || e}`);
|
|
110
153
|
}
|
|
154
|
+
if (migrated > 0) {
|
|
155
|
+
console.log(` [cloud] Stale token cleanup: ${migrated} token(s) migrated to canonical dirs`);
|
|
156
|
+
}
|
|
111
157
|
if (archived > 0) {
|
|
112
158
|
console.log(` [cloud] Stale token cleanup: ${archived} dir(s) archived to tokens/.archive/`);
|
|
113
159
|
}
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAyG5G,QAAA,MAAM,SAAS,QAA4E,CAAC;AAiE5F,qFAAqF;AACrF,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAE/G,wBAAgB,YAAY,CAAC,EAAE,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAM/D;AAOD,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAA2B;AAU7E,iBAAS,YAAY,IAAI,MAAM,CAgB9B;AAOD,sEAAsE;AACtE,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAyG5G,QAAA,MAAM,SAAS,QAA4E,CAAC;AAiE5F,qFAAqF;AACrF,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,CAAC;AAE/G,wBAAgB,YAAY,CAAC,EAAE,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAM/D;AAOD,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAA2B;AAU7E,iBAAS,YAAY,IAAI,MAAM,CAgB9B;AAOD,sEAAsE;AACtE,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgDxE;AAED;;qCAEqC;AACrC,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCjF;AAyBD,2CAA2C;AAC3C,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,4CAA4C;AAC5C,wBAAgB,cAAc,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CA+B3L;AAuID;;;;;;;;;;;;4EAY4E;AAC5E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcpD;AAED;;;0EAG0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;qDAEqD;AACrD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,aAAa,CA6DzH;AAMD,QAAA,MAAM,mBAAmB;;eAEE,QAAQ,GAAG,MAAM,GAAG,OAAO;gBAC3B,OAAO,GAAG,QAAQ;;;;;;;;;;;;;;;;;;;;CAoB5C,CAAC;AAEF,QAAA,MAAM,oBAAoB,EAAE,oBAS3B,CAAC;AAEF,QAAA,MAAM,iBAAiB;aACJ,MAAM,EAAE;aACR,MAAM,EAAE;gBACL,MAAM,EAAE;oBAOJ,MAAM,EAAE;oBACR,MAAM,EAAE;CACjC,CAAC;AAIF,2BAA2B;AAC3B,wBAAgB,YAAY,IAAI,aAAa,EAAE,CA4C9C;AAoCD;;;;0CAI0C;AAC1C,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAuBlE;AAED;;;;;;;;;;;;;;;iDAeiD;AACjD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CA8ChF;AAED,2BAA2B;AAC3B;;;oEAGoE;AACpE,wBAAsB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC3E;AAED;;;wEAGwE;AACxE,wBAAgB,QAAQ,IAAI,MAAM,CAWjC;AAED;;4DAE4D;AAC5D,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB1D;AAED;;;;;uEAKuE;AACvE,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmB7D;AAED;;;;;;kCAMkC;AAClC,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAa9D;AAED;;;;;0CAK0C;AAC1C,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAYlE;AAED,wEAAwE;AACxE,wBAAgB,eAAe,IAAI,OAAO,mBAAmB,CAkC5D;AAED,uBAAuB;AACvB,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,CAEhD;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,IAAI,oBAAoB,CAGvD;AAED,iCAAiC;AACjC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAIrE;AAED,qCAAqC;AACrC,wBAAgB,aAAa,IAAI,OAAO,iBAAiB,CAExD;AAED,4EAA4E;AAC5E,wBAAsB,aAAa,CAAC,IAAI,EAAE,OAAO,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBjF;AAgCD;;;oEAGoE;AACpE,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAYtD;AAED;sDACsD;AACtD,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBjE;AAcD,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,aAAa,CA0B5C;AAyBD,wBAAsB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzE;AAED,oCAAoC;AACpC,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,qDAAqD;AACrD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wCAAwC;AACxC,OAAO,EAAE,YAAY,EAAE,CAAC;AAKxB,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAkB5E;AAED;;;mFAGmF;AACnF,wBAAsB,eAAe,CAAC,QAAQ,GAAE,QAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAclF;AAED,QAAA,MAAM,gBAAgB,EAAE,aAMvB,CAAC;AAEF,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED,uEAAuE;AACvE,wBAAgB,WAAW,IAAI,OAAO,CAGrC;AAED,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,SAAS,EAAE,CAAC;AAErG;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDlE"}
|
package/index.js
CHANGED
|
@@ -264,7 +264,18 @@ export async function cloudRead(filename) {
|
|
|
264
264
|
return null;
|
|
265
265
|
}
|
|
266
266
|
console.log(` [cloud] Reading ${filename} via ${pendingCloudConfig.provider} API...`);
|
|
267
|
-
|
|
267
|
+
// Wall-clock timeout: a hung gdrive fetch used to block every other IPC
|
|
268
|
+
// (the service main thread serialised everything behind whatever was
|
|
269
|
+
// in flight). One stuck `getUserDict` once held the dispatcher for 101 s
|
|
270
|
+
// — saveDraft / getAccounts / searchContacts all timed out client-side
|
|
271
|
+
// before the gdrive call eventually errored with "fetch failed". 15 s is
|
|
272
|
+
// plenty for a healthy round-trip; anything longer means the network /
|
|
273
|
+
// OAuth refresh / Google side is wedged and we should fall back to the
|
|
274
|
+
// local cache instead of holding up the UI.
|
|
275
|
+
const content = await Promise.race([
|
|
276
|
+
provider.read(filename),
|
|
277
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`cloudRead ${filename}: 15s timeout`)), 15_000)),
|
|
278
|
+
]);
|
|
268
279
|
if (content) {
|
|
269
280
|
setCloudError(null);
|
|
270
281
|
// Cache locally
|
|
@@ -305,7 +316,14 @@ export async function cloudWrite(filename, content) {
|
|
|
305
316
|
throw new Error(err);
|
|
306
317
|
}
|
|
307
318
|
try {
|
|
308
|
-
|
|
319
|
+
// 30 s timeout — uploads run slightly longer than reads (round-trip
|
|
320
|
+
// for resumable upload init + content body), so the cap is bigger
|
|
321
|
+
// than cloudRead's 15 s, but still bounded. Same reason: a wedged
|
|
322
|
+
// gdrive call must not freeze the IPC dispatcher.
|
|
323
|
+
await Promise.race([
|
|
324
|
+
provider.write(filename, content),
|
|
325
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`cloudWrite ${filename}: 30s timeout`)), 30_000)),
|
|
326
|
+
]);
|
|
309
327
|
setCloudError(null);
|
|
310
328
|
}
|
|
311
329
|
catch (e) {
|