@haex-space/vault-sdk 3.1.0 → 3.2.2

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 (45) hide show
  1. package/dist/{client-C0DPNG62.d.mts → client-GeColu97.d.mts} +263 -2
  2. package/dist/{client-B_B6rLIw.d.ts → client-z1jTcuQE.d.ts} +263 -2
  3. package/dist/index.d.mts +76 -6
  4. package/dist/index.d.ts +76 -6
  5. package/dist/index.js +244 -47
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +241 -48
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/node.d.mts +1 -1
  10. package/dist/node.d.ts +1 -1
  11. package/dist/nuxt.js +16 -6
  12. package/dist/nuxt.js.map +1 -1
  13. package/dist/nuxt.mjs +16 -6
  14. package/dist/nuxt.mjs.map +1 -1
  15. package/dist/react.d.mts +2 -2
  16. package/dist/react.d.ts +2 -2
  17. package/dist/react.js +237 -46
  18. package/dist/react.js.map +1 -1
  19. package/dist/react.mjs +237 -46
  20. package/dist/react.mjs.map +1 -1
  21. package/dist/runtime/nuxt.plugin.client.d.mts +2 -2
  22. package/dist/runtime/nuxt.plugin.client.d.ts +2 -2
  23. package/dist/runtime/nuxt.plugin.client.js +237 -50
  24. package/dist/runtime/nuxt.plugin.client.js.map +1 -1
  25. package/dist/runtime/nuxt.plugin.client.mjs +237 -50
  26. package/dist/runtime/nuxt.plugin.client.mjs.map +1 -1
  27. package/dist/svelte.d.mts +2 -2
  28. package/dist/svelte.d.ts +2 -2
  29. package/dist/svelte.js +237 -46
  30. package/dist/svelte.js.map +1 -1
  31. package/dist/svelte.mjs +237 -46
  32. package/dist/svelte.mjs.map +1 -1
  33. package/dist/{types-DmCSegdY.d.mts → types-CDMBvvjl.d.mts} +2 -0
  34. package/dist/{types-DmCSegdY.d.ts → types-CDMBvvjl.d.ts} +2 -0
  35. package/dist/vite.js +15 -5
  36. package/dist/vite.js.map +1 -1
  37. package/dist/vite.mjs +15 -5
  38. package/dist/vite.mjs.map +1 -1
  39. package/dist/vue.d.mts +2 -2
  40. package/dist/vue.d.ts +2 -2
  41. package/dist/vue.js +237 -46
  42. package/dist/vue.js.map +1 -1
  43. package/dist/vue.mjs +237 -46
  44. package/dist/vue.mjs.map +1 -1
  45. package/package.json +1 -1
package/dist/react.mjs CHANGED
@@ -648,6 +648,40 @@ var SHELL_COMMANDS = {
648
648
  close: "extension_shell_close"
649
649
  };
650
650
 
651
+ // src/commands/passwords.ts
652
+ var PASSWORD_COMMANDS = {
653
+ /** List items (no secrets) within the extension's tag scope */
654
+ list: "extension_password_list",
655
+ /** Read full item including secrets, by id */
656
+ read: "extension_password_read",
657
+ /** Create item — must include >=1 tag in scope */
658
+ create: "extension_password_create",
659
+ /** Update item — keeps >=1 tag in scope */
660
+ update: "extension_password_update",
661
+ /** Delete item — must be in scope */
662
+ delete: "extension_password_delete"
663
+ };
664
+
665
+ // src/commands/mail.ts
666
+ var MAIL_COMMANDS = {
667
+ /** LIST mailboxes + optional STATUS counts */
668
+ listMailboxes: "extension_mail_list_mailboxes",
669
+ /** Lightweight envelope fetch for list views */
670
+ fetchEnvelopes: "extension_mail_fetch_envelopes",
671
+ /** Full message fetch (envelope + body + attachment metadata) */
672
+ fetchMessage: "extension_mail_fetch_message",
673
+ /** Set or unset IMAP flags on a UID set */
674
+ setFlags: "extension_mail_set_flags",
675
+ /** MOVE messages between mailboxes (COPY+EXPUNGE fallback) */
676
+ moveMessages: "extension_mail_move_messages",
677
+ /** APPEND a base64-encoded RFC822 message into a mailbox */
678
+ appendMessage: "extension_mail_append_message",
679
+ /** SMTP send. Returns the assigned Message-ID. */
680
+ sendMessage: "extension_mail_send_message",
681
+ /** Build RFC822 bytes without sending (for Drafts via APPEND) */
682
+ buildRfc822: "extension_mail_build_rfc822"
683
+ };
684
+
651
685
  // src/api/storage.ts
