@haex-space/vault-sdk 3.0.0 → 3.2.0

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-dpJHb3FP.d.ts → client-GeColu97.d.mts} +270 -2
  2. package/dist/{client-BXtzUBWv.d.mts → client-z1jTcuQE.d.ts} +270 -2
  3. package/dist/index.d.mts +93 -6
  4. package/dist/index.d.ts +93 -6
  5. package/dist/index.js +301 -45
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +298 -46
  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 +34 -7
  12. package/dist/nuxt.js.map +1 -1
  13. package/dist/nuxt.mjs +34 -7
  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 +294 -44
  18. package/dist/react.js.map +1 -1
  19. package/dist/react.mjs +294 -44
  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 +294 -48
  24. package/dist/runtime/nuxt.plugin.client.js.map +1 -1
  25. package/dist/runtime/nuxt.plugin.client.mjs +294 -48
  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 +294 -44
  30. package/dist/svelte.js.map +1 -1
  31. package/dist/svelte.mjs +294 -44
  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 +33 -6
  36. package/dist/vite.js.map +1 -1
  37. package/dist/vite.mjs +33 -6
  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 +294 -44
  42. package/dist/vue.js.map +1 -1
  43. package/dist/vue.mjs +294 -44
  44. package/dist/vue.mjs.map +1 -1
  45. package/package.json +2 -1
@@ -265,6 +265,40 @@ var SHELL_COMMANDS = {
265
265
  close: "extension_shell_close"
266
266
  };
267
267
 
268
+ // src/commands/passwords.ts
269
+ var PASSWORD_COMMANDS = {
270
+ /** List items (no secrets) within the extension's tag scope */
271
+ list: "extension_password_list",
272
+ /** Read full item including secrets, by id */
273
+ read: "extension_password_read",
274
+ /** Create item — must include >=1 tag in scope */
275
+ create: "extension_password_create",
276
+ /** Update item — keeps >=1 tag in scope */
277
+ update: "extension_password_update",
278
+ /** Delete item — must be in scope */
279
+ delete: "extension_password_delete"
280
+ };
281
+
282
+ // src/commands/mail.ts
283
+ var MAIL_COMMANDS = {
284
+ /** LIST mailboxes + optional STATUS counts */
285
+ listMailboxes: "extension_mail_list_mailboxes",
286
+ /** Lightweight envelope fetch for list views */
287
+ fetchEnvelopes: "extension_mail_fetch_envelopes",
288
+ /** Full message fetch (envelope + body + attachment metadata) */
289
+ fetchMessage: "extension_mail_fetch_message",
290
+ /** Set or unset IMAP flags on a UID set */
291
+ setFlags: "extension_mail_set_flags",
292
+ /** MOVE messages between mailboxes (COPY+EXPUNGE fallback) */
293
+ moveMessages: "extension_mail_move_messages",
294
+ /** APPEND a base64-encoded RFC822 message into a mailbox */
295
+ appendMessage: "extension_mail_append_message",
296
+ /** SMTP send. Returns the assigned Message-ID. */
297
+ sendMessage: "extension_mail_send_message",
298
+ /** Build RFC822 bytes without sending (for Drafts via APPEND) */
299
+ buildRfc822: "extension_mail_build_rfc822"
300
+ };
301
+
268
302
  // src/api/storage.ts
