@haex-space/vault-sdk 3.2.7 → 3.3.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.
- package/dist/{client-exZiz0Ph.d.ts → client-BW3ayV19.d.mts} +83 -2
- package/dist/{client-Bbm83Oy6.d.mts → client-Cm23j1wm.d.ts} +83 -2
- package/dist/index.d.mts +30 -6
- package/dist/index.d.ts +30 -6
- package/dist/index.js +186 -221
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +184 -222
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +185 -224
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +185 -224
- package/dist/react.mjs.map +1 -1
- package/dist/runtime/nuxt.plugin.client.d.mts +2 -2
- package/dist/runtime/nuxt.plugin.client.d.ts +2 -2
- package/dist/runtime/nuxt.plugin.client.js +185 -224
- package/dist/runtime/nuxt.plugin.client.js.map +1 -1
- package/dist/runtime/nuxt.plugin.client.mjs +185 -224
- package/dist/runtime/nuxt.plugin.client.mjs.map +1 -1
- package/dist/svelte.d.mts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +185 -224
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +185 -224
- package/dist/svelte.mjs.map +1 -1
- package/dist/{types-CDMBvvjl.d.mts → types-fHuxbqa4.d.mts} +13 -1
- package/dist/{types-CDMBvvjl.d.ts → types-fHuxbqa4.d.ts} +13 -1
- package/dist/vue.d.mts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +185 -224
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +185 -224
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as nuxt_app from 'nuxt/app';
|
|
2
2
|
import { ShallowRef } from 'vue';
|
|
3
|
-
import { H as HaexVaultSdk } from '../client-
|
|
4
|
-
import { A as ApplicationContext } from '../types-
|
|
3
|
+
import { H as HaexVaultSdk } from '../client-BW3ayV19.mjs';
|
|
4
|
+
import { A as ApplicationContext } from '../types-fHuxbqa4.mjs';
|
|
5
5
|
import 'drizzle-orm/sqlite-proxy';
|
|
6
6
|
|
|
7
7
|
declare const _default: nuxt_app.Plugin<{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as nuxt_app from 'nuxt/app';
|
|
2
2
|
import { ShallowRef } from 'vue';
|
|
3
|
-
import { H as HaexVaultSdk } from '../client-
|
|
4
|
-
import { A as ApplicationContext } from '../types-
|
|
3
|
+
import { H as HaexVaultSdk } from '../client-Cm23j1wm.js';
|
|
4
|
+
import { A as ApplicationContext } from '../types-fHuxbqa4.js';
|
|
5
5
|
import 'drizzle-orm/sqlite-proxy';
|
|
6
6
|
|
|
7
7
|
declare const _default: nuxt_app.Plugin<{
|
|
@@ -15,16 +15,21 @@ var HAEXTENSION_EVENTS = {
|
|
|
15
15
|
/** File system change detected (from native file watcher) */
|
|
16
16
|
FILE_CHANGED: "filesync:file-changed",
|
|
17
17
|
/** Tables have been updated via sync (CRDT pull from server) */
|
|
18
|
-
SYNC_TABLES_UPDATED: "haextension:sync:tables-updated"
|
|
18
|
+
SYNC_TABLES_UPDATED: "haextension:sync:tables-updated",
|
|
19
|
+
/** A runtime permission prompt was resolved (granted/denied) by the user.
|
|
20
|
+
* The SDK uses this to auto-retry the original request; extensions may also
|
|
21
|
+
* subscribe via `client.on(HAEXTENSION_EVENTS.PERMISSION_RESOLVED, ...)`. */
|
|
22
|
+
PERMISSION_RESOLVED: "extension:permission-resolved"
|
|
23
|
+
};
|
|
24
|
+
var NOTIFICATION_EVENTS = {
|
|
25
|
+
/** A click on one of this extension's notifications (body or action button). */
|
|
26
|
+
CLICK: "haextension:notification:click"
|
|
19
27
|
};
|
|
20
28
|
var EXTERNAL_EVENTS = {
|
|
21
29
|
/** External request from authorized client */
|
|
22
30
|
REQUEST: "haextension:external:request",
|
|
23
31
|
/** AI action request (tool calls from AI assistant) */
|
|
24
|
-
ACTION_REQUEST: "haextension:action:request"
|
|
25
|
-
/** New external client requesting authorization */
|
|
26
|
-
AUTHORIZATION_REQUEST: "external:authorization-request"
|
|
27
|
-
};
|
|
32
|
+
ACTION_REQUEST: "haextension:action:request"};
|
|
28
33
|
var SHELL_EVENTS = {
|
|
29
34
|
/** PTY output data from a shell session */
|
|
30
35
|
OUTPUT: "shell:output",
|
|
@@ -38,6 +43,9 @@ var TABLE_SEPARATOR = "__";
|
|
|
38
43
|
function getTableName(publicKey, extensionName, tableName) {
|
|
39
44
|
return `${publicKey}${TABLE_SEPARATOR}${extensionName}${TABLE_SEPARATOR}${tableName}`;
|
|
40
45
|
}
|
|
46
|
+
function isPermissionPromptError(error) {
|
|
47
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === 1004 /* PROMPT_REQUIRED */;
|
|
48
|
+
}
|
|
41
49
|
var HaexVaultSdkError = class extends Error {
|
|
42
50
|
constructor(code, messageKey, details) {
|
|
43
51
|
super(messageKey);
|
|
@@ -301,6 +309,14 @@ var MAIL_COMMANDS = {
|
|
|
301
309
|
buildRfc822: "extension_mail_build_rfc822"
|
|
302
310
|
};
|
|
303
311
|
|
|
312
|
+
// src/commands/notifications.ts
|
|
313
|
+
var NOTIFICATION_COMMANDS = {
|
|
314
|
+
/** Show an OS notification. Returns the assigned notification id. */
|
|
315
|
+
show: "extension_notifications_show",
|
|
316
|
+
/** Dismiss a previously shown notification (only own notifications). */
|
|
317
|
+
dismiss: "extension_notifications_dismiss"
|
|
318
|
+
};
|
|
319
|
+
|
|
304
320
|
// src/api/storage.ts
|
|
305
321
|
var StorageAPI = class {
|
|
306
322
|
constructor(client) {
|
|
@@ -1400,6 +1416,38 @@ var MailAPI = class {
|
|
|
1400
1416
|
}
|
|
1401
1417
|
};
|
|
1402
1418
|
|
|
1419
|
+
// src/api/notifications.ts
|
|
1420
|
+
var NotificationsAPI = class {
|
|
1421
|
+
constructor(client) {
|
|
1422
|
+
this.client = client;
|
|
1423
|
+
}
|
|
1424
|
+
/** Show a notification. Returns its id so it can be dismissed later. */
|
|
1425
|
+
async show(opts) {
|
|
1426
|
+
return this.client.request(NOTIFICATION_COMMANDS.show, {
|
|
1427
|
+
options: opts
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
/** Dismiss a previously shown notification (only own notifications). */
|
|
1431
|
+
async dismiss(id) {
|
|
1432
|
+
return this.client.request(NOTIFICATION_COMMANDS.dismiss, { id });
|
|
1433
|
+
}
|
|
1434
|
+
/**
|
|
1435
|
+
* Listen for clicks on this extension's notifications. Useful when the
|
|
1436
|
+
* extension is already open and wants to react in-app (e.g. router.push the
|
|
1437
|
+
* `path`) instead of relying on the host to focus the webview.
|
|
1438
|
+
*
|
|
1439
|
+
* Returns an unsubscribe function.
|
|
1440
|
+
*/
|
|
1441
|
+
onClick(handler) {
|
|
1442
|
+
const wrapped = (event) => {
|
|
1443
|
+
const data = event.data;
|
|
1444
|
+
if (data) handler(data);
|
|
1445
|
+
};
|
|
1446
|
+
this.client.on(NOTIFICATION_EVENTS.CLICK, wrapped);
|
|
1447
|
+
return () => this.client.off(NOTIFICATION_EVENTS.CLICK, wrapped);
|
|
1448
|
+
}
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1403
1451
|
// src/messages.ts
|
|
1404
1452
|
var HAEXSPACE_MESSAGE_TYPES = {
|
|
1405
1453
|
/** Debug message for development/troubleshooting */
|
|
@@ -1608,6 +1656,21 @@ async function initNativeMode(ctx, log, onEvent, onContextChange) {
|
|
|
1608
1656
|
await setupTauriEventListeners(ctx, log, onEvent, onContextChange);
|
|
1609
1657
|
return { extensionInfo, context };
|
|
1610
1658
|
}
|
|
1659
|
+
async function forwardEvent(listen, log, onEvent, listenOptions, eventName, shape) {
|
|
1660
|
+
try {
|
|
1661
|
+
await listen(eventName, (event) => {
|
|
1662
|
+
if (event.payload == null) {
|
|
1663
|
+
log(`Event '${eventName}' received with no payload`);
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
const extra = shape ? shape(event.payload) : { data: event.payload };
|
|
1667
|
+
onEvent({ type: eventName, timestamp: Date.now(), ...extra });
|
|
1668
|
+
}, listenOptions);
|
|
1669
|
+
log(`Listener registered: ${eventName}`);
|
|
1670
|
+
} catch (error) {
|
|
1671
|
+
log(`Failed to register listener '${eventName}':`, error);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1611
1674
|
async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
|
|
1612
1675
|
const { listen } = getTauriEvent();
|
|
1613
1676
|
const webviewLabel = getCurrentWebviewLabel();
|
|
@@ -1639,207 +1702,30 @@ async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
|
|
|
1639
1702
|
} catch (error) {
|
|
1640
1703
|
log("Failed to setup context change listener:", error);
|
|
1641
1704
|
}
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
type: EXTERNAL_EVENTS.ACTION_REQUEST,
|
|
1667
|
-
data: event.payload,
|
|
1668
|
-
timestamp: Date.now()
|
|
1669
|
-
});
|
|
1670
|
-
} else {
|
|
1671
|
-
log("AI action request event has no payload!");
|
|
1672
|
-
}
|
|
1673
|
-
}, listenOptions);
|
|
1674
|
-
log("AI action request listener registered successfully");
|
|
1675
|
-
} catch (error) {
|
|
1676
|
-
log("Failed to setup AI action request listener:", error);
|
|
1677
|
-
}
|
|
1678
|
-
log("Registering file change listener for:", HAEXTENSION_EVENTS.FILE_CHANGED);
|
|
1679
|
-
try {
|
|
1680
|
-
await listen(HAEXTENSION_EVENTS.FILE_CHANGED, (event) => {
|
|
1681
|
-
log("File change event received:", event.payload);
|
|
1682
|
-
if (event.payload) {
|
|
1683
|
-
const payload = event.payload;
|
|
1684
|
-
onEvent({
|
|
1685
|
-
type: HAEXTENSION_EVENTS.FILE_CHANGED,
|
|
1686
|
-
ruleId: payload.ruleId,
|
|
1687
|
-
changeType: payload.changeType,
|
|
1688
|
-
path: payload.path,
|
|
1689
|
-
timestamp: Date.now()
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
}, listenOptions);
|
|
1693
|
-
log("File change listener registered successfully");
|
|
1694
|
-
} catch (error) {
|
|
1695
|
-
log("Failed to setup file change listener:", error);
|
|
1696
|
-
}
|
|
1697
|
-
log("Registering sync tables updated listener for:", HAEXTENSION_EVENTS.SYNC_TABLES_UPDATED);
|
|
1698
|
-
try {
|
|
1699
|
-
await listen(HAEXTENSION_EVENTS.SYNC_TABLES_UPDATED, (event) => {
|
|
1700
|
-
log("Sync tables updated event received:", event.payload);
|
|
1701
|
-
if (event.payload) {
|
|
1702
|
-
const payload = event.payload;
|
|
1703
|
-
onEvent({
|
|
1704
|
-
type: HAEXTENSION_EVENTS.SYNC_TABLES_UPDATED,
|
|
1705
|
-
data: { tables: payload.tables },
|
|
1706
|
-
timestamp: Date.now()
|
|
1707
|
-
});
|
|
1708
|
-
}
|
|
1709
|
-
}, listenOptions);
|
|
1710
|
-
log("Sync tables updated listener registered successfully");
|
|
1711
|
-
} catch (error) {
|
|
1712
|
-
log("Failed to setup sync tables updated listener:", error);
|
|
1713
|
-
}
|
|
1714
|
-
log("Setting up LocalSend event listeners");
|
|
1715
|
-
try {
|
|
1716
|
-
await setupLocalSendEventListeners(log, onEvent, listenOptions);
|
|
1717
|
-
log("LocalSend event listeners setup complete");
|
|
1718
|
-
} catch (error) {
|
|
1719
|
-
log("Failed to setup LocalSend event listeners:", error);
|
|
1720
|
-
}
|
|
1721
|
-
log("Setting up Shell event listeners");
|
|
1722
|
-
try {
|
|
1723
|
-
await listen(SHELL_EVENTS.OUTPUT, (event) => {
|
|
1724
|
-
if (event.payload) {
|
|
1725
|
-
const payload = event.payload;
|
|
1726
|
-
onEvent({
|
|
1727
|
-
type: SHELL_EVENTS.OUTPUT,
|
|
1728
|
-
timestamp: Date.now(),
|
|
1729
|
-
sessionId: payload.sessionId,
|
|
1730
|
-
data: payload.data
|
|
1731
|
-
});
|
|
1732
|
-
}
|
|
1733
|
-
}, listenOptions);
|
|
1734
|
-
log("Shell output listener registered");
|
|
1735
|
-
await listen(SHELL_EVENTS.EXIT, (event) => {
|
|
1736
|
-
if (event.payload) {
|
|
1737
|
-
const payload = event.payload;
|
|
1738
|
-
onEvent({
|
|
1739
|
-
type: SHELL_EVENTS.EXIT,
|
|
1740
|
-
timestamp: Date.now(),
|
|
1741
|
-
sessionId: payload.sessionId,
|
|
1742
|
-
exitCode: payload.exitCode
|
|
1743
|
-
});
|
|
1744
|
-
}
|
|
1745
|
-
}, listenOptions);
|
|
1746
|
-
log("Shell exit listener registered");
|
|
1747
|
-
} catch (error) {
|
|
1748
|
-
log("Failed to setup Shell event listeners:", error);
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
async function setupLocalSendEventListeners(log, onEvent, listenOptions) {
|
|
1752
|
-
const { listen } = getTauriEvent();
|
|
1753
|
-
try {
|
|
1754
|
-
await listen(LOCALSEND_EVENTS.deviceDiscovered, (event) => {
|
|
1755
|
-
log("LocalSend device discovered:", event.payload);
|
|
1756
|
-
if (event.payload) {
|
|
1757
|
-
onEvent({
|
|
1758
|
-
type: LOCALSEND_EVENTS.deviceDiscovered,
|
|
1759
|
-
data: event.payload,
|
|
1760
|
-
timestamp: Date.now()
|
|
1761
|
-
});
|
|
1762
|
-
}
|
|
1763
|
-
}, listenOptions);
|
|
1764
|
-
log("LocalSend device discovered listener registered");
|
|
1765
|
-
} catch (error) {
|
|
1766
|
-
log("Failed to setup LocalSend device discovered listener:", error);
|
|
1767
|
-
}
|
|
1768
|
-
try {
|
|
1769
|
-
await listen(LOCALSEND_EVENTS.deviceLost, (event) => {
|
|
1770
|
-
log("LocalSend device lost:", event.payload);
|
|
1771
|
-
if (event.payload) {
|
|
1772
|
-
onEvent({
|
|
1773
|
-
type: LOCALSEND_EVENTS.deviceLost,
|
|
1774
|
-
data: event.payload,
|
|
1775
|
-
timestamp: Date.now()
|
|
1776
|
-
});
|
|
1777
|
-
}
|
|
1778
|
-
}, listenOptions);
|
|
1779
|
-
log("LocalSend device lost listener registered");
|
|
1780
|
-
} catch (error) {
|
|
1781
|
-
log("Failed to setup LocalSend device lost listener:", error);
|
|
1782
|
-
}
|
|
1783
|
-
try {
|
|
1784
|
-
await listen(LOCALSEND_EVENTS.transferRequest, (event) => {
|
|
1785
|
-
log("LocalSend transfer request:", event.payload);
|
|
1786
|
-
if (event.payload) {
|
|
1787
|
-
onEvent({
|
|
1788
|
-
type: LOCALSEND_EVENTS.transferRequest,
|
|
1789
|
-
data: event.payload,
|
|
1790
|
-
timestamp: Date.now()
|
|
1791
|
-
});
|
|
1792
|
-
}
|
|
1793
|
-
}, listenOptions);
|
|
1794
|
-
log("LocalSend transfer request listener registered");
|
|
1795
|
-
} catch (error) {
|
|
1796
|
-
log("Failed to setup LocalSend transfer request listener:", error);
|
|
1797
|
-
}
|
|
1798
|
-
try {
|
|
1799
|
-
await listen(LOCALSEND_EVENTS.transferProgress, (event) => {
|
|
1800
|
-
log("LocalSend transfer progress event:", event);
|
|
1801
|
-
if (event.payload) {
|
|
1802
|
-
onEvent({
|
|
1803
|
-
type: LOCALSEND_EVENTS.transferProgress,
|
|
1804
|
-
data: event.payload,
|
|
1805
|
-
timestamp: Date.now()
|
|
1806
|
-
});
|
|
1807
|
-
}
|
|
1808
|
-
}, listenOptions);
|
|
1809
|
-
log("LocalSend transfer progress listener registered");
|
|
1810
|
-
} catch (error) {
|
|
1811
|
-
log("Failed to setup LocalSend transfer progress listener:", error);
|
|
1812
|
-
}
|
|
1813
|
-
try {
|
|
1814
|
-
await listen(LOCALSEND_EVENTS.transferComplete, (event) => {
|
|
1815
|
-
log("LocalSend transfer complete:", event.payload);
|
|
1816
|
-
if (event.payload) {
|
|
1817
|
-
onEvent({
|
|
1818
|
-
type: LOCALSEND_EVENTS.transferComplete,
|
|
1819
|
-
data: event.payload,
|
|
1820
|
-
timestamp: Date.now()
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
}, listenOptions);
|
|
1824
|
-
log("LocalSend transfer complete listener registered");
|
|
1825
|
-
} catch (error) {
|
|
1826
|
-
log("Failed to setup LocalSend transfer complete listener:", error);
|
|
1827
|
-
}
|
|
1828
|
-
try {
|
|
1829
|
-
await listen(LOCALSEND_EVENTS.transferFailed, (event) => {
|
|
1830
|
-
log("LocalSend transfer failed:", event.payload);
|
|
1831
|
-
if (event.payload) {
|
|
1832
|
-
onEvent({
|
|
1833
|
-
type: LOCALSEND_EVENTS.transferFailed,
|
|
1834
|
-
data: event.payload,
|
|
1835
|
-
timestamp: Date.now()
|
|
1836
|
-
});
|
|
1837
|
-
}
|
|
1838
|
-
}, listenOptions);
|
|
1839
|
-
log("LocalSend transfer failed listener registered");
|
|
1840
|
-
} catch (error) {
|
|
1841
|
-
log("Failed to setup LocalSend transfer failed listener:", error);
|
|
1842
|
-
}
|
|
1705
|
+
for (const eventName of [
|
|
1706
|
+
HAEXTENSION_EVENTS.PERMISSION_RESOLVED,
|
|
1707
|
+
EXTERNAL_EVENTS.REQUEST,
|
|
1708
|
+
EXTERNAL_EVENTS.ACTION_REQUEST,
|
|
1709
|
+
NOTIFICATION_EVENTS.CLICK,
|
|
1710
|
+
...Object.values(LOCALSEND_EVENTS)
|
|
1711
|
+
]) {
|
|
1712
|
+
await forwardEvent(listen, log, onEvent, listenOptions, eventName);
|
|
1713
|
+
}
|
|
1714
|
+
await forwardEvent(listen, log, onEvent, listenOptions, HAEXTENSION_EVENTS.SYNC_TABLES_UPDATED, (payload) => ({
|
|
1715
|
+
data: { tables: payload.tables }
|
|
1716
|
+
}));
|
|
1717
|
+
await forwardEvent(listen, log, onEvent, listenOptions, HAEXTENSION_EVENTS.FILE_CHANGED, (payload) => {
|
|
1718
|
+
const { ruleId, changeType, path } = payload;
|
|
1719
|
+
return { ruleId, changeType, path };
|
|
1720
|
+
});
|
|
1721
|
+
await forwardEvent(listen, log, onEvent, listenOptions, SHELL_EVENTS.OUTPUT, (payload) => {
|
|
1722
|
+
const { sessionId, data } = payload;
|
|
1723
|
+
return { sessionId, data };
|
|
1724
|
+
});
|
|
1725
|
+
await forwardEvent(listen, log, onEvent, listenOptions, SHELL_EVENTS.EXIT, (payload) => {
|
|
1726
|
+
const { sessionId, exitCode } = payload;
|
|
1727
|
+
return { sessionId, exitCode };
|
|
1728
|
+
});
|
|
1843
1729
|
}
|
|
1844
1730
|
async function initIframeMode(ctx, log, messageHandler) {
|
|
1845
1731
|
if (!isInIframe()) {
|
|
@@ -2183,6 +2069,68 @@ var AI_COMMANDS = {
|
|
|
2183
2069
|
actionRespond: "ai_action_respond"
|
|
2184
2070
|
};
|
|
2185
2071
|
|
|
2072
|
+
// src/client/permissionRetry.ts
|
|
2073
|
+
var PERMISSION_DECISION_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2074
|
+
var MAX_PERMISSION_RETRIES = 3;
|
|
2075
|
+
function permissionKey(resourceType, action, target) {
|
|
2076
|
+
return `${resourceType}:${action}:${target}`;
|
|
2077
|
+
}
|
|
2078
|
+
var PermissionWaiterRegistry = class {
|
|
2079
|
+
constructor() {
|
|
2080
|
+
this.waiters = /* @__PURE__ */ new Map();
|
|
2081
|
+
}
|
|
2082
|
+
/** Wait for a decision on `key`; resolves "timeout" if none arrives in time. */
|
|
2083
|
+
wait(key, timeoutMs = PERMISSION_DECISION_TIMEOUT_MS) {
|
|
2084
|
+
return new Promise((resolve) => {
|
|
2085
|
+
const set = this.waiters.get(key) ?? /* @__PURE__ */ new Set();
|
|
2086
|
+
this.waiters.set(key, set);
|
|
2087
|
+
const settle = (outcome) => {
|
|
2088
|
+
if (!set.has(callback)) return;
|
|
2089
|
+
set.delete(callback);
|
|
2090
|
+
if (set.size === 0) this.waiters.delete(key);
|
|
2091
|
+
clearTimeout(timer);
|
|
2092
|
+
resolve(outcome);
|
|
2093
|
+
};
|
|
2094
|
+
const callback = (outcome) => settle(outcome);
|
|
2095
|
+
const timer = setTimeout(() => settle("timeout"), timeoutMs);
|
|
2096
|
+
set.add(callback);
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
/** Resolve everyone waiting on `key` with the user's decision. */
|
|
2100
|
+
resolve(key, decision) {
|
|
2101
|
+
const set = this.waiters.get(key);
|
|
2102
|
+
if (!set) return;
|
|
2103
|
+
for (const callback of [...set]) callback(decision);
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
function toDeniedError(error) {
|
|
2107
|
+
return { ...error, code: 1002 /* DENIED */ };
|
|
2108
|
+
}
|
|
2109
|
+
async function withPermissionRetry(send, registry, log, timeoutMs = PERMISSION_DECISION_TIMEOUT_MS) {
|
|
2110
|
+
for (let attempt = 0; ; attempt++) {
|
|
2111
|
+
try {
|
|
2112
|
+
return await send();
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
if (!isPermissionPromptError(error) || attempt >= MAX_PERMISSION_RETRIES) {
|
|
2115
|
+
throw error;
|
|
2116
|
+
}
|
|
2117
|
+
const key = permissionKey(error.resourceType, error.action, error.target);
|
|
2118
|
+
log(`Permission prompt required for ${key} \u2014 waiting for user decision`);
|
|
2119
|
+
const outcome = await registry.wait(key, timeoutMs);
|
|
2120
|
+
if (outcome === "granted") {
|
|
2121
|
+
log(`Permission ${key} granted \u2014 retrying request`);
|
|
2122
|
+
continue;
|
|
2123
|
+
}
|
|
2124
|
+
if (outcome === "denied") {
|
|
2125
|
+
log(`Permission ${key} denied`);
|
|
2126
|
+
throw toDeniedError(error);
|
|
2127
|
+
}
|
|
2128
|
+
log(`Permission ${key} prompt timed out`);
|
|
2129
|
+
throw error;
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2186
2134
|
// src/client.ts
|
|
2187
2135
|
var HaexVaultSdk = class {
|
|
2188
2136
|
constructor(config = {}) {
|
|
@@ -2198,6 +2146,7 @@ var HaexVaultSdk = class {
|
|
|
2198
2146
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
2199
2147
|
this.externalRequestHandlers = /* @__PURE__ */ new Map();
|
|
2200
2148
|
this.reactiveSubscribers = /* @__PURE__ */ new Set();
|
|
2149
|
+
this.permissionWaiters = new PermissionWaiterRegistry();
|
|
2201
2150
|
// Handlers
|
|
2202
2151
|
this.messageHandler = null;
|
|
2203
2152
|
/**
|
|
@@ -2233,7 +2182,16 @@ var HaexVaultSdk = class {
|
|
|
2233
2182
|
this.shell = new ShellAPI(this);
|
|
2234
2183
|
this.passwords = new PasswordsAPI(this);
|
|
2235
2184
|
this.mail = new MailAPI(this);
|
|
2185
|
+
this.notifications = new NotificationsAPI(this);
|
|
2236
2186
|
installConsoleForwarding(this.config.debug);
|
|
2187
|
+
this.on(HAEXTENSION_EVENTS.PERMISSION_RESOLVED, (event) => {
|
|
2188
|
+
const data = event.data;
|
|
2189
|
+
if (!data) return;
|
|
2190
|
+
this.permissionWaiters.resolve(
|
|
2191
|
+
permissionKey(data.resourceType, data.action, data.target),
|
|
2192
|
+
data.decision === "denied" ? "denied" : "granted"
|
|
2193
|
+
);
|
|
2194
|
+
});
|
|
2237
2195
|
this.readyPromise = new Promise((resolve, reject) => {
|
|
2238
2196
|
this.resolveReady = resolve;
|
|
2239
2197
|
this.rejectReady = reject;
|
|
@@ -2382,24 +2340,27 @@ var HaexVaultSdk = class {
|
|
|
2382
2340
|
// ==========================================================================
|
|
2383
2341
|
async request(method, params) {
|
|
2384
2342
|
const resolvedParams = params ?? {};
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2343
|
+
const send = () => {
|
|
2344
|
+
if (this.isNativeWindow && hasTauri()) {
|
|
2345
|
+
const paramsWithCredentials = {
|
|
2346
|
+
...resolvedParams,
|
|
2347
|
+
publicKey: this._extensionInfo?.publicKey,
|
|
2348
|
+
name: this._extensionInfo?.name
|
|
2349
|
+
};
|
|
2350
|
+
return sendInvoke(method, paramsWithCredentials, this.config, this.log.bind(this));
|
|
2351
|
+
}
|
|
2352
|
+
const requestId = generateRequestId(++this.requestCounter);
|
|
2353
|
+
return sendPostMessage(
|
|
2354
|
+
method,
|
|
2355
|
+
resolvedParams,
|
|
2356
|
+
requestId,
|
|
2357
|
+
this.config,
|
|
2358
|
+
this._extensionInfo,
|
|
2359
|
+
this.pendingRequests,
|
|
2360
|
+
this.hostPort
|
|
2361
|
+
);
|
|
2362
|
+
};
|
|
2363
|
+
return withPermissionRetry(send, this.permissionWaiters, this.log.bind(this));
|
|
2403
2364
|
}
|
|
2404
2365
|
// ==========================================================================
|
|
2405
2366
|
// Private: Initialization
|