652
686
  var StorageAPI = class {
653
687
  constructor(client) {
@@ -671,6 +705,12 @@ var StorageAPI = class {
671
705
  };
672
706
 
673
707
  // src/api/database.ts
708
+ function quoteIdent(identifier) {
709
+ if (identifier.startsWith('"') && identifier.endsWith('"')) {
710
+ return identifier;
711
+ }
712
+ return `"${identifier.replace(/"/g, '""')}"`;
713
+ }
674
714
  var DatabaseAPI = class {
675
715
  constructor(client) {
676
716
  this.client = client;
@@ -701,11 +741,11 @@ var DatabaseAPI = class {
701
741
  });
702
742
  }
703
743
  async createTable(tableName, columns) {
704
- const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
744
+ const query = `CREATE TABLE IF NOT EXISTS ${quoteIdent(tableName)} (${columns})`;
705
745
  await this.execute(query);
706
746
  }
707
747
  async dropTable(tableName) {
708
- const query = `DROP TABLE IF EXISTS ${tableName}`;
748
+ const query = `DROP TABLE IF EXISTS ${quoteIdent(tableName)}`;
709
749
  await this.execute(query);
710
750
  }
711
751
  /**
@@ -734,18 +774,17 @@ var DatabaseAPI = class {
734
774
  async insert(tableName, data) {
735
775
  const keys = Object.keys(data);
736
776
  const values = Object.values(data);
777
+ const quotedCols = keys.map(quoteIdent).join(", ");
737
778
  const placeholders = keys.map(() => "?").join(", ");
738
- const query = `INSERT INTO ${tableName} (${keys.join(
739
- ", "
740
- )}) VALUES (${placeholders})`;
779
+ const query = `INSERT INTO ${quoteIdent(tableName)} (${quotedCols}) VALUES (${placeholders})`;
741
780
  const result = await this.execute(query, values);
742
781
  return result.lastInsertId ?? -1;
743
782
  }
744
783
  async update(tableName, data, where, whereParams) {
745
784
  const keys = Object.keys(data);
746
785
  const values = Object.values(data);
747
- const setClause = keys.map((key) => `${key} = ?`).join(", ");
748
- const query = `UPDATE ${tableName} SET ${setClause} WHERE ${where}`;
786
+ const setClause = keys.map((key) => `${quoteIdent(key)} = ?`).join(", ");
787
+ const query = `UPDATE ${quoteIdent(tableName)} SET ${setClause} WHERE ${where}`;
749
788
  const result = await this.execute(query, [
750
789
  ...values,
751
790
  ...whereParams || []
@@ -753,12 +792,12 @@ var DatabaseAPI = class {
753
792
  return result.rowsAffected;
754
793
  }
755
794
  async delete(tableName, where, whereParams) {
756
- const query = `DELETE FROM ${tableName} WHERE ${where}`;
795
+ const query = `DELETE FROM ${quoteIdent(tableName)} WHERE ${where}`;
757
796
  const result = await this.execute(query, whereParams);
758
797
  return result.rowsAffected;
759
798
  }
760
799
  async count(tableName, where, whereParams) {
761
- const query = where ? `SELECT COUNT(*) as count FROM ${tableName} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${tableName}`;
800
+ const query = where ? `SELECT COUNT(*) as count FROM ${quoteIdent(tableName)} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${quoteIdent(tableName)}`;
762
801
  const result = await this.queryOne(query, whereParams);
763
802
  return result?.count ?? 0;
764
803
  }
@@ -1580,6 +1619,140 @@ var ShellAPI = class {
1580
1619
  }
1581
1620
  };
1582
1621
 
1622
+ // src/api/passwords.ts
1623
+ var PasswordsAPI = class {
1624
+ constructor(client) {
1625
+ this.client = client;
1626
+ }
1627
+ /** List items in scope — summaries only, no secrets. */
1628
+ async listAsync() {
1629
+ return this.client.request(
1630
+ PASSWORD_COMMANDS.list,
1631
+ {}
1632
+ );
1633
+ }
1634
+ /** Read a single item by id with full secrets. */
1635
+ async readAsync(itemId) {
1636
+ return this.client.request(PASSWORD_COMMANDS.read, {
1637
+ itemId
1638
+ });
1639
+ }
1640
+ /**
1641
+ * Create a new password item. `input.tags` must contain at least one
1642
+ * tag within the extension's permission scope, otherwise the write
1643
+ * is rejected as a security violation.
1644
+ *
1645
+ * Returns the new item id.
1646
+ */
1647
+ async createAsync(input) {
1648
+ return this.client.request(PASSWORD_COMMANDS.create, { input });
1649
+ }
1650
+ /**
1651
+ * Update an existing item. The item must already be in scope, and
1652
+ * the new tag set must keep at least one tag in scope (extensions
1653
+ * cannot orphan an item out of their own reach).
1654
+ */
1655
+ async updateAsync(itemId, input) {
1656
+ return this.client.request(PASSWORD_COMMANDS.update, {
1657
+ itemId,
1658
+ input
1659
+ });
1660
+ }
1661
+ /** Delete an item by id. Item must be in scope. */
1662
+ async deleteAsync(itemId) {
1663
+ return this.client.request(PASSWORD_COMMANDS.delete, { itemId });
1664
+ }
1665
+ };
1666
+
1667
+ // src/api/mail.ts
1668
+ var MailAPI = class {
1669
+ constructor(client) {
1670
+ this.client = client;
1671
+ }
1672
+ /**
1673
+ * LIST mailboxes for an IMAP account. Pass `includeStatus=true` for
1674
+ * EXISTS/UNSEEN/UIDVALIDITY/UIDNEXT per box (one extra round-trip
1675
+ * per mailbox — fine for typical accounts, expensive for large
1676
+ * trees).
1677
+ */
1678
+ async listMailboxesAsync(imap, options = {}) {
1679
+ return this.client.request(MAIL_COMMANDS.listMailboxes, {
1680
+ imap,
1681
+ reference: options.reference,
1682
+ pattern: options.pattern,
1683
+ includeStatus: options.includeStatus
1684
+ });
1685
+ }
1686
+ /** Fetch lightweight envelopes for a mailbox + range (for list views). */
1687
+ async fetchEnvelopesAsync(imap, mailbox, range) {
1688
+ return this.client.request(
1689
+ MAIL_COMMANDS.fetchEnvelopes,
1690
+ { imap, mailbox, range }
1691
+ );
1692
+ }
1693
+ /** Fetch a full message (envelope + body + attachment metadata) by UID. */
1694
+ async fetchMessageAsync(imap, mailbox, uid) {
1695
+ return this.client.request(MAIL_COMMANDS.fetchMessage, {
1696
+ imap,
1697
+ mailbox,
1698
+ uid
1699
+ });
1700
+ }
1701
+ /**
1702
+ * Set or unset IMAP flags. Use `flags=["\\Seen"]` + `add=true` to
1703
+ * mark messages as read; `add=false` removes the flag(s).
1704
+ */
1705
+ async setFlagsAsync(imap, mailbox, uids, flags, add) {
1706
+ return this.client.request(MAIL_COMMANDS.setFlags, {
1707
+ imap,
1708
+ mailbox,
1709
+ uids,
1710
+ flags,
1711
+ add
1712
+ });
1713
+ }
1714
+ /** Move messages between mailboxes. Falls back to COPY+EXPUNGE on servers without MOVE. */
1715
+ async moveMessagesAsync(imap, sourceMailbox, destinationMailbox, uids) {
1716
+ return this.client.request(MAIL_COMMANDS.moveMessages, {
1717
+ imap,
1718
+ sourceMailbox,
1719
+ destinationMailbox,
1720
+ uids
1721
+ });
1722
+ }
1723
+ /**
1724
+ * APPEND a base64-encoded RFC822 message into a mailbox. Combine
1725
+ * with `buildRfc822Async` to save drafts, or with the bytes returned
1726
+ * after `sendMessageAsync` to mirror the sent copy into "Sent".
1727
+ */
1728
+ async appendMessageAsync(imap, mailbox, rfc822Base64, flags) {
1729
+ return this.client.request(MAIL_COMMANDS.appendMessage, {
1730
+ imap,
1731
+ mailbox,
1732
+ rfc822Base64,
1733
+ flags
1734
+ });
1735
+ }
1736
+ /** Send a message via SMTP. Returns the assigned Message-ID (no angle brackets). */
1737
+ async sendMessageAsync(smtp, message) {
1738
+ return this.client.request(MAIL_COMMANDS.sendMessage, {
1739
+ smtp,
1740
+ message
1741
+ });
1742
+ }
1743
+ /**
1744
+ * Build RFC822 bytes for a message without sending — useful for
1745
+ * drafts that get APPENDed to a "Drafts" folder. Permission-wise
1746
+ * this is a fetch operation (no SMTP host involved).
1747
+ */
1748
+ async buildRfc822Async(imapHost, message) {
1749
+ return this.client.request(MAIL_COMMANDS.buildRfc822, {
1750
+ imapHost,
1751
+ message
1752
+ });
1753
+ }
1754
+ };
1755
+
1583
1756
  // src/client/tableName.ts
1584
1757
  function validatePublicKey(publicKey) {
1585
1758
  if (!publicKey || typeof publicKey !== "string" || publicKey.trim() === "") {
@@ -1667,6 +1840,10 @@ function parseTableName(fullTableName) {
1667
1840
 
1668
1841
  // src/client/init.ts
1669
1842
  var PORT_HANDSHAKE_TIMEOUT_MS = 1e4;
1843
+ function getCurrentWebviewLabel() {
1844
+ const internals = window.__TAURI_INTERNALS__;
1845
+ return internals?.metadata?.currentWebview?.label;
1846
+ }
1670
1847
  function isInIframe() {
1671
1848
  return window.self !== window.top;
1672
1849
  }
@@ -1695,6 +1872,13 @@ async function initNativeMode(ctx, log, onEvent, onContextChange) {
1695
1872
  }
1696
1873
  async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1697
1874
  const { listen } = getTauriEvent();
1875
+ const webviewLabel = getCurrentWebviewLabel();
1876
+ const listenOptions = webviewLabel ? { target: webviewLabel } : void 0;
1877
+ if (!webviewLabel) {
1878
+ log(
1879
+ "WARNING: could not read __TAURI_INTERNALS__.metadata.currentWebview.label \u2014 registering listeners without a target. Label-scoped emits from the host will not be delivered until the metadata is available."
1880
+ );
1881
+ }
1698
1882
  log("Setting up Tauri event listener for:", HAEXTENSION_EVENTS.CONTEXT_CHANGED);
1699
1883
  try {
1700
1884
  await listen(HAEXTENSION_EVENTS.CONTEXT_CHANGED, (event) => {
@@ -1712,7 +1896,7 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1712
1896
  } else {
1713
1897
  log("Event received but no context in payload:", event);
1714
1898
  }
1715
- });
1899
+ }, listenOptions);
1716
1900
  log("Context change listener registered successfully");
1717
1901
  } catch (error) {
1718
1902
  log("Failed to setup context change listener:", error);
@@ -1730,7 +1914,7 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1730
1914
  } else {
1731
1915
  log("External request event has no payload!");
1732
1916
  }
1733
- });
1917
+ }, listenOptions);
1734
1918
  log("External request listener registered successfully");