269
303
  var StorageAPI = class {
270
304
  constructor(client) {
@@ -288,6 +322,12 @@ var StorageAPI = class {
288
322
  };
289
323
 
290
324
  // src/api/database.ts
325
+ function quoteIdent(identifier) {
326
+ if (identifier.startsWith('"') && identifier.endsWith('"')) {
327
+ return identifier;
328
+ }
329
+ return `"${identifier.replace(/"/g, '""')}"`;
330
+ }
291
331
  var DatabaseAPI = class {
292
332
  constructor(client) {
293
333
  this.client = client;
@@ -318,11 +358,11 @@ var DatabaseAPI = class {
318
358
  });
319
359
  }
320
360
  async createTable(tableName, columns) {
321
- const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
361
+ const query = `CREATE TABLE IF NOT EXISTS ${quoteIdent(tableName)} (${columns})`;
322
362
  await this.execute(query);
323
363
  }
324
364
  async dropTable(tableName) {
325
- const query = `DROP TABLE IF EXISTS ${tableName}`;
365
+ const query = `DROP TABLE IF EXISTS ${quoteIdent(tableName)}`;
326
366
  await this.execute(query);
327
367
  }
328
368
  /**
@@ -351,18 +391,17 @@ var DatabaseAPI = class {
351
391
  async insert(tableName, data) {
352
392
  const keys = Object.keys(data);
353
393
  const values = Object.values(data);
394
+ const quotedCols = keys.map(quoteIdent).join(", ");
354
395
  const placeholders = keys.map(() => "?").join(", ");
355
- const query = `INSERT INTO ${tableName} (${keys.join(
356
- ", "
357
- )}) VALUES (${placeholders})`;
396
+ const query = `INSERT INTO ${quoteIdent(tableName)} (${quotedCols}) VALUES (${placeholders})`;
358
397
  const result = await this.execute(query, values);
359
398
  return result.lastInsertId ?? -1;
360
399
  }
361
400
  async update(tableName, data, where, whereParams) {
362
401
  const keys = Object.keys(data);
363
402
  const values = Object.values(data);
364
- const setClause = keys.map((key) => `${key} = ?`).join(", ");
365
- const query = `UPDATE ${tableName} SET ${setClause} WHERE ${where}`;
403
+ const setClause = keys.map((key) => `${quoteIdent(key)} = ?`).join(", ");
404
+ const query = `UPDATE ${quoteIdent(tableName)} SET ${setClause} WHERE ${where}`;
366
405
  const result = await this.execute(query, [
367
406
  ...values,
368
407
  ...whereParams || []
@@ -370,12 +409,12 @@ var DatabaseAPI = class {
370
409
  return result.rowsAffected;
371
410
  }
372
411
  async delete(tableName, where, whereParams) {
373
- const query = `DELETE FROM ${tableName} WHERE ${where}`;
412
+ const query = `DELETE FROM ${quoteIdent(tableName)} WHERE ${where}`;
374
413
  const result = await this.execute(query, whereParams);
375
414
  return result.rowsAffected;
376
415
  }
377
416
  async count(tableName, where, whereParams) {
378
- const query = where ? `SELECT COUNT(*) as count FROM ${tableName} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${tableName}`;
417
+ const query = where ? `SELECT COUNT(*) as count FROM ${quoteIdent(tableName)} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${quoteIdent(tableName)}`;
379
418
  const result = await this.queryOne(query, whereParams);
380
419
  return result?.count ?? 0;
381
420
  }
@@ -1222,12 +1261,163 @@ var ShellAPI = class {
1222
1261
  }
1223
1262
  };
1224
1263
 
1264
+ // src/api/passwords.ts
1265
+ var PasswordsAPI = class {
1266
+ constructor(client) {
1267
+ this.client = client;
1268
+ }
1269
+ /** List items in scope — summaries only, no secrets. */
1270
+ async listAsync() {
1271
+ return this.client.request(
1272
+ PASSWORD_COMMANDS.list,
1273
+ {}
1274
+ );
1275
+ }
1276
+ /** Read a single item by id with full secrets. */
1277
+ async readAsync(itemId) {
1278
+ return this.client.request(PASSWORD_COMMANDS.read, {
1279
+ itemId
1280
+ });
1281
+ }
1282
+ /**
1283
+ * Create a new password item. `input.tags` must contain at least one
1284
+ * tag within the extension's permission scope, otherwise the write
1285
+ * is rejected as a security violation.
1286
+ *
1287
+ * Returns the new item id.
1288
+ */
1289
+ async createAsync(input) {
1290
+ return this.client.request(PASSWORD_COMMANDS.create, { input });
1291
+ }
1292
+ /**
1293
+ * Update an existing item. The item must already be in scope, and
1294
+ * the new tag set must keep at least one tag in scope (extensions
1295
+ * cannot orphan an item out of their own reach).
1296
+ */
1297
+ async updateAsync(itemId, input) {
1298
+ return this.client.request(PASSWORD_COMMANDS.update, {
1299
+ itemId,
1300
+ input
1301
+ });
1302
+ }
1303
+ /** Delete an item by id. Item must be in scope. */
1304
+ async deleteAsync(itemId) {
1305
+ return this.client.request(PASSWORD_COMMANDS.delete, { itemId });
1306
+ }
1307
+ };
1308
+
1309
+ // src/api/mail.ts
1310
+ var MailAPI = class {
1311
+ constructor(client) {
1312
+ this.client = client;
1313
+ }
1314
+ /**
1315
+ * LIST mailboxes for an IMAP account. Pass `includeStatus=true` for
1316
+ * EXISTS/UNSEEN/UIDVALIDITY/UIDNEXT per box (one extra round-trip
1317
+ * per mailbox — fine for typical accounts, expensive for large
1318
+ * trees).
1319
+ */
1320
+ async listMailboxesAsync(imap, options = {}) {
1321
+ return this.client.request(MAIL_COMMANDS.listMailboxes, {
1322
+ imap,
1323
+ reference: options.reference,
1324
+ pattern: options.pattern,
1325
+ includeStatus: options.includeStatus
1326
+ });
1327
+ }
1328
+ /** Fetch lightweight envelopes for a mailbox + range (for list views). */
1329
+ async fetchEnvelopesAsync(imap, mailbox, range) {
1330
+ return this.client.request(
1331
+ MAIL_COMMANDS.fetchEnvelopes,
1332
+ { imap, mailbox, range }
1333
+ );
1334
+ }
1335
+ /** Fetch a full message (envelope + body + attachment metadata) by UID. */
1336
+ async fetchMessageAsync(imap, mailbox, uid) {
1337
+ return this.client.request(MAIL_COMMANDS.fetchMessage, {
1338
+ imap,
1339
+ mailbox,
1340
+ uid
1341
+ });
1342
+ }
1343
+ /**
1344
+ * Set or unset IMAP flags. Use `flags=["\\Seen"]` + `add=true` to
1345
+ * mark messages as read; `add=false` removes the flag(s).
1346
+ */
1347
+ async setFlagsAsync(imap, mailbox, uids, flags, add) {
1348
+ return this.client.request(MAIL_COMMANDS.setFlags, {
1349
+ imap,
1350
+ mailbox,
1351
+ uids,
1352
+ flags,
1353
+ add
1354
+ });
1355
+ }
1356
+ /** Move messages between mailboxes. Falls back to COPY+EXPUNGE on servers without MOVE. */
1357
+ async moveMessagesAsync(imap, sourceMailbox, destinationMailbox, uids) {
1358
+ return this.client.request(MAIL_COMMANDS.moveMessages, {
1359
+ imap,
1360
+ sourceMailbox,
1361
+ destinationMailbox,
1362
+ uids
1363
+ });
1364
+ }
1365
+ /**
1366
+ * APPEND a base64-encoded RFC822 message into a mailbox. Combine
1367
+ * with `buildRfc822Async` to save drafts, or with the bytes returned
1368
+ * after `sendMessageAsync` to mirror the sent copy into "Sent".
1369
+ */
1370
+ async appendMessageAsync(imap, mailbox, rfc822Base64, flags) {
1371
+ return this.client.request(MAIL_COMMANDS.appendMessage, {
1372
+ imap,
1373
+ mailbox,
1374
+ rfc822Base64,
1375
+ flags
1376
+ });
1377
+ }
1378
+ /** Send a message via SMTP. Returns the assigned Message-ID (no angle brackets). */
1379
+ async sendMessageAsync(smtp, message) {
1380
+ return this.client.request(MAIL_COMMANDS.sendMessage, {
1381
+ smtp,
1382
+ message
1383
+ });
1384
+ }
1385
+ /**
1386
+ * Build RFC822 bytes for a message without sending — useful for
1387
+ * drafts that get APPENDed to a "Drafts" folder. Permission-wise
1388
+ * this is a fetch operation (no SMTP host involved).
1389
+ */
1390
+ async buildRfc822Async(imapHost, message) {
1391
+ return this.client.request(MAIL_COMMANDS.buildRfc822, {
1392
+ imapHost,
1393
+ message
1394
+ });
1395
+ }
1396
+ };
1397
+
1225
1398
  // src/messages.ts
1226
1399
  var HAEXSPACE_MESSAGE_TYPES = {
1227
1400
  /** Debug message for development/troubleshooting */
1228
1401
  DEBUG: "haexspace:debug",
1229
1402
  /** Console forwarding from extension iframe */
1230
- CONSOLE_FORWARD: "console.forward"
1403
+ CONSOLE_FORWARD: "console.forward",
1404
+ /**
1405
+ * Sent from main window to iframe on the shared window listener, carrying
1406
+ * one `MessagePort` in `event.ports[0]`. Once received, the SDK switches
1407
+ * to port-based messaging and never reads the window listener again.
1408
+ *
1409
+ * Payload: `{ type: PORT_INIT }` — no data. The port itself is the payload.
1410
+ */
1411
+ PORT_INIT: "haexspace:port:init",
1412
+ /**
1413
+ * Sent from SDK to main window *over the MessagePort* after the port is
1414
+ * installed. Main uses this to mark the iframe as ready and flush any
1415
+ * events buffered during the handshake window. Only valid on the port —
1416
+ * a READY sent over window.postMessage is ignored.
1417
+ *
1418
+ * Payload: `{ type: PORT_READY }` — no data.
1419
+ */
1420
+ PORT_READY: "haexspace:port:ready"
1231
1421
  };
1232
1422
 
1233
1423
  // src/polyfills/consoleForwarding.ts
@@ -1382,6 +1572,7 @@ function parseTableName(fullTableName) {
1382
1572
  }
1383
1573
 
1384
1574
  // src/client/init.ts
1575
+ var PORT_HANDSHAKE_TIMEOUT_MS = 1e4;
1385
1576
  function isInIframe() {
1386
1577
  return window.self !== window.top;
1387
1578
  }
@@ -1638,17 +1829,20 @@ async function initIframeMode(ctx, log, messageHandler, request) {
1638
1829
  if (!isInIframe()) {
1639
1830
  throw new HaexVaultSdkError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
1640
1831
  }
1832
+ const port = await waitForHostPortAsync(log);
1641
1833
  ctx.handlers.messageHandler = messageHandler;
1642
- window.addEventListener("message", messageHandler);
1834
+ port.addEventListener("message", messageHandler);
1835
+ port.start();
1836
+ port.postMessage({ type: HAEXSPACE_MESSAGE_TYPES.PORT_READY });
1643
1837
  ctx.state.isNativeWindow = false;
1644
1838
  ctx.state.initialized = true;
1645
- log("HaexVault SDK initialized in iframe mode");
1839
+ log("HaexVault SDK initialized in iframe mode (MessagePort transport)");
1646
1840
  if (ctx.config.manifest) {
1647
1841
  ctx.state.extensionInfo = {
1648
1842
  publicKey: ctx.config.manifest.publicKey,
1649
1843
  name: ctx.config.manifest.name,
1650
1844
  version: ctx.config.manifest.version,
1651
- displayName: ctx.config.manifest.name
1845
+ displayName: ctx.config.manifest.displayName ?? ctx.config.manifest.name
1652
1846
  };
1653
1847
  log("Extension info loaded from manifest:", ctx.state.extensionInfo);
1654
1848
  }
@@ -1656,7 +1850,42 @@ async function initIframeMode(ctx, log, messageHandler, request) {
1656
1850
  const context = await request(EXTENSION_COMMANDS.getContext);
1657
1851
  ctx.state.context = context;
1658
1852
  log("Application context received:", context);
1659
- return { context };
1853
+ return { context, port };
1854
+ }
1855
+ function waitForHostPortAsync(log) {
1856
+ return new Promise((resolve, reject) => {
1857
+ let settled = false;
1858
+ const cleanup = () => {
1859
+ window.removeEventListener("message", handler);
1860
+ };
1861
+ const timeoutId = setTimeout(() => {
1862
+ if (settled) return;
1863
+ settled = true;
1864
+ cleanup();
1865
+ reject(
1866
+ new HaexVaultSdkError(
1867
+ "TIMEOUT" /* TIMEOUT */,
1868
+ "errors.port_handshake_timeout",
1869
+ { timeout: PORT_HANDSHAKE_TIMEOUT_MS }
1870
+ )
1871
+ );
1872
+ }, PORT_HANDSHAKE_TIMEOUT_MS);
1873
+ const handler = (event) => {
1874
+ const type = event.data?.type;
1875
+ if (type !== HAEXSPACE_MESSAGE_TYPES.PORT_INIT) return;
1876
+ const port = event.ports[0];
1877
+ if (!port) {
1878
+ log("PORT_INIT received but event.ports is empty \u2014 ignoring");
1879
+ return;
1880
+ }
1881
+ if (settled) return;
1882
+ settled = true;
1883
+ clearTimeout(timeoutId);
1884
+ cleanup();
1885
+ resolve(port);
1886
+ };
1887
+ window.addEventListener("message", handler);
1888
+ });
1660
1889
  }
1661
1890
  function sendDebugInfo(config) {
1662
1891
  if (!config.debug) return;
@@ -1680,7 +1909,15 @@ postMessage error: ${e}`);
1680
1909
  function generateRequestId(counter) {
1681
1910
  return `req_${counter}`;
1682
1911
  }
1683
- function sendPostMessage(method, params, requestId, config, extensionInfo, pendingRequests) {
1912
+ function sendPostMessage(method, params, requestId, config, extensionInfo, pendingRequests, port) {
1913
+ if (!port) {
1914
+ return Promise.reject(
1915
+ new HaexVaultSdkError(
1916
+ "EXTENSION_NOT_INITIALIZED" /* EXTENSION_NOT_INITIALIZED */,
1917
+ "errors.port_not_connected"
1918
+ )
1919
+ );
1920
+ }
1684
1921
  const request = {
1685
1922
  method,
1686
1923
  params,
@@ -1696,17 +1933,16 @@ function sendPostMessage(method, params, requestId, config, extensionInfo, pendi
1696
1933
  );
1697
1934
  }, config.timeout);
1698
1935
  pendingRequests.set(requestId, { resolve, reject, timeout });
1699
- const targetOrigin = "*";
1700
1936
  if (config.debug) {
1701
1937
  console.log("[SDK Debug] ========== Sending Request ==========");
1702
1938
  console.log("[SDK Debug] Request ID:", requestId);
1703
1939
  console.log("[SDK Debug] Method:", request.method);
1704
1940
  console.log("[SDK Debug] Params:", request.params);
1705
- console.log("[SDK Debug] Target origin:", targetOrigin);
1941
+ console.log("[SDK Debug] Transport: MessagePort");
1706
1942
  console.log("[SDK Debug] Extension info:", extensionInfo);
1707
1943
  console.log("[SDK Debug] ========================================");
1708
1944
  }
1709
- window.parent.postMessage({ id: requestId, ...request }, targetOrigin);
1945
+ port.postMessage({ id: requestId, ...request });
1710
1946
  });
1711
1947
  }
1712
1948
  async function sendInvoke(method, params, config, _log) {
@@ -1725,11 +1961,6 @@ function createMessageHandler(config, pendingRequests, extensionInfo, onEvent) {
1725
1961
  return (event) => {
1726
1962
  if (config.debug) {
1727
1963
  console.log("[SDK Debug] ========== Message Received ==========");
1728
- console.log("[SDK Debug] Event origin:", event.origin);
1729
- console.log(
1730
- "[SDK Debug] Event source:",
1731
- event.source === window.parent ? "parent window" : "unknown"
1732
- );
1733
1964
  console.log("[SDK Debug] Event data:", event.data);
1734
1965
  console.log("[SDK Debug] Extension info loaded:", !!extensionInfo());
1735
1966
  console.log(
@@ -1737,12 +1968,6 @@ function createMessageHandler(config, pendingRequests, extensionInfo, onEvent) {
1737
1968
  pendingRequests.size
1738
1969
  );
1739
1970
  }
1740
- if (event.source !== window.parent) {
1741
- if (config.debug) {
1742
- console.error("[SDK Debug] \u274C REJECTED: Message not from parent window!");
1743
- }
1744
- return;
1745
- }
1746
1971
  const data = event.data;
1747
1972
  if ("id" in data && pendingRequests.has(data.id)) {
1748
1973
  if (config.debug) {
@@ -1808,11 +2033,10 @@ function processEvent(event, log, eventListeners, onContextChanged, onExternalRe
1808
2033
  emitEvent(event, log, eventListeners);
1809
2034
  }
1810
2035
  function emitEvent(event, log, eventListeners) {
1811
- console.log("[HaexVault SDK] emitEvent called with:", event.type, event);
1812
- console.log("[HaexVault SDK] Registered event types:", Array.from(eventListeners.keys()));
1813
- log("Event received:", event);
2036
+ log("emitEvent called with:", event.type, event);
2037
+ log("Registered event types:", Array.from(eventListeners.keys()));
1814
2038
  const listeners = eventListeners.get(event.type);
1815
- console.log("[HaexVault SDK] Listeners for", event.type, ":", listeners?.size ?? 0);
2039
+ log("Listeners for", event.type, ":", listeners?.size ?? 0);
1816
2040
  if (listeners) {
1817
2041
  listeners.forEach((callback) => callback(event));
1818
2042
  }
@@ -1909,9 +2133,9 @@ function registerExternalHandler(action, handler, handlers, log) {
1909
2133
  };
1910
2134
  }
1911
2135
  async function handleExternalRequest(request, handlers, respond, log) {
1912
- console.log("[SDK Debug] handleExternalRequest called!");
1913
- console.log("[SDK Debug] Request:", JSON.stringify(request, null, 2));
1914
- console.log("[SDK Debug] Available handlers:", Array.from(handlers.keys()));
2136
+ log("handleExternalRequest called");
2137
+ log("Request:", request);
2138
+ log("Available handlers:", Array.from(handlers.keys()));
1915
2139
  log(`[ExternalRequest] Received request: ${request.action} from ${request.publicKey.substring(0, 20)}...`);
1916
2140
  const handler = handlers.get(request.action);
1917
2141
  if (!handler) {
@@ -1937,7 +2161,6 @@ async function handleExternalRequest(request, handlers, respond, log) {
1937
2161
  }
1938
2162
  }
1939
2163
  async function respondToExternalRequest(response, request) {
1940
- console.log("[SDK Debug] respondToExternalRequest called with:", JSON.stringify(response, null, 2));
1941
2164
  await request(EXTERNAL_BRIDGE_COMMANDS.respond, response);
1942
2165
  }
1943
2166
 
@@ -1964,6 +2187,13 @@ var HaexVaultSdk = class {
1964
2187
  this.reactiveSubscribers = /* @__PURE__ */ new Set();
1965
2188
  // Handlers
1966
2189
  this.messageHandler = null;
2190
+ /**
2191
+ * MessagePort obtained from the main window during iframe-mode handshake.
2192
+ * `null` until `initIframe()` completes successfully. Every outbound
2193
+ * request in iframe mode flows through this port; `sendPostMessage` rejects
2194
+ * if called before the handshake finishes.
2195
+ */
2196
+ this.hostPort = null;
1967
2197
  this.setupPromise = null;
1968
2198
  this.setupHook = null;
1969
2199
  // Public APIs
@@ -1988,11 +2218,17 @@ var HaexVaultSdk = class {
1988
2218
  this.localsend = new LocalSendAPI(this);
1989
2219
  this.spaces = new SpacesAPI(this);
1990
2220
  this.shell = new ShellAPI(this);
2221
+ this.passwords = new PasswordsAPI(this);
2222
+ this.mail = new MailAPI(this);
1991
2223
  installConsoleForwarding(this.config.debug);
1992
- this.readyPromise = new Promise((resolve) => {
2224
+ this.readyPromise = new Promise((resolve, reject) => {
1993
2225
  this.resolveReady = resolve;
2226
+ this.rejectReady = reject;
2227
+ });
2228
+ this.init().catch((error) => {
2229
+ this.log("Init failed:", error);
2230
+ this.rejectReady(error);
1994
2231
  });
1995
- this.init();
1996
2232
  }
1997
2233
  // ==========================================================================
1998
2234
  // Lifecycle
@@ -2020,9 +2256,14 @@ var HaexVaultSdk = class {
2020
2256
  return this.setupPromise;
2021
2257
  }
2022
2258
  destroy() {
2023
- if (this.messageHandler) {
2024
- window.removeEventListener("message", this.messageHandler);
2259
+ if (this.messageHandler && this.hostPort) {
2260
+ this.hostPort.removeEventListener("message", this.messageHandler);
2025
2261
  }
2262
+ if (this.hostPort) {
2263
+ this.hostPort.close();
2264
+ this.hostPort = null;
2265
+ }
2266
+ this.messageHandler = null;
2026
2267
  this.pendingRequests.forEach(({ timeout }) => clearTimeout(timeout));
2027
2268
  this.pendingRequests.clear();
2028
2269
  this.eventListeners.clear();
@@ -2137,7 +2378,15 @@ var HaexVaultSdk = class {
2137
2378
  return sendInvoke(method, paramsWithCredentials, this.config, this.log.bind(this));
2138
2379
  }
2139
2380
  const requestId = generateRequestId(++this.requestCounter);
2140
- return sendPostMessage(method, resolvedParams, requestId, this.config, this._extensionInfo, this.pendingRequests);
2381
+ return sendPostMessage(
2382
+ method,
2383
+ resolvedParams,
2384
+ requestId,
2385
+ this.config,
2386
+ this._extensionInfo,
2387
+ this.pendingRequests,
2388
+ this.hostPort
2389
+ );
2141
2390
  }
2142
2391
  // ==========================================================================
2143
2392
  // Private: Initialization
@@ -2204,7 +2453,7 @@ var HaexVaultSdk = class {
2204
2453
  () => this._extensionInfo,
2205
2454
  this.handleEvent.bind(this)
2206
2455
  );
2207
- const { context } = await initIframeMode(
2456
+ const { context, port } = await initIframeMode(
2208
2457
  {
2209
2458
  config: this.config,
2210
2459
  state: {
@@ -2236,12 +2485,13 @@ var HaexVaultSdk = class {
2236
2485
  this.messageHandler,
2237
2486
  this.request.bind(this)
2238
2487
  );
2488
+ this.hostPort = port;
2239
2489
  if (this.config.manifest) {
2240
2490
  this._extensionInfo = {
2241
2491
  publicKey: this.config.manifest.publicKey,
2242
2492
  name: this.config.manifest.name,
2243
2493
  version: this.config.manifest.version,
2244
- displayName: this.config.manifest.name
2494
+ displayName: this.config.manifest.displayName ?? this.config.manifest.name
2245
2495
  };
2246
2496
  this.notifySubscribersInternal();
2247
2497
  }
@@ -2323,22 +2573,18 @@ var nuxt_plugin_client_default = defineNuxtPlugin(async (nuxtApp) => {
2323
2573
  context: client.context
2324
2574
  });
2325
2575
  await client.ready();
2326
- console.log("[Nuxt Plugin] Client ready, context:", client.context);
2327
2576
  state.value = {
2328
2577
  isReady: true,
2329
2578
  isSetupComplete: false,
2330
2579
  context: client.context
2331
2580
  };
2332
- console.log("[Nuxt Plugin] Initial state set:", state.value);
2333
2581
  client.subscribe(() => {
2334
- console.log("[Nuxt Plugin] Client context updated:", client.context);
2335
2582
  const isSetupComplete = client.setupCompleted;
2336
2583
  state.value = {
2337
2584
  ...state.value,
2338
2585
  context: client.context,
2339
2586
  isSetupComplete
2340
2587
  };
2341
- console.log("[Nuxt Plugin] State updated:", state.value);
2342
2588
  });
2343
2589
  const haexVaultPlugin = {
2344
2590
  client,