@haex-space/vault-sdk 2.9.3 → 3.1.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.
@@ -314,7 +314,7 @@ var DatabaseAPI = class {
314
314
  }
315
315
  async transaction(statements) {
316
316
  await this.client.request(DATABASE_COMMANDS.transaction, {
317
- statements
317
+ statements: statements.map((s) => [s.sql, s.params || []])
318
318
  });
319
319
  }
320
320
  async createTable(tableName, columns) {
@@ -1227,7 +1227,24 @@ var HAEXSPACE_MESSAGE_TYPES = {
1227
1227
  /** Debug message for development/troubleshooting */
1228
1228
  DEBUG: "haexspace:debug",
1229
1229
  /** Console forwarding from extension iframe */
1230
- CONSOLE_FORWARD: "console.forward"
1230
+ CONSOLE_FORWARD: "console.forward",
1231
+ /**
1232
+ * Sent from main window to iframe on the shared window listener, carrying
1233
+ * one `MessagePort` in `event.ports[0]`. Once received, the SDK switches
1234
+ * to port-based messaging and never reads the window listener again.
1235
+ *
1236
+ * Payload: `{ type: PORT_INIT }` — no data. The port itself is the payload.
1237
+ */
1238
+ PORT_INIT: "haexspace:port:init",
1239
+ /**
1240
+ * Sent from SDK to main window *over the MessagePort* after the port is
1241
+ * installed. Main uses this to mark the iframe as ready and flush any
1242
+ * events buffered during the handshake window. Only valid on the port —
1243
+ * a READY sent over window.postMessage is ignored.
1244
+ *
1245
+ * Payload: `{ type: PORT_READY }` — no data.
1246
+ */
1247
+ PORT_READY: "haexspace:port:ready"
1231
1248
  };
1232
1249
 
1233
1250
  // src/polyfills/consoleForwarding.ts
@@ -1382,6 +1399,7 @@ function parseTableName(fullTableName) {
1382
1399
  }
1383
1400
 
1384
1401
  // src/client/init.ts
1402
+ var PORT_HANDSHAKE_TIMEOUT_MS = 1e4;
1385
1403
  function isInIframe() {
1386
1404
  return window.self !== window.top;
1387
1405
  }
@@ -1638,11 +1656,14 @@ async function initIframeMode(ctx, log, messageHandler, request) {
1638
1656
  if (!isInIframe()) {
1639
1657
  throw new HaexVaultSdkError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
1640
1658
  }
1659
+ const port = await waitForHostPortAsync(log);
1641
1660
  ctx.handlers.messageHandler = messageHandler;
1642
- window.addEventListener("message", messageHandler);
1661
+ port.addEventListener("message", messageHandler);
1662
+ port.start();
1663
+ port.postMessage({ type: HAEXSPACE_MESSAGE_TYPES.PORT_READY });
1643
1664
  ctx.state.isNativeWindow = false;
1644
1665
  ctx.state.initialized = true;
1645
- log("HaexVault SDK initialized in iframe mode");
1666
+ log("HaexVault SDK initialized in iframe mode (MessagePort transport)");
1646
1667
  if (ctx.config.manifest) {
1647
1668
  ctx.state.extensionInfo = {
1648
1669
  publicKey: ctx.config.manifest.publicKey,
@@ -1656,7 +1677,42 @@ async function initIframeMode(ctx, log, messageHandler, request) {
1656
1677
  const context = await request(EXTENSION_COMMANDS.getContext);
1657
1678
  ctx.state.context = context;
1658
1679
  log("Application context received:", context);
1659
- return { context };
1680
+ return { context, port };
1681
+ }
1682
+ function waitForHostPortAsync(log) {
1683
+ return new Promise((resolve, reject) => {
1684
+ let settled = false;
1685
+ const cleanup = () => {
1686
+ window.removeEventListener("message", handler);
1687
+ };
1688
+ const timeoutId = setTimeout(() => {
1689
+ if (settled) return;
1690
+ settled = true;
1691
+ cleanup();
1692
+ reject(
1693
+ new HaexVaultSdkError(
1694
+ "TIMEOUT" /* TIMEOUT */,
1695
+ "errors.port_handshake_timeout",
1696
+ { timeout: PORT_HANDSHAKE_TIMEOUT_MS }
1697
+ )
1698
+ );
1699
+ }, PORT_HANDSHAKE_TIMEOUT_MS);
1700
+ const handler = (event) => {
1701
+ const type = event.data?.type;
1702
+ if (type !== HAEXSPACE_MESSAGE_TYPES.PORT_INIT) return;
1703
+ const port = event.ports[0];
1704
+ if (!port) {
1705
+ log("PORT_INIT received but event.ports is empty \u2014 ignoring");
1706
+ return;
1707
+ }
1708
+ if (settled) return;
1709
+ settled = true;
1710
+ clearTimeout(timeoutId);
1711
+ cleanup();
1712
+ resolve(port);
1713
+ };
1714
+ window.addEventListener("message", handler);
1715
+ });
1660
1716
  }
1661
1717
  function sendDebugInfo(config) {
1662
1718
  if (!config.debug) return;
@@ -1680,7 +1736,15 @@ postMessage error: ${e}`);
1680
1736
  function generateRequestId(counter) {
1681
1737
  return `req_${counter}`;
1682
1738
  }
1683
- function sendPostMessage(method, params, requestId, config, extensionInfo, pendingRequests) {
1739
+ function sendPostMessage(method, params, requestId, config, extensionInfo, pendingRequests, port) {
1740
+ if (!port) {
1741
+ return Promise.reject(
1742
+ new HaexVaultSdkError(
1743
+ "EXTENSION_NOT_INITIALIZED" /* EXTENSION_NOT_INITIALIZED */,
1744
+ "errors.port_not_connected"
1745
+ )
1746
+ );
1747
+ }
1684
1748
  const request = {
1685
1749
  method,
1686
1750
  params,
@@ -1696,17 +1760,16 @@ function sendPostMessage(method, params, requestId, config, extensionInfo, pendi
1696
1760
  );
1697
1761
  }, config.timeout);
1698
1762
  pendingRequests.set(requestId, { resolve, reject, timeout });
1699
- const targetOrigin = "*";
1700
1763
  if (config.debug) {
1701
1764
  console.log("[SDK Debug] ========== Sending Request ==========");
1702
1765
  console.log("[SDK Debug] Request ID:", requestId);
1703
1766
  console.log("[SDK Debug] Method:", request.method);
1704
1767
  console.log("[SDK Debug] Params:", request.params);
1705
- console.log("[SDK Debug] Target origin:", targetOrigin);
1768
+ console.log("[SDK Debug] Transport: MessagePort");
1706
1769
  console.log("[SDK Debug] Extension info:", extensionInfo);
1707
1770
  console.log("[SDK Debug] ========================================");
1708
1771
  }
1709
- window.parent.postMessage({ id: requestId, ...request }, targetOrigin);
1772
+ port.postMessage({ id: requestId, ...request });
1710
1773
  });
1711
1774
  }
1712
1775
  async function sendInvoke(method, params, config, _log) {
@@ -1725,11 +1788,6 @@ function createMessageHandler(config, pendingRequests, extensionInfo, onEvent) {
1725
1788
  return (event) => {
1726
1789
  if (config.debug) {
1727
1790
  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
1791
  console.log("[SDK Debug] Event data:", event.data);
1734
1792
  console.log("[SDK Debug] Extension info loaded:", !!extensionInfo());
1735
1793
  console.log(
@@ -1737,12 +1795,6 @@ function createMessageHandler(config, pendingRequests, extensionInfo, onEvent) {
1737
1795
  pendingRequests.size
1738
1796
  );
1739
1797
  }
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
1798
  const data = event.data;
1747
1799
  if ("id" in data && pendingRequests.has(data.id)) {
1748
1800
  if (config.debug) {
@@ -1964,6 +2016,13 @@ var HaexVaultSdk = class {
1964
2016
  this.reactiveSubscribers = /* @__PURE__ */ new Set();
1965
2017
  // Handlers
1966
2018
  this.messageHandler = null;
2019
+ /**
2020
+ * MessagePort obtained from the main window during iframe-mode handshake.
2021
+ * `null` until `initIframe()` completes successfully. Every outbound
2022
+ * request in iframe mode flows through this port; `sendPostMessage` rejects
2023
+ * if called before the handshake finishes.
2024
+ */
2025
+ this.hostPort = null;
1967
2026
  this.setupPromise = null;
1968
2027
  this.setupHook = null;
1969
2028
  // Public APIs
@@ -2137,7 +2196,15 @@ var HaexVaultSdk = class {
2137
2196
  return sendInvoke(method, paramsWithCredentials, this.config, this.log.bind(this));
2138
2197
  }
2139
2198
  const requestId = generateRequestId(++this.requestCounter);
2140
- return sendPostMessage(method, resolvedParams, requestId, this.config, this._extensionInfo, this.pendingRequests);
2199
+ return sendPostMessage(
2200
+ method,
2201
+ resolvedParams,
2202
+ requestId,
2203
+ this.config,
2204
+ this._extensionInfo,
2205
+ this.pendingRequests,
2206
+ this.hostPort
2207
+ );
2141
2208
  }
2142
2209
  // ==========================================================================
2143
2210
  // Private: Initialization
@@ -2204,7 +2271,7 @@ var HaexVaultSdk = class {
2204
2271
  () => this._extensionInfo,
2205
2272
  this.handleEvent.bind(this)
2206
2273
  );
2207
- const { context } = await initIframeMode(
2274
+ const { context, port } = await initIframeMode(
2208
2275
  {
2209
2276
  config: this.config,
2210
2277
  state: {
@@ -2236,6 +2303,7 @@ var HaexVaultSdk = class {
2236
2303
  this.messageHandler,
2237
2304
  this.request.bind(this)
2238
2305
  );
2306
+ this.hostPort = port;
2239
2307
  if (this.config.manifest) {
2240
2308
  this._extensionInfo = {
2241
2309
  publicKey: this.config.manifest.publicKey,