1735
1919
  } catch (error) {
1736
1920
  log("Failed to setup external request listener:", error);
@@ -1748,7 +1932,7 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1748
1932
  } else {
1749
1933
  log("AI action request event has no payload!");
1750
1934
  }
1751
- });
1935
+ }, listenOptions);
1752
1936
  log("AI action request listener registered successfully");
1753
1937
  } catch (error) {
1754
1938
  log("Failed to setup AI action request listener:", error);
@@ -1767,7 +1951,7 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1767
1951
  timestamp: Date.now()
1768
1952
  });
1769
1953
  }
1770
- });
1954
+ }, listenOptions);
1771
1955
  log("File change listener registered successfully");
1772
1956
  } catch (error) {
1773
1957
  log("Failed to setup file change listener:", error);
@@ -1784,14 +1968,14 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1784
1968
  timestamp: Date.now()
1785
1969
  });
1786
1970
  }
1787
- });
1971
+ }, listenOptions);
1788
1972
  log("Sync tables updated listener registered successfully");
1789
1973
  } catch (error) {
1790
1974
  log("Failed to setup sync tables updated listener:", error);
1791
1975
  }
1792
1976
  log("Setting up LocalSend event listeners");
1793
1977
  try {
1794
- await setupLocalSendEventListeners(log, onEvent);
1978
+ await setupLocalSendEventListeners(log, onEvent, listenOptions);
1795
1979
  log("LocalSend event listeners setup complete");
1796
1980
  } catch (error) {
1797
1981
  log("Failed to setup LocalSend event listeners:", error);
@@ -1808,7 +1992,7 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1808
1992
  data: payload.data
1809
1993
  });
