@bobfrankston/mailx 1.0.107 → 1.0.109

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.107",
3
+ "version": "1.0.109",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -9,7 +9,7 @@ import * as fs from "node:fs";
9
9
  import { MailxDB } from "@bobfrankston/mailx-store";
10
10
  import { ImapManager } from "@bobfrankston/mailx-imap";
11
11
  import { createApiRouter } from "@bobfrankston/mailx-api";
12
- import { loadSettings, getConfigDir, getStorePath, getStorageInfo, initLocalConfig } from "@bobfrankston/mailx-settings";
12
+ import { loadSettings, loadAccountsAsync, getConfigDir, getStorePath, getStorageInfo, initLocalConfig } from "@bobfrankston/mailx-settings";
13
13
  import { ports } from "@bobfrankston/miscinfo";
14
14
  import { createServer } from "node:http";
15
15
  const PORT = ports.mailx;
@@ -46,13 +46,17 @@ const rootPkg = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, "..",
46
46
  const SERVER_VERSION = rootPkg.version;
47
47
  // ── Initialize ──
48
48
  initLocalConfig();
49
- const settings = loadSettings();
49
+ let settings = loadSettings();
50
50
  if (settings.accounts.length === 0) {
51
- console.log(" No accounts configured.");
52
- console.log(" See README for setup: https://github.com/BobFrankston/mailx#first-time-setup");
53
- console.log(" Quick: create ~/.mailx/settings.jsonc with your IMAP/SMTP account details.");
54
- console.log(" Or: place shared settings on OneDrive at home/.mailx/settings.jsonc");
55
- console.log(" Server will start at http://127.0.0.1:9333 configure accounts to begin.");
51
+ // Try cloud API fallback (Google Drive, OneDrive) if filesystem mount not available
52
+ const cloudAccounts = await loadAccountsAsync();
53
+ if (cloudAccounts.length > 0) {
54
+ settings = { ...settings, accounts: cloudAccounts };
55
+ console.log(` Loaded ${cloudAccounts.length} account(s) from cloud API`);
56
+ }
57
+ else {
58
+ console.log(" No accounts configured. Open http://127.0.0.1:9333 to set up.");
59
+ }
56
60
  }
57
61
  const dbDir = getConfigDir();
58
62
  const db = new MailxDB(dbDir);
@@ -4,7 +4,7 @@
4
4
  * when the cloud drive is not mounted locally.
5
5
  * Falls back to local cache when offline.
6
6
  */
7
- export type CloudProvider = "onedrive" | "gdrive" | "dropbox" | "local";
7
+ export type CloudProvider = "onedrive" | "gdrive" | "google" | "dropbox" | "local";
8
8
  export interface CloudFile {
9
9
  read(filePath: string): Promise<string | null>;
10
10
  write(filePath: string, content: string): Promise<boolean>;
@@ -275,6 +275,7 @@ export function getCloudProvider(provider) {
275
275
  write: oneDriveWrite,
276
276
  exists: oneDriveExists,
277
277
  };
278
+ case "google":
278
279
  case "gdrive":
279
280
  return {
280
281
  read: gDriveRead,
@@ -60,6 +60,8 @@ declare const DEFAULT_ALLOWLIST: {
60
60
  };
61
61
  /** Load account configs */
62
62
  export declare function loadAccounts(): AccountConfig[];
63
+ /** Load accounts with cloud API fallback (async — use when cloud settings may not be mounted) */
64
+ export declare function loadAccountsAsync(): Promise<AccountConfig[]>;
63
65
  /** Save account configs */
64
66
  export declare function saveAccounts(accounts: AccountConfig[]): void;
65
67
  /** Load preferences (shared + local overrides, with legacy fallback) */
@@ -391,6 +391,35 @@ function applyAccountOverrides(accounts) {
391
391
  }
392
392
  return accounts;
393
393
  }
394
+ /** Load accounts with cloud API fallback (async — use when cloud settings may not be mounted) */
395
+ export async function loadAccountsAsync() {
396
+ // Try sync first (filesystem)
397
+ const accounts = loadAccounts();
398
+ if (accounts.length > 0)
399
+ return accounts;
400
+ // Try cloud API fallback
401
+ if (pendingCloudConfig) {
402
+ console.log(" [cloud] Trying cloud API for accounts...");
403
+ const content = await cloudRead("accounts.jsonc");
404
+ if (content) {
405
+ const data = parseJsonc(content);
406
+ if (data?.accounts || Array.isArray(data)) {
407
+ const raw = data.accounts || data;
408
+ const globalName = data.name || "";
409
+ return applyAccountOverrides(raw.map((a) => normalizeAccount(a, globalName)));
410
+ }
411
+ }
412
+ // Also try legacy settings.jsonc
413
+ const legacy = await cloudRead("settings.jsonc");
414
+ if (legacy) {
415
+ const data = parseJsonc(legacy);
416
+ if (data?.accounts) {
417
+ return applyAccountOverrides(data.accounts.map((a) => normalizeAccount(a, data.name)));
418
+ }
419
+ }
420
+ }
421
+ return [];
422
+ }
394
423
  /** Save account configs */
395
424
  export function saveAccounts(accounts) {
396
425
  saveFile("accounts.jsonc", { accounts });