1810
1994
  }
1811
- });
1995
+ }, listenOptions);
1812
1996
  log("Shell output listener registered");
1813
1997
  await listen(SHELL_EVENTS.EXIT, (event) => {
1814
1998
  if (event.payload) {
@@ -1820,13 +2004,13 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
1820
2004
  exitCode: payload.exitCode
1821
2005
  });
1822
2006
  }
1823
- });
2007
+ }, listenOptions);
1824
2008
  log("Shell exit listener registered");
1825
2009
  } catch (error) {
1826
2010
  log("Failed to setup Shell event listeners:", error);
1827
2011
  }
1828
2012
  }
1829
- async function setupLocalSendEventListeners(log, onEvent) {
2013
+ async function setupLocalSendEventListeners(log, onEvent, listenOptions) {
1830
2014
  const { listen } = getTauriEvent();
1831
2015
  try {
1832
2016
  await listen(LOCALSEND_EVENTS.deviceDiscovered, (event) => {
@@ -1838,7 +2022,7 @@ async function setupLocalSendEventListeners(log, onEvent) {
1838
2022
  timestamp: Date.now()
1839
2023
  });
1840
2024
  }
1841
- });
2025
+ }, listenOptions);
1842
2026
  log("LocalSend device discovered listener registered");
1843
2027
  } catch (error) {
1844
2028
  log("Failed to setup LocalSend device discovered listener:", error);
@@ -1853,7 +2037,7 @@ async function setupLocalSendEventListeners(log, onEvent) {
1853
2037
  timestamp: Date.now()
1854
2038
  });
1855
2039
  }
1856
- });
2040
+ }, listenOptions);
1857
2041
  log("LocalSend device lost listener registered");
1858
2042
  } catch (error) {
1859
2043
  log("Failed to setup LocalSend device lost listener:", error);
@@ -1868,7 +2052,7 @@ async function setupLocalSendEventListeners(log, onEvent) {
1868
2052
  timestamp: Date.now()
1869
2053
  });
1870
2054
  }
1871
- });
2055
+ }, listenOptions);
1872
2056
  log("LocalSend transfer request listener registered");
1873
2057
  } catch (error) {
1874
2058
  log("Failed to setup LocalSend transfer request listener:", error);
@@ -1883,7 +2067,7 @@ async function setupLocalSendEventListeners(log, onEvent) {
1883
2067
  timestamp: Date.now()
1884
2068
  });
1885
2069
  }
1886
- });
2070
+ }, listenOptions);
1887
2071
  log("LocalSend transfer progress listener registered");
1888
2072
  } catch (error) {
1889
2073
  log("Failed to setup LocalSend transfer progress listener:", error);
@@ -1898,7 +2082,7 @@ async function setupLocalSendEventListeners(log, onEvent) {
1898
2082
  timestamp: Date.now()
1899
2083
  });
1900
2084
  }
1901
- });
2085
+ }, listenOptions);
1902
2086
  log("LocalSend transfer complete listener registered");
1903
2087
  } catch (error) {
1904
2088
  log("Failed to setup LocalSend transfer complete listener:", error);
@@ -1913,13 +2097,13 @@ async function setupLocalSendEventListeners(log, onEvent) {
1913
2097
  timestamp: Date.now()
1914
2098
  });
1915
2099
  }
1916
- });
2100
+ }, listenOptions);
1917
2101
  log("LocalSend transfer failed listener registered");
1918
2102
  } catch (error) {
1919
2103
  log("Failed to setup LocalSend transfer failed listener:", error);
1920
2104
  }
1921
2105
  }
1922
- async function initIframeMode(ctx, log, messageHandler, request) {
2106
+ async function initIframeMode(ctx, log, messageHandler) {
1923
2107
  if (!isInIframe()) {
1924
2108
  throw new HaexVaultSdkError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
1925
2109
  }
@@ -1936,15 +2120,12 @@ async function initIframeMode(ctx, log, messageHandler, request) {
1936
2120
  publicKey: ctx.config.manifest.publicKey,
1937
2121
  name: ctx.config.manifest.name,
1938
2122
  version: ctx.config.manifest.version,
1939
- displayName: ctx.config.manifest.name
2123
+ displayName: ctx.config.manifest.displayName ?? ctx.config.manifest.name
1940
2124
  };
1941
2125
  log("Extension info loaded from manifest:", ctx.state.extensionInfo);
1942
2126
  }
1943
2127
  sendDebugInfo(ctx.config);
1944
- const context = await request(EXTENSION_COMMANDS.getContext);
1945
- ctx.state.context = context;
1946
- log("Application context received:", context);
1947
- return { context, port };
2128
+ return port;
1948
2129
  }
1949
2130
  function waitForHostPortAsync(log) {
1950
2131
  return new Promise((resolve, reject) => {
@@ -2127,11 +2308,10 @@ function processEvent(event, log, eventListeners, onContextChanged, onExternalRe
2127
2308
  emitEvent(event, log, eventListeners);
2128
2309
  }
2129
2310
  function emitEvent(event, log, eventListeners) {
2130
- console.log("[HaexVault SDK] emitEvent called with:", event.type, event);
2131
- console.log("[HaexVault SDK] Registered event types:", Array.from(eventListeners.keys()));
2132
- log("Event received:", event);
2311
+ log("emitEvent called with:", event.type, event);
2312
+ log("Registered event types:", Array.from(eventListeners.keys()));
2133
2313
  const listeners = eventListeners.get(event.type);
2134
- console.log("[HaexVault SDK] Listeners for", event.type, ":", listeners?.size ?? 0);
2314
+ log("Listeners for", event.type, ":", listeners?.size ?? 0);
2135
2315
  if (listeners) {
2136
2316
  listeners.forEach((callback) => callback(event));
2137
2317
  }
@@ -2228,9 +2408,9 @@ function registerExternalHandler(action, handler, handlers, log) {
2228
2408
  };
2229
2409
  }
2230
2410
  async function handleExternalRequest(request, handlers, respond, log) {
2231
- console.log("[SDK Debug] handleExternalRequest called!");
2232
- console.log("[SDK Debug] Request:", JSON.stringify(request, null, 2));
2233
- console.log("[SDK Debug] Available handlers:", Array.from(handlers.keys()));
2411
+ log("handleExternalRequest called");
2412
+ log("Request:", request);
2413
+ log("Available handlers:", Array.from(handlers.keys()));
2234
2414
  log(`[ExternalRequest] Received request: ${request.action} from ${request.publicKey.substring(0, 20)}...`);
2235
2415
  const handler = handlers.get(request.action);
2236
2416
  if (!handler) {
@@ -2256,7 +2436,6 @@ async function handleExternalRequest(request, handlers, respond, log) {
2256
2436
  }
2257
2437
  }
2258
2438
  async function respondToExternalRequest(response, request) {
2259
- console.log("[SDK Debug] respondToExternalRequest called with:", JSON.stringify(response, null, 2));
2260
2439
  await request(EXTERNAL_BRIDGE_COMMANDS.respond, response);
2261
2440
  }
2262
2441
 
@@ -2314,11 +2493,17 @@ var HaexVaultSdk = class {
2314
2493
  this.localsend = new LocalSendAPI(this);
2315
2494
  this.spaces = new SpacesAPI(this);
2316
2495
  this.shell = new ShellAPI(this);
2496
+ this.passwords = new PasswordsAPI(this);
2497
+ this.mail = new MailAPI(this);
2317
2498
  installConsoleForwarding(this.config.debug);
2318
- this.readyPromise = new Promise((resolve) => {
2499
+ this.readyPromise = new Promise((resolve, reject) => {
2319
2500
  this.resolveReady = resolve;
2501
+ this.rejectReady = reject;
2502
+ });
2503
+ this.init().catch((error) => {
2504
+ this.log("Init failed:", error);
2505
+ this.rejectReady(error);
2320
2506
  });
2321
- this.init();
2322
2507
  }
2323
2508
  // ==========================================================================
2324
2509
  // Lifecycle
@@ -2346,9 +2531,14 @@ var HaexVaultSdk = class {
2346
2531
  return this.setupPromise;
2347
2532
  }
2348
2533
  destroy() {
2349
- if (this.messageHandler) {
2350
- window.removeEventListener("message", this.messageHandler);
2534
+ if (this.messageHandler && this.hostPort) {
2535
+ this.hostPort.removeEventListener("message", this.messageHandler);
2351
2536
  }
2537
+ if (this.hostPort) {
2538
+ this.hostPort.close();
2539
+ this.hostPort = null;
2540
+ }
2541
+ this.messageHandler = null;
2352
2542
  this.pendingRequests.forEach(({ timeout }) => clearTimeout(timeout));
2353
2543
  this.pendingRequests.clear();
2354
2544
  this.eventListeners.clear();
@@ -2538,7 +2728,7 @@ var HaexVaultSdk = class {
2538
2728
  () => this._extensionInfo,
2539
2729
  this.handleEvent.bind(this)
2540
2730
  );
2541
- const { context, port } = await initIframeMode(
2731
+ const port = await initIframeMode(
2542
2732
  {
2543
2733
  config: this.config,
2544
2734
  state: {
@@ -2567,8 +2757,7 @@ var HaexVaultSdk = class {
2567
2757
  }
2568
2758
  },
2569
2759
  this.log.bind(this),
2570
- this.messageHandler,
2571
- this.request.bind(this)
2760
+ this.messageHandler
2572
2761
  );
2573
2762
  this.hostPort = port;
2574
2763
  if (this.config.manifest) {
@@ -2576,10 +2765,12 @@ var HaexVaultSdk = class {
2576
2765
  publicKey: this.config.manifest.publicKey,
2577
2766
  name: this.config.manifest.name,
2578
2767
  version: this.config.manifest.version,
2579
- displayName: this.config.manifest.name
2768
+ displayName: this.config.manifest.displayName ?? this.config.manifest.name
2580
2769
  };
2581
2770
  this.notifySubscribersInternal();
2582
2771
  }
2772
+ const context = await this.request(EXTENSION_COMMANDS.getContext);
2773
+ this.log("Application context received:", context);
2583
2774
  this._context = context;
2584
2775
  this.isNativeWindow = false;
2585
2776
  this.initialized = true;