@haex-space/vault-sdk 2.3.15 → 2.4.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-ChH7wiuU.d.ts → client-BSdAg7D1.d.ts} +25 -95
- package/dist/{client-8eGxojZ1.d.mts → client-ClYpUDoI.d.mts} +25 -95
- package/dist/index.d.mts +75 -5
- package/dist/index.d.ts +75 -5
- package/dist/index.js +1090 -678
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1087 -678
- 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 +1024 -655
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +1024 -655
- 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 +1033 -664
- package/dist/runtime/nuxt.plugin.client.js.map +1 -1
- package/dist/runtime/nuxt.plugin.client.mjs +1033 -664
- 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 +1026 -657
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +1026 -657
- package/dist/svelte.mjs.map +1 -1
- package/dist/{types-DBF83o_W.d.mts → types-CmPqOcLB.d.mts} +8 -8
- package/dist/{types-DBF83o_W.d.ts → types-CmPqOcLB.d.ts} +8 -8
- package/dist/vue.d.mts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +1024 -655
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +1024 -655
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/vue.js
CHANGED
|
@@ -342,6 +342,46 @@ var HAEXTENSION_EVENTS = {
|
|
|
342
342
|
EXTERNAL_REQUEST: "haextension:external:request"
|
|
343
343
|
};
|
|
344
344
|
|
|
345
|
+
// src/types.ts
|
|
346
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
347
|
+
var TABLE_SEPARATOR = "__";
|
|
348
|
+
function getTableName(publicKey, extensionName, tableName) {
|
|
349
|
+
return `${publicKey}${TABLE_SEPARATOR}${extensionName}${TABLE_SEPARATOR}${tableName}`;
|
|
350
|
+
}
|
|
351
|
+
var HaexVaultSdkError = class extends Error {
|
|
352
|
+
constructor(code, messageKey, details) {
|
|
353
|
+
super(messageKey);
|
|
354
|
+
this.code = code;
|
|
355
|
+
this.messageKey = messageKey;
|
|
356
|
+
this.details = details;
|
|
357
|
+
this.name = "HaexVaultSdkError";
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Get localized error message
|
|
361
|
+
* @param locale - Locale code (e.g., 'en', 'de')
|
|
362
|
+
* @param translations - Translation object
|
|
363
|
+
*/
|
|
364
|
+
getLocalizedMessage(locale = "en", translations) {
|
|
365
|
+
if (!translations || !translations[locale]) {
|
|
366
|
+
return this.messageKey;
|
|
367
|
+
}
|
|
368
|
+
let message = translations[locale][this.messageKey] || this.messageKey;
|
|
369
|
+
if (this.details) {
|
|
370
|
+
Object.entries(this.details).forEach(([key, value]) => {
|
|
371
|
+
message = message.replace(`{${key}}`, String(value));
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return message;
|
|
375
|
+
}
|
|
376
|
+
toJSON() {
|
|
377
|
+
return {
|
|
378
|
+
code: this.code,
|
|
379
|
+
message: this.messageKey,
|
|
380
|
+
details: this.details
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
345
385
|
// src/methods.ts
|
|
346
386
|
var HAEXTENSION_METHODS = {
|
|
347
387
|
context: {
|
|
@@ -403,46 +443,6 @@ var HAEXTENSION_METHODS = {
|
|
|
403
443
|
}
|
|
404
444
|
};
|
|
405
445
|
|
|
406
|
-
// src/types.ts
|
|
407
|
-
var DEFAULT_TIMEOUT = 3e4;
|
|
408
|
-
var TABLE_SEPARATOR = "__";
|
|
409
|
-
function getTableName(publicKey, extensionName, tableName) {
|
|
410
|
-
return `${publicKey}${TABLE_SEPARATOR}${extensionName}${TABLE_SEPARATOR}${tableName}`;
|
|
411
|
-
}
|
|
412
|
-
var HaexHubError = class extends Error {
|
|
413
|
-
constructor(code, messageKey, details) {
|
|
414
|
-
super(messageKey);
|
|
415
|
-
this.code = code;
|
|
416
|
-
this.messageKey = messageKey;
|
|
417
|
-
this.details = details;
|
|
418
|
-
this.name = "HaexHubError";
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* Get localized error message
|
|
422
|
-
* @param locale - Locale code (e.g., 'en', 'de')
|
|
423
|
-
* @param translations - Translation object
|
|
424
|
-
*/
|
|
425
|
-
getLocalizedMessage(locale = "en", translations) {
|
|
426
|
-
if (!translations || !translations[locale]) {
|
|
427
|
-
return this.messageKey;
|
|
428
|
-
}
|
|
429
|
-
let message = translations[locale][this.messageKey] || this.messageKey;
|
|
430
|
-
if (this.details) {
|
|
431
|
-
Object.entries(this.details).forEach(([key, value]) => {
|
|
432
|
-
message = message.replace(`{${key}}`, String(value));
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
return message;
|
|
436
|
-
}
|
|
437
|
-
toJSON() {
|
|
438
|
-
return {
|
|
439
|
-
code: this.code,
|
|
440
|
-
message: this.messageKey,
|
|
441
|
-
details: this.details
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
|
|
446
446
|
// src/api/storage.ts
|
|
447
447
|
var StorageAPI = class {
|
|
448
448
|
constructor(client) {
|
|
@@ -985,548 +985,543 @@ var PermissionsAPI = class {
|
|
|
985
985
|
return response.status === "granted";
|
|
986
986
|
}
|
|
987
987
|
};
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
this._context = null;
|
|
998
|
-
this.reactiveSubscribers = /* @__PURE__ */ new Set();
|
|
999
|
-
this.isNativeWindow = false;
|
|
1000
|
-
// Wird im Konstruktor initialisiert
|
|
1001
|
-
this.setupPromise = null;
|
|
1002
|
-
this.setupHook = null;
|
|
1003
|
-
this._setupCompleted = false;
|
|
1004
|
-
this.orm = null;
|
|
1005
|
-
this.config = {
|
|
1006
|
-
debug: config.debug ?? false,
|
|
1007
|
-
timeout: config.timeout ?? DEFAULT_TIMEOUT,
|
|
1008
|
-
manifest: config.manifest
|
|
1009
|
-
};
|
|
1010
|
-
this.storage = new StorageAPI(this);
|
|
1011
|
-
this.database = new DatabaseAPI(this);
|
|
1012
|
-
this.filesystem = new FilesystemAPI(this);
|
|
1013
|
-
this.web = new WebAPI(this);
|
|
1014
|
-
this.permissions = new PermissionsAPI(this);
|
|
1015
|
-
installConsoleForwarding(this.config.debug);
|
|
1016
|
-
this.readyPromise = new Promise((resolve) => {
|
|
1017
|
-
this.resolveReady = resolve;
|
|
1018
|
-
});
|
|
1019
|
-
this.init();
|
|
988
|
+
|
|
989
|
+
// src/client/tableName.ts
|
|
990
|
+
function validatePublicKey(publicKey) {
|
|
991
|
+
if (!publicKey || typeof publicKey !== "string" || publicKey.trim() === "") {
|
|
992
|
+
throw new HaexVaultSdkError(
|
|
993
|
+
"INVALID_PUBLIC_KEY" /* INVALID_PUBLIC_KEY */,
|
|
994
|
+
"errors.invalid_public_key",
|
|
995
|
+
{ publicKey }
|
|
996
|
+
);
|
|
1020
997
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
998
|
+
}
|
|
999
|
+
function validateExtensionName(extensionName) {
|
|
1000
|
+
if (!extensionName || !/^[a-z][a-z0-9-]*$/i.test(extensionName)) {
|
|
1001
|
+
throw new HaexVaultSdkError(
|
|
1002
|
+
"INVALID_EXTENSION_NAME" /* INVALID_EXTENSION_NAME */,
|
|
1003
|
+
"errors.invalid_extension_name",
|
|
1004
|
+
{ extensionName }
|
|
1005
|
+
);
|
|
1027
1006
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1007
|
+
if (extensionName.includes(TABLE_SEPARATOR)) {
|
|
1008
|
+
throw new HaexVaultSdkError(
|
|
1009
|
+
"INVALID_EXTENSION_NAME" /* INVALID_EXTENSION_NAME */,
|
|
1010
|
+
"errors.extension_name_contains_separator",
|
|
1011
|
+
{ extensionName, separator: TABLE_SEPARATOR }
|
|
1012
|
+
);
|
|
1033
1013
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
throw new Error("Setup hook already registered");
|
|
1042
|
-
}
|
|
1043
|
-
this.setupHook = setupFn;
|
|
1014
|
+
}
|
|
1015
|
+
function validateTableName(tableName) {
|
|
1016
|
+
if (!tableName || typeof tableName !== "string") {
|
|
1017
|
+
throw new HaexVaultSdkError(
|
|
1018
|
+
"INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
|
|
1019
|
+
"errors.table_name_empty"
|
|
1020
|
+
);
|
|
1044
1021
|
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
await this.readyPromise;
|
|
1052
|
-
if (!this.setupHook || this.setupCompleted) {
|
|
1053
|
-
return;
|
|
1054
|
-
}
|
|
1055
|
-
if (!this.setupPromise) {
|
|
1056
|
-
this.setupPromise = this.runSetupAsync();
|
|
1057
|
-
}
|
|
1058
|
-
return this.setupPromise;
|
|
1022
|
+
if (tableName.includes(TABLE_SEPARATOR)) {
|
|
1023
|
+
throw new HaexVaultSdkError(
|
|
1024
|
+
"INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
|
|
1025
|
+
"errors.table_name_contains_separator",
|
|
1026
|
+
{ tableName, separator: TABLE_SEPARATOR }
|
|
1027
|
+
);
|
|
1059
1028
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
this.log("[HaexSpace] Setup completed successfully");
|
|
1067
|
-
this.notifySubscribers();
|
|
1068
|
-
} catch (error) {
|
|
1069
|
-
this.log("[HaexSpace] Setup failed:", error);
|
|
1070
|
-
throw error;
|
|
1071
|
-
}
|
|
1029
|
+
if (!/^[a-z][a-z0-9-_]*$/i.test(tableName)) {
|
|
1030
|
+
throw new HaexVaultSdkError(
|
|
1031
|
+
"INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
|
|
1032
|
+
"errors.table_name_format",
|
|
1033
|
+
{ tableName }
|
|
1034
|
+
);
|
|
1072
1035
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
initializeDatabase(schema) {
|
|
1080
|
-
if (!this._extensionInfo) {
|
|
1081
|
-
throw new HaexHubError(
|
|
1082
|
-
"EXTENSION_INFO_UNAVAILABLE" /* EXTENSION_INFO_UNAVAILABLE */,
|
|
1083
|
-
"errors.client_not_ready"
|
|
1084
|
-
);
|
|
1085
|
-
}
|
|
1086
|
-
const dbInstance = sqliteProxy.drizzle(
|
|
1087
|
-
async (sql, params, method) => {
|
|
1088
|
-
try {
|
|
1089
|
-
if (method === "run" || method === "all") {
|
|
1090
|
-
const result2 = await this.request(
|
|
1091
|
-
HAEXTENSION_METHODS.database.execute,
|
|
1092
|
-
{
|
|
1093
|
-
query: sql,
|
|
1094
|
-
params
|
|
1095
|
-
}
|
|
1096
|
-
);
|
|
1097
|
-
if (method === "all") {
|
|
1098
|
-
return { rows: result2.rows || [] };
|
|
1099
|
-
}
|
|
1100
|
-
if (result2.rows && Array.isArray(result2.rows) && result2.rows.length > 0) {
|
|
1101
|
-
return { rows: result2.rows };
|
|
1102
|
-
}
|
|
1103
|
-
return result2;
|
|
1104
|
-
}
|
|
1105
|
-
const result = await this.request(HAEXTENSION_METHODS.database.query, {
|
|
1106
|
-
query: sql,
|
|
1107
|
-
params
|
|
1108
|
-
});
|
|
1109
|
-
const rows = result.rows;
|
|
1110
|
-
if (method === "get") {
|
|
1111
|
-
return { rows: rows.length > 0 ? rows.at(0) : void 0 };
|
|
1112
|
-
}
|
|
1113
|
-
return { rows };
|
|
1114
|
-
} catch (error) {
|
|
1115
|
-
this.log("Database operation failed:", error);
|
|
1116
|
-
throw error;
|
|
1117
|
-
}
|
|
1118
|
-
},
|
|
1119
|
-
{
|
|
1120
|
-
schema,
|
|
1121
|
-
logger: false
|
|
1122
|
-
}
|
|
1036
|
+
}
|
|
1037
|
+
function getExtensionTableName(extensionInfo2, tableName) {
|
|
1038
|
+
if (!extensionInfo2) {
|
|
1039
|
+
throw new HaexVaultSdkError(
|
|
1040
|
+
"EXTENSION_INFO_UNAVAILABLE" /* EXTENSION_INFO_UNAVAILABLE */,
|
|
1041
|
+
"errors.extension_info_unavailable"
|
|
1123
1042
|
);
|
|
1124
|
-
this.orm = dbInstance;
|
|
1125
|
-
return dbInstance;
|
|
1126
1043
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1044
|
+
validateTableName(tableName);
|
|
1045
|
+
const { publicKey, name } = extensionInfo2;
|
|
1046
|
+
return `"${getTableName(publicKey, name, tableName)}"`;
|
|
1047
|
+
}
|
|
1048
|
+
function getDependencyTableName(publicKey, extensionName, tableName) {
|
|
1049
|
+
validatePublicKey(publicKey);
|
|
1050
|
+
validateExtensionName(extensionName);
|
|
1051
|
+
validateTableName(tableName);
|
|
1052
|
+
return `"${getTableName(publicKey, extensionName, tableName)}"`;
|
|
1053
|
+
}
|
|
1054
|
+
function parseTableName(fullTableName) {
|
|
1055
|
+
let cleanTableName = fullTableName;
|
|
1056
|
+
if (cleanTableName.startsWith('"') && cleanTableName.endsWith('"')) {
|
|
1057
|
+
cleanTableName = cleanTableName.slice(1, -1);
|
|
1129
1058
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1059
|
+
const parts = cleanTableName.split(TABLE_SEPARATOR);
|
|
1060
|
+
if (parts.length !== 3) {
|
|
1061
|
+
return null;
|
|
1132
1062
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
return
|
|
1136
|
-
this.reactiveSubscribers.delete(callback);
|
|
1137
|
-
};
|
|
1063
|
+
const [publicKey, extensionName, tableName] = parts;
|
|
1064
|
+
if (!publicKey || !extensionName || !tableName) {
|
|
1065
|
+
return null;
|
|
1138
1066
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1067
|
+
return {
|
|
1068
|
+
publicKey,
|
|
1069
|
+
extensionName,
|
|
1070
|
+
tableName
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/client/init.ts
|
|
1075
|
+
function isInIframe() {
|
|
1076
|
+
return window.self !== window.top;
|
|
1077
|
+
}
|
|
1078
|
+
function hasTauri() {
|
|
1079
|
+
return typeof window.__TAURI__ !== "undefined";
|
|
1080
|
+
}
|
|
1081
|
+
function getTauriCore() {
|
|
1082
|
+
return window.__TAURI__.core;
|
|
1083
|
+
}
|
|
1084
|
+
function getTauriEvent() {
|
|
1085
|
+
return window.__TAURI__.event;
|
|
1086
|
+
}
|
|
1087
|
+
async function initNativeMode(ctx, log, onEvent, onContextChange) {
|
|
1088
|
+
const { invoke } = getTauriCore();
|
|
1089
|
+
const extensionInfo2 = await invoke("webview_extension_get_info");
|
|
1090
|
+
const context2 = await invoke("webview_extension_context_get");
|
|
1091
|
+
ctx.state.isNativeWindow = true;
|
|
1092
|
+
ctx.state.initialized = true;
|
|
1093
|
+
ctx.state.extensionInfo = extensionInfo2;
|
|
1094
|
+
ctx.state.context = context2;
|
|
1095
|
+
log("HaexVault SDK initialized in native WebViewWindow mode");
|
|
1096
|
+
log("Extension info:", extensionInfo2);
|
|
1097
|
+
log("Application context:", context2);
|
|
1098
|
+
await setupTauriEventListeners(ctx, log, onEvent, onContextChange);
|
|
1099
|
+
return { extensionInfo: extensionInfo2, context: context2 };
|
|
1100
|
+
}
|
|
1101
|
+
async function setupTauriEventListeners(ctx, log, onEvent, onContextChange) {
|
|
1102
|
+
const { listen } = getTauriEvent();
|
|
1103
|
+
console.log("[HaexVault SDK] Setting up Tauri event listener for:", HAEXTENSION_EVENTS.CONTEXT_CHANGED);
|
|
1104
|
+
try {
|
|
1105
|
+
await listen(HAEXTENSION_EVENTS.CONTEXT_CHANGED, (event) => {
|
|
1106
|
+
console.log("[HaexVault SDK] Received Tauri event:", HAEXTENSION_EVENTS.CONTEXT_CHANGED, event);
|
|
1107
|
+
log("Received context change event:", event);
|
|
1108
|
+
const payload = event.payload;
|
|
1109
|
+
if (payload?.context) {
|
|
1110
|
+
ctx.state.context = payload.context;
|
|
1111
|
+
console.log("[HaexVault SDK] Updated context to:", ctx.state.context);
|
|
1112
|
+
onContextChange(payload.context);
|
|
1113
|
+
onEvent({
|
|
1114
|
+
type: HAEXTENSION_EVENTS.CONTEXT_CHANGED,
|
|
1115
|
+
data: { context: ctx.state.context },
|
|
1116
|
+
timestamp: Date.now()
|
|
1117
|
+
});
|
|
1118
|
+
} else {
|
|
1119
|
+
console.warn("[HaexVault SDK] Event received but no context in payload:", event);
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
console.log("[HaexVault SDK] Context change listener registered successfully");
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
console.error("[HaexVault SDK] Failed to setup context change listener:", error);
|
|
1125
|
+
log("Failed to setup context change listener:", error);
|
|
1141
1126
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1127
|
+
try {
|
|
1128
|
+
await listen(HAEXTENSION_EVENTS.EXTERNAL_REQUEST, (event) => {
|
|
1129
|
+
log("Received external request event:", event);
|
|
1130
|
+
if (event.payload) {
|
|
1131
|
+
onEvent({
|
|
1132
|
+
type: HAEXTENSION_EVENTS.EXTERNAL_REQUEST,
|
|
1133
|
+
data: event.payload,
|
|
1134
|
+
timestamp: Date.now()
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
console.log("[HaexVault SDK] External request listener registered successfully");
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
console.error("[HaexVault SDK] Failed to setup external request listener:", error);
|
|
1141
|
+
log("Failed to setup external request listener:", error);
|
|
1144
1142
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1143
|
+
}
|
|
1144
|
+
async function initIframeMode(ctx, log, messageHandler, request) {
|
|
1145
|
+
if (!isInIframe()) {
|
|
1146
|
+
throw new HaexVaultSdkError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
|
|
1147
|
+
}
|
|
1148
|
+
ctx.handlers.messageHandler = messageHandler;
|
|
1149
|
+
window.addEventListener("message", messageHandler);
|
|
1150
|
+
ctx.state.isNativeWindow = false;
|
|
1151
|
+
ctx.state.initialized = true;
|
|
1152
|
+
log("HaexVault SDK initialized in iframe mode");
|
|
1153
|
+
if (ctx.config.manifest) {
|
|
1154
|
+
ctx.state.extensionInfo = {
|
|
1155
|
+
publicKey: ctx.config.manifest.publicKey,
|
|
1156
|
+
name: ctx.config.manifest.name,
|
|
1157
|
+
version: ctx.config.manifest.version,
|
|
1158
|
+
displayName: ctx.config.manifest.name
|
|
1159
|
+
};
|
|
1160
|
+
log("Extension info loaded from manifest:", ctx.state.extensionInfo);
|
|
1155
1161
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1162
|
+
sendDebugInfo(ctx.config);
|
|
1163
|
+
const context2 = await request(HAEXTENSION_METHODS.context.get);
|
|
1164
|
+
ctx.state.context = context2;
|
|
1165
|
+
log("Application context received:", context2);
|
|
1166
|
+
return { context: context2 };
|
|
1167
|
+
}
|
|
1168
|
+
function sendDebugInfo(config) {
|
|
1169
|
+
if (!config.debug) return;
|
|
1170
|
+
if (typeof window === "undefined" || !window.parent) return;
|
|
1171
|
+
const debugInfo = `SDK Debug:
|
|
1172
|
+
window.parent exists: ${!!window.parent}
|
|
1173
|
+
window.parent === window: ${window.parent === window}
|
|
1174
|
+
window.self === window.top: ${window.self === window.top}`;
|
|
1175
|
+
try {
|
|
1176
|
+
window.parent.postMessage({
|
|
1177
|
+
type: HAEXSPACE_MESSAGE_TYPES.DEBUG,
|
|
1178
|
+
data: debugInfo
|
|
1179
|
+
}, "*");
|
|
1180
|
+
} catch (e) {
|
|
1181
|
+
alert(debugInfo + `
|
|
1182
|
+
postMessage error: ${e}`);
|
|
1161
1183
|
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// src/commands.ts
|
|
1187
|
+
var TAURI_COMMANDS = {
|
|
1188
|
+
database: {
|
|
1189
|
+
query: "webview_extension_db_query",
|
|
1190
|
+
execute: "webview_extension_db_execute",
|
|
1191
|
+
registerMigrations: "webview_extension_db_register_migrations"
|
|
1192
|
+
},
|
|
1193
|
+
permissions: {
|
|
1194
|
+
checkWeb: "webview_extension_check_web_permission",
|
|
1195
|
+
checkDatabase: "webview_extension_check_database_permission",
|
|
1196
|
+
checkFilesystem: "webview_extension_check_filesystem_permission"
|
|
1197
|
+
},
|
|
1198
|
+
web: {
|
|
1199
|
+
open: "webview_extension_web_open",
|
|
1200
|
+
fetch: "webview_extension_web_request"
|
|
1201
|
+
},
|
|
1202
|
+
filesystem: {
|
|
1203
|
+
saveFile: "webview_extension_fs_save_file",
|
|
1204
|
+
openFile: "webview_extension_fs_open_file",
|
|
1205
|
+
showImage: "webview_extension_fs_show_image"
|
|
1206
|
+
},
|
|
1207
|
+
external: {
|
|
1208
|
+
respond: "webview_extension_external_respond"
|
|
1209
|
+
},
|
|
1210
|
+
filesync: {
|
|
1211
|
+
// Spaces
|
|
1212
|
+
listSpaces: "filesync_list_spaces",
|
|
1213
|
+
createSpace: "filesync_create_space",
|
|
1214
|
+
deleteSpace: "filesync_delete_space",
|
|
1215
|
+
// Files
|
|
1216
|
+
listFiles: "filesync_list_files",
|
|
1217
|
+
getFile: "filesync_get_file",
|
|
1218
|
+
uploadFile: "filesync_upload_file",
|
|
1219
|
+
downloadFile: "filesync_download_file",
|
|
1220
|
+
deleteFile: "filesync_delete_file",
|
|
1221
|
+
// Backends
|
|
1222
|
+
listBackends: "filesync_list_backends",
|
|
1223
|
+
addBackend: "filesync_add_backend",
|
|
1224
|
+
removeBackend: "filesync_remove_backend",
|
|
1225
|
+
testBackend: "filesync_test_backend",
|
|
1226
|
+
// Sync Rules
|
|
1227
|
+
listSyncRules: "filesync_list_sync_rules",
|
|
1228
|
+
addSyncRule: "filesync_add_sync_rule",
|
|
1229
|
+
removeSyncRule: "filesync_remove_sync_rule",
|
|
1230
|
+
// Sync Operations
|
|
1231
|
+
getSyncStatus: "filesync_get_sync_status",
|
|
1232
|
+
triggerSync: "filesync_trigger_sync",
|
|
1233
|
+
pauseSync: "filesync_pause_sync",
|
|
1234
|
+
resumeSync: "filesync_resume_sync",
|
|
1235
|
+
// Conflict Resolution
|
|
1236
|
+
resolveConflict: "filesync_resolve_conflict",
|
|
1237
|
+
// UI Helpers
|
|
1238
|
+
selectFolder: "filesync_select_folder"
|
|
1180
1239
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1240
|
+
};
|
|
1241
|
+
|
|
1242
|
+
// src/transport/handlers/database.ts
|
|
1243
|
+
var databaseHandlers = {
|
|
1244
|
+
[HAEXTENSION_METHODS.database.query]: {
|
|
1245
|
+
command: TAURI_COMMANDS.database.query,
|
|
1246
|
+
args: (p) => ({
|
|
1247
|
+
query: p.query,
|
|
1248
|
+
params: p.params || []
|
|
1249
|
+
})
|
|
1250
|
+
},
|
|
1251
|
+
[HAEXTENSION_METHODS.database.execute]: {
|
|
1252
|
+
command: TAURI_COMMANDS.database.execute,
|
|
1253
|
+
args: (p) => ({
|
|
1254
|
+
query: p.query,
|
|
1255
|
+
params: p.params || []
|
|
1256
|
+
})
|
|
1257
|
+
},
|
|
1258
|
+
[HAEXTENSION_METHODS.database.registerMigrations]: {
|
|
1259
|
+
command: TAURI_COMMANDS.database.registerMigrations,
|
|
1260
|
+
args: (p) => ({
|
|
1261
|
+
extensionVersion: p.extensionVersion,
|
|
1262
|
+
migrations: p.migrations
|
|
1263
|
+
})
|
|
1194
1264
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1267
|
+
// src/transport/handlers/permissions.ts
|
|
1268
|
+
var permissionsHandlers = {
|
|
1269
|
+
"permissions.web.check": {
|
|
1270
|
+
command: TAURI_COMMANDS.permissions.checkWeb,
|
|
1271
|
+
args: (p) => ({
|
|
1272
|
+
url: p.url
|
|
1273
|
+
})
|
|
1274
|
+
},
|
|
1275
|
+
"permissions.database.check": {
|
|
1276
|
+
command: TAURI_COMMANDS.permissions.checkDatabase,
|
|
1277
|
+
args: (p) => ({
|
|
1278
|
+
resource: p.resource,
|
|
1279
|
+
operation: p.operation
|
|
1280
|
+
})
|
|
1281
|
+
},
|
|
1282
|
+
"permissions.filesystem.check": {
|
|
1283
|
+
command: TAURI_COMMANDS.permissions.checkFilesystem,
|
|
1284
|
+
args: (p) => ({
|
|
1285
|
+
path: p.path,
|
|
1286
|
+
actionStr: p.action
|
|
1287
|
+
})
|
|
1200
1288
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
)
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1289
|
+
};
|
|
1290
|
+
|
|
1291
|
+
// src/transport/handlers/web.ts
|
|
1292
|
+
var webHandlers = {
|
|
1293
|
+
[HAEXTENSION_METHODS.application.open]: {
|
|
1294
|
+
command: TAURI_COMMANDS.web.open,
|
|
1295
|
+
args: (p) => ({
|
|
1296
|
+
url: p.url
|
|
1297
|
+
})
|
|
1298
|
+
},
|
|
1299
|
+
[HAEXTENSION_METHODS.web.fetch]: {
|
|
1300
|
+
command: TAURI_COMMANDS.web.fetch,
|
|
1301
|
+
args: (p) => ({
|
|
1302
|
+
url: p.url,
|
|
1303
|
+
method: p.method,
|
|
1304
|
+
headers: p.headers,
|
|
1305
|
+
body: p.body
|
|
1306
|
+
})
|
|
1214
1307
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
const response = await this.request(
|
|
1241
|
-
"permissions.database.check",
|
|
1242
|
-
{
|
|
1243
|
-
resource,
|
|
1244
|
-
operation
|
|
1245
|
-
}
|
|
1246
|
-
);
|
|
1247
|
-
return response.status === "granted";
|
|
1248
|
-
}
|
|
1249
|
-
async respondToSearch(requestId, results) {
|
|
1250
|
-
await this.request("search.respond", {
|
|
1251
|
-
requestId,
|
|
1252
|
-
results
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
/**
|
|
1256
|
-
* Register a handler for external requests (from browser extensions, CLI, servers, etc.)
|
|
1257
|
-
*
|
|
1258
|
-
* @param action - The action/method name to handle (e.g., "get-logins", "get-totp")
|
|
1259
|
-
* @param handler - Function that processes the request and returns a response
|
|
1260
|
-
* @returns Unsubscribe function to remove the handler
|
|
1261
|
-
*
|
|
1262
|
-
* @example
|
|
1263
|
-
* ```typescript
|
|
1264
|
-
* client.onExternalRequest("get-logins", async (request) => {
|
|
1265
|
-
* const entries = await getMatchingEntries(request.payload.url);
|
|
1266
|
-
* return {
|
|
1267
|
-
* requestId: request.requestId,
|
|
1268
|
-
* success: true,
|
|
1269
|
-
* data: { entries }
|
|
1270
|
-
* };
|
|
1271
|
-
* });
|
|
1272
|
-
* ```
|
|
1273
|
-
*/
|
|
1274
|
-
onExternalRequest(action, handler) {
|
|
1275
|
-
this.externalRequestHandlers.set(action, handler);
|
|
1276
|
-
this.log(`[ExternalRequest] Registered handler for action: ${action}`);
|
|
1277
|
-
return () => {
|
|
1278
|
-
this.externalRequestHandlers.delete(action);
|
|
1279
|
-
this.log(`[ExternalRequest] Unregistered handler for action: ${action}`);
|
|
1280
|
-
};
|
|
1281
|
-
}
|
|
1282
|
-
/**
|
|
1283
|
-
* Send a response to an external request back to haex-vault
|
|
1284
|
-
* This is called internally after a handler processes a request
|
|
1285
|
-
*/
|
|
1286
|
-
async respondToExternalRequest(response) {
|
|
1287
|
-
await this.request("external.respond", response);
|
|
1288
|
-
}
|
|
1289
|
-
async request(method, params) {
|
|
1290
|
-
const resolvedParams = params ?? {};
|
|
1291
|
-
if (this.isNativeWindow && typeof window.__TAURI__ !== "undefined") {
|
|
1292
|
-
return this.invoke(method, resolvedParams);
|
|
1293
|
-
}
|
|
1294
|
-
return this.postMessage(method, resolvedParams);
|
|
1295
|
-
}
|
|
1296
|
-
async postMessage(method, params) {
|
|
1297
|
-
const requestId = this.generateRequestId();
|
|
1298
|
-
const request = {
|
|
1299
|
-
method,
|
|
1300
|
-
params,
|
|
1301
|
-
timestamp: Date.now()
|
|
1302
|
-
};
|
|
1303
|
-
return new Promise((resolve, reject) => {
|
|
1304
|
-
const timeout = setTimeout(() => {
|
|
1305
|
-
this.pendingRequests.delete(requestId);
|
|
1306
|
-
reject(
|
|
1307
|
-
new HaexHubError("TIMEOUT" /* TIMEOUT */, "errors.timeout", {
|
|
1308
|
-
timeout: this.config.timeout
|
|
1309
|
-
})
|
|
1310
|
-
);
|
|
1311
|
-
}, this.config.timeout);
|
|
1312
|
-
this.pendingRequests.set(requestId, { resolve, reject, timeout });
|
|
1313
|
-
const targetOrigin = "*";
|
|
1314
|
-
if (this.config.debug) {
|
|
1315
|
-
console.log("[SDK Debug] ========== Sending Request ==========");
|
|
1316
|
-
console.log("[SDK Debug] Request ID:", requestId);
|
|
1317
|
-
console.log("[SDK Debug] Method:", request.method);
|
|
1318
|
-
console.log("[SDK Debug] Params:", request.params);
|
|
1319
|
-
console.log("[SDK Debug] Target origin:", targetOrigin);
|
|
1320
|
-
console.log("[SDK Debug] Extension info:", this._extensionInfo);
|
|
1321
|
-
console.log("[SDK Debug] ========================================");
|
|
1322
|
-
}
|
|
1323
|
-
window.parent.postMessage({ id: requestId, ...request }, targetOrigin);
|
|
1324
|
-
});
|
|
1325
|
-
}
|
|
1326
|
-
async invoke(method, params) {
|
|
1327
|
-
const { invoke } = window.__TAURI__.core;
|
|
1328
|
-
if (this.config.debug) {
|
|
1329
|
-
console.log("[SDK Debug] ========== Invoke Request ==========");
|
|
1330
|
-
console.log("[SDK Debug] Method:", method);
|
|
1331
|
-
console.log("[SDK Debug] Params:", params);
|
|
1332
|
-
console.log("[SDK Debug] =======================================");
|
|
1333
|
-
}
|
|
1334
|
-
switch (method) {
|
|
1335
|
-
case HAEXTENSION_METHODS.database.query:
|
|
1336
|
-
return invoke("webview_extension_db_query", {
|
|
1337
|
-
query: params.query,
|
|
1338
|
-
params: params.params || []
|
|
1339
|
-
});
|
|
1340
|
-
case HAEXTENSION_METHODS.database.execute:
|
|
1341
|
-
return invoke("webview_extension_db_execute", {
|
|
1342
|
-
query: params.query,
|
|
1343
|
-
params: params.params || []
|
|
1344
|
-
});
|
|
1345
|
-
case "permissions.web.check":
|
|
1346
|
-
return invoke("webview_extension_check_web_permission", {
|
|
1347
|
-
url: params.url
|
|
1348
|
-
});
|
|
1349
|
-
case "permissions.database.check":
|
|
1350
|
-
return invoke("webview_extension_check_database_permission", {
|
|
1351
|
-
resource: params.resource,
|
|
1352
|
-
operation: params.operation
|
|
1353
|
-
});
|
|
1354
|
-
case "permissions.filesystem.check":
|
|
1355
|
-
return invoke("webview_extension_check_filesystem_permission", {
|
|
1356
|
-
path: params.path,
|
|
1357
|
-
actionStr: params.action
|
|
1358
|
-
});
|
|
1359
|
-
case HAEXTENSION_METHODS.application.open:
|
|
1360
|
-
return invoke("webview_extension_web_open", {
|
|
1361
|
-
url: params.url
|
|
1362
|
-
});
|
|
1363
|
-
case HAEXTENSION_METHODS.web.fetch:
|
|
1364
|
-
return invoke("webview_extension_web_request", {
|
|
1365
|
-
url: params.url,
|
|
1366
|
-
method: params.method,
|
|
1367
|
-
headers: params.headers,
|
|
1368
|
-
body: params.body
|
|
1369
|
-
});
|
|
1370
|
-
case HAEXTENSION_METHODS.filesystem.saveFile:
|
|
1371
|
-
return invoke("webview_extension_fs_save_file", {
|
|
1372
|
-
data: params.data,
|
|
1373
|
-
defaultPath: params.defaultPath,
|
|
1374
|
-
title: params.title,
|
|
1375
|
-
filters: params.filters
|
|
1376
|
-
});
|
|
1377
|
-
case HAEXTENSION_METHODS.filesystem.openFile:
|
|
1378
|
-
return invoke("webview_extension_fs_open_file", {
|
|
1379
|
-
data: params.data,
|
|
1380
|
-
fileName: params.fileName
|
|
1381
|
-
});
|
|
1382
|
-
case HAEXTENSION_METHODS.database.registerMigrations:
|
|
1383
|
-
return invoke("webview_extension_db_register_migrations", {
|
|
1384
|
-
extensionVersion: params.extensionVersion,
|
|
1385
|
-
migrations: params.migrations
|
|
1386
|
-
});
|
|
1387
|
-
case "external.respond":
|
|
1388
|
-
return invoke("webview_extension_external_respond", {
|
|
1389
|
-
requestId: params.requestId,
|
|
1390
|
-
success: params.success,
|
|
1391
|
-
data: params.data,
|
|
1392
|
-
error: params.error
|
|
1393
|
-
});
|
|
1394
|
-
default:
|
|
1395
|
-
throw new HaexHubError(
|
|
1396
|
-
"METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
|
|
1397
|
-
"errors.method_not_found",
|
|
1398
|
-
{ method }
|
|
1399
|
-
);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
on(eventType, callback) {
|
|
1403
|
-
if (!this.eventListeners.has(eventType)) {
|
|
1404
|
-
this.eventListeners.set(eventType, /* @__PURE__ */ new Set());
|
|
1405
|
-
}
|
|
1406
|
-
this.eventListeners.get(eventType).add(callback);
|
|
1308
|
+
};
|
|
1309
|
+
|
|
1310
|
+
// src/transport/handlers/filesystem.ts
|
|
1311
|
+
var filesystemHandlers = {
|
|
1312
|
+
[HAEXTENSION_METHODS.filesystem.saveFile]: {
|
|
1313
|
+
command: TAURI_COMMANDS.filesystem.saveFile,
|
|
1314
|
+
args: (p) => ({
|
|
1315
|
+
data: p.data,
|
|
1316
|
+
defaultPath: p.defaultPath,
|
|
1317
|
+
title: p.title,
|
|
1318
|
+
filters: p.filters
|
|
1319
|
+
})
|
|
1320
|
+
},
|
|
1321
|
+
[HAEXTENSION_METHODS.filesystem.openFile]: {
|
|
1322
|
+
command: TAURI_COMMANDS.filesystem.openFile,
|
|
1323
|
+
args: (p) => ({
|
|
1324
|
+
data: p.data,
|
|
1325
|
+
fileName: p.fileName
|
|
1326
|
+
})
|
|
1327
|
+
},
|
|
1328
|
+
[HAEXTENSION_METHODS.filesystem.showImage]: {
|
|
1329
|
+
command: TAURI_COMMANDS.filesystem.showImage,
|
|
1330
|
+
args: (p) => ({
|
|
1331
|
+
dataUrl: p.dataUrl
|
|
1332
|
+
})
|
|
1407
1333
|
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1336
|
+
// src/transport/handlers/external.ts
|
|
1337
|
+
var externalHandlers = {
|
|
1338
|
+
"external.respond": {
|
|
1339
|
+
command: TAURI_COMMANDS.external.respond,
|
|
1340
|
+
args: (p) => ({
|
|
1341
|
+
requestId: p.requestId,
|
|
1342
|
+
success: p.success,
|
|
1343
|
+
data: p.data,
|
|
1344
|
+
error: p.error
|
|
1345
|
+
})
|
|
1413
1346
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1349
|
+
// src/transport/handlers/filesync.ts
|
|
1350
|
+
var filesyncHandlers = {
|
|
1351
|
+
// ==========================================================================
|
|
1352
|
+
// Spaces
|
|
1353
|
+
// ==========================================================================
|
|
1354
|
+
[HAEXTENSION_METHODS.filesystem.sync.listSpaces]: {
|
|
1355
|
+
command: TAURI_COMMANDS.filesync.listSpaces,
|
|
1356
|
+
args: () => ({})
|
|
1357
|
+
},
|
|
1358
|
+
[HAEXTENSION_METHODS.filesystem.sync.createSpace]: {
|
|
1359
|
+
command: TAURI_COMMANDS.filesync.createSpace,
|
|
1360
|
+
args: (p) => ({ request: p })
|
|
1361
|
+
},
|
|
1362
|
+
[HAEXTENSION_METHODS.filesystem.sync.deleteSpace]: {
|
|
1363
|
+
command: TAURI_COMMANDS.filesync.deleteSpace,
|
|
1364
|
+
args: (p) => ({ spaceId: p.spaceId })
|
|
1365
|
+
},
|
|
1366
|
+
// ==========================================================================
|
|
1367
|
+
// Files
|
|
1368
|
+
// ==========================================================================
|
|
1369
|
+
[HAEXTENSION_METHODS.filesystem.sync.listFiles]: {
|
|
1370
|
+
command: TAURI_COMMANDS.filesync.listFiles,
|
|
1371
|
+
args: (p) => ({ request: p })
|
|
1372
|
+
},
|
|
1373
|
+
[HAEXTENSION_METHODS.filesystem.sync.getFile]: {
|
|
1374
|
+
command: TAURI_COMMANDS.filesync.getFile,
|
|
1375
|
+
args: (p) => ({ fileId: p.fileId })
|
|
1376
|
+
},
|
|
1377
|
+
[HAEXTENSION_METHODS.filesystem.sync.uploadFile]: {
|
|
1378
|
+
command: TAURI_COMMANDS.filesync.uploadFile,
|
|
1379
|
+
args: (p) => ({ request: p })
|
|
1380
|
+
},
|
|
1381
|
+
[HAEXTENSION_METHODS.filesystem.sync.downloadFile]: {
|
|
1382
|
+
command: TAURI_COMMANDS.filesync.downloadFile,
|
|
1383
|
+
args: (p) => ({ request: p })
|
|
1384
|
+
},
|
|
1385
|
+
[HAEXTENSION_METHODS.filesystem.sync.deleteFile]: {
|
|
1386
|
+
command: TAURI_COMMANDS.filesync.deleteFile,
|
|
1387
|
+
args: (p) => ({ fileId: p.fileId })
|
|
1388
|
+
},
|
|
1389
|
+
// ==========================================================================
|
|
1390
|
+
// Backends
|
|
1391
|
+
// ==========================================================================
|
|
1392
|
+
[HAEXTENSION_METHODS.filesystem.sync.listBackends]: {
|
|
1393
|
+
command: TAURI_COMMANDS.filesync.listBackends,
|
|
1394
|
+
args: () => ({})
|
|
1395
|
+
},
|
|
1396
|
+
[HAEXTENSION_METHODS.filesystem.sync.addBackend]: {
|
|
1397
|
+
command: TAURI_COMMANDS.filesync.addBackend,
|
|
1398
|
+
args: (p) => ({ request: p })
|
|
1399
|
+
},
|
|
1400
|
+
[HAEXTENSION_METHODS.filesystem.sync.removeBackend]: {
|
|
1401
|
+
command: TAURI_COMMANDS.filesync.removeBackend,
|
|
1402
|
+
args: (p) => ({ backendId: p.backendId })
|
|
1403
|
+
},
|
|
1404
|
+
[HAEXTENSION_METHODS.filesystem.sync.testBackend]: {
|
|
1405
|
+
command: TAURI_COMMANDS.filesync.testBackend,
|
|
1406
|
+
args: (p) => ({ backendId: p.backendId })
|
|
1407
|
+
},
|
|
1408
|
+
// ==========================================================================
|
|
1409
|
+
// Sync Rules
|
|
1410
|
+
// ==========================================================================
|
|
1411
|
+
[HAEXTENSION_METHODS.filesystem.sync.listSyncRules]: {
|
|
1412
|
+
command: TAURI_COMMANDS.filesync.listSyncRules,
|
|
1413
|
+
args: () => ({})
|
|
1414
|
+
},
|
|
1415
|
+
[HAEXTENSION_METHODS.filesystem.sync.addSyncRule]: {
|
|
1416
|
+
command: TAURI_COMMANDS.filesync.addSyncRule,
|
|
1417
|
+
args: (p) => ({ request: p })
|
|
1418
|
+
},
|
|
1419
|
+
[HAEXTENSION_METHODS.filesystem.sync.removeSyncRule]: {
|
|
1420
|
+
command: TAURI_COMMANDS.filesync.removeSyncRule,
|
|
1421
|
+
args: (p) => ({ ruleId: p.ruleId })
|
|
1422
|
+
},
|
|
1423
|
+
// ==========================================================================
|
|
1424
|
+
// Sync Operations
|
|
1425
|
+
// ==========================================================================
|
|
1426
|
+
[HAEXTENSION_METHODS.filesystem.sync.getSyncStatus]: {
|
|
1427
|
+
command: TAURI_COMMANDS.filesync.getSyncStatus,
|
|
1428
|
+
args: () => ({})
|
|
1429
|
+
},
|
|
1430
|
+
[HAEXTENSION_METHODS.filesystem.sync.triggerSync]: {
|
|
1431
|
+
command: TAURI_COMMANDS.filesync.triggerSync,
|
|
1432
|
+
args: () => ({})
|
|
1433
|
+
},
|
|
1434
|
+
[HAEXTENSION_METHODS.filesystem.sync.pauseSync]: {
|
|
1435
|
+
command: TAURI_COMMANDS.filesync.pauseSync,
|
|
1436
|
+
args: () => ({})
|
|
1437
|
+
},
|
|
1438
|
+
[HAEXTENSION_METHODS.filesystem.sync.resumeSync]: {
|
|
1439
|
+
command: TAURI_COMMANDS.filesync.resumeSync,
|
|
1440
|
+
args: () => ({})
|
|
1441
|
+
},
|
|
1442
|
+
// ==========================================================================
|
|
1443
|
+
// Conflict Resolution
|
|
1444
|
+
// ==========================================================================
|
|
1445
|
+
[HAEXTENSION_METHODS.filesystem.sync.resolveConflict]: {
|
|
1446
|
+
command: TAURI_COMMANDS.filesync.resolveConflict,
|
|
1447
|
+
args: (p) => ({ request: p })
|
|
1448
|
+
},
|
|
1449
|
+
// ==========================================================================
|
|
1450
|
+
// UI Helpers
|
|
1451
|
+
// ==========================================================================
|
|
1452
|
+
[HAEXTENSION_METHODS.filesystem.sync.selectFolder]: {
|
|
1453
|
+
command: TAURI_COMMANDS.filesync.selectFolder,
|
|
1454
|
+
args: () => ({})
|
|
1423
1455
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
if (event.payload) {
|
|
1466
|
-
this.handleEvent({
|
|
1467
|
-
type: HAEXTENSION_EVENTS.EXTERNAL_REQUEST,
|
|
1468
|
-
data: event.payload,
|
|
1469
|
-
timestamp: Date.now()
|
|
1470
|
-
});
|
|
1471
|
-
}
|
|
1472
|
-
});
|
|
1473
|
-
console.log("[HaexSpace SDK] External request listener registered successfully");
|
|
1474
|
-
} catch (error) {
|
|
1475
|
-
console.error("[HaexSpace SDK] Failed to setup external request listener:", error);
|
|
1476
|
-
this.log("Failed to setup external request listener:", error);
|
|
1477
|
-
}
|
|
1478
|
-
this.resolveReady();
|
|
1479
|
-
return;
|
|
1480
|
-
}
|
|
1481
|
-
} catch (error) {
|
|
1482
|
-
this.log("Tauri commands failed, falling back to iframe mode", error);
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
if (window.self === window.top) {
|
|
1486
|
-
throw new HaexHubError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
|
|
1487
|
-
}
|
|
1488
|
-
this.messageHandler = this.handleMessage.bind(this);
|
|
1489
|
-
window.addEventListener("message", this.messageHandler);
|
|
1490
|
-
this.isNativeWindow = false;
|
|
1491
|
-
this.initialized = true;
|
|
1492
|
-
this.log("HaexSpace SDK initialized in iframe mode");
|
|
1493
|
-
try {
|
|
1494
|
-
if (this.config.manifest) {
|
|
1495
|
-
this._extensionInfo = {
|
|
1496
|
-
publicKey: this.config.manifest.publicKey,
|
|
1497
|
-
name: this.config.manifest.name,
|
|
1498
|
-
version: this.config.manifest.version,
|
|
1499
|
-
displayName: this.config.manifest.name
|
|
1500
|
-
};
|
|
1501
|
-
this.log("Extension info loaded from manifest:", this._extensionInfo);
|
|
1502
|
-
this.notifySubscribers();
|
|
1503
|
-
}
|
|
1504
|
-
if (typeof window !== "undefined" && window.parent) {
|
|
1505
|
-
const debugInfo = `SDK Debug:
|
|
1506
|
-
window.parent exists: ${!!window.parent}
|
|
1507
|
-
window.parent === window: ${window.parent === window}
|
|
1508
|
-
window.self === window.top: ${window.self === window.top}`;
|
|
1509
|
-
try {
|
|
1510
|
-
window.parent.postMessage({
|
|
1511
|
-
type: HAEXSPACE_MESSAGE_TYPES.DEBUG,
|
|
1512
|
-
data: debugInfo
|
|
1513
|
-
}, "*");
|
|
1514
|
-
} catch (e) {
|
|
1515
|
-
alert(debugInfo + `
|
|
1516
|
-
postMessage error: ${e}`);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
this._context = await this.request(HAEXTENSION_METHODS.context.get);
|
|
1520
|
-
this.log("Application context received:", this._context);
|
|
1521
|
-
this.notifySubscribers();
|
|
1522
|
-
this.resolveReady();
|
|
1523
|
-
} catch (error) {
|
|
1524
|
-
this.log("Failed to load extension info or context:", error);
|
|
1525
|
-
throw error;
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
// src/transport/handlers/index.ts
|
|
1459
|
+
var allHandlers = {
|
|
1460
|
+
...databaseHandlers,
|
|
1461
|
+
...permissionsHandlers,
|
|
1462
|
+
...webHandlers,
|
|
1463
|
+
...filesystemHandlers,
|
|
1464
|
+
...externalHandlers,
|
|
1465
|
+
...filesyncHandlers
|
|
1466
|
+
};
|
|
1467
|
+
|
|
1468
|
+
// src/client/transport.ts
|
|
1469
|
+
function generateRequestId(counter) {
|
|
1470
|
+
return `req_${counter}`;
|
|
1471
|
+
}
|
|
1472
|
+
function sendPostMessage(method, params, requestId, config, extensionInfo2, pendingRequests) {
|
|
1473
|
+
const request = {
|
|
1474
|
+
method,
|
|
1475
|
+
params,
|
|
1476
|
+
timestamp: Date.now()
|
|
1477
|
+
};
|
|
1478
|
+
return new Promise((resolve, reject) => {
|
|
1479
|
+
const timeout = setTimeout(() => {
|
|
1480
|
+
pendingRequests.delete(requestId);
|
|
1481
|
+
reject(
|
|
1482
|
+
new HaexVaultSdkError("TIMEOUT" /* TIMEOUT */, "errors.timeout", {
|
|
1483
|
+
timeout: config.timeout
|
|
1484
|
+
})
|
|
1485
|
+
);
|
|
1486
|
+
}, config.timeout);
|
|
1487
|
+
pendingRequests.set(requestId, { resolve, reject, timeout });
|
|
1488
|
+
const targetOrigin = "*";
|
|
1489
|
+
if (config.debug) {
|
|
1490
|
+
console.log("[SDK Debug] ========== Sending Request ==========");
|
|
1491
|
+
console.log("[SDK Debug] Request ID:", requestId);
|
|
1492
|
+
console.log("[SDK Debug] Method:", request.method);
|
|
1493
|
+
console.log("[SDK Debug] Params:", request.params);
|
|
1494
|
+
console.log("[SDK Debug] Target origin:", targetOrigin);
|
|
1495
|
+
console.log("[SDK Debug] Extension info:", extensionInfo2);
|
|
1496
|
+
console.log("[SDK Debug] ========================================");
|
|
1526
1497
|
}
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1498
|
+
window.parent.postMessage({ id: requestId, ...request }, targetOrigin);
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
async function sendInvoke(method, params, config, log) {
|
|
1502
|
+
const { invoke } = window.__TAURI__.core;
|
|
1503
|
+
if (config.debug) {
|
|
1504
|
+
console.log("[SDK Debug] ========== Invoke Request ==========");
|
|
1505
|
+
console.log("[SDK Debug] Method:", method);
|
|
1506
|
+
console.log("[SDK Debug] Params:", params);
|
|
1507
|
+
console.log("[SDK Debug] =======================================");
|
|
1508
|
+
}
|
|
1509
|
+
const handler = allHandlers[method];
|
|
1510
|
+
if (handler) {
|
|
1511
|
+
const args = handler.args(params);
|
|
1512
|
+
return invoke(handler.command, args);
|
|
1513
|
+
}
|
|
1514
|
+
throw new HaexVaultSdkError(
|
|
1515
|
+
"METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
|
|
1516
|
+
"errors.method_not_found",
|
|
1517
|
+
{ method }
|
|
1518
|
+
);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
// src/client/events.ts
|
|
1522
|
+
function createMessageHandler(config, pendingRequests, extensionInfo2, onEvent) {
|
|
1523
|
+
return (event) => {
|
|
1524
|
+
if (config.debug) {
|
|
1530
1525
|
console.log("[SDK Debug] ========== Message Received ==========");
|
|
1531
1526
|
console.log("[SDK Debug] Event origin:", event.origin);
|
|
1532
1527
|
console.log(
|
|
@@ -1534,160 +1529,534 @@ postMessage error: ${e}`);
|
|
|
1534
1529
|
event.source === window.parent ? "parent window" : "unknown"
|
|
1535
1530
|
);
|
|
1536
1531
|
console.log("[SDK Debug] Event data:", event.data);
|
|
1537
|
-
console.log("[SDK Debug] Extension info loaded:", !!
|
|
1532
|
+
console.log("[SDK Debug] Extension info loaded:", !!extensionInfo2());
|
|
1538
1533
|
console.log(
|
|
1539
1534
|
"[SDK Debug] Pending requests count:",
|
|
1540
|
-
|
|
1535
|
+
pendingRequests.size
|
|
1541
1536
|
);
|
|
1542
1537
|
}
|
|
1543
1538
|
if (event.source !== window.parent) {
|
|
1544
|
-
if (
|
|
1539
|
+
if (config.debug) {
|
|
1545
1540
|
console.error("[SDK Debug] \u274C REJECTED: Message not from parent window!");
|
|
1546
1541
|
}
|
|
1547
1542
|
return;
|
|
1548
1543
|
}
|
|
1549
1544
|
const data = event.data;
|
|
1550
|
-
if ("id" in data &&
|
|
1551
|
-
if (
|
|
1545
|
+
if ("id" in data && pendingRequests.has(data.id)) {
|
|
1546
|
+
if (config.debug) {
|
|
1552
1547
|
console.log("[SDK Debug] \u2705 Found pending request for ID:", data.id);
|
|
1553
1548
|
}
|
|
1554
|
-
const pending =
|
|
1549
|
+
const pending = pendingRequests.get(data.id);
|
|
1555
1550
|
clearTimeout(pending.timeout);
|
|
1556
|
-
|
|
1551
|
+
pendingRequests.delete(data.id);
|
|
1557
1552
|
if (data.error) {
|
|
1558
|
-
if (
|
|
1553
|
+
if (config.debug) {
|
|
1559
1554
|
console.error("[SDK Debug] \u274C Request failed:", data.error);
|
|
1560
1555
|
}
|
|
1561
1556
|
pending.reject(data.error);
|
|
1562
1557
|
} else {
|
|
1563
|
-
if (
|
|
1558
|
+
if (config.debug) {
|
|
1564
1559
|
console.log("[SDK Debug] \u2705 Request succeeded:", data.result);
|
|
1565
1560
|
}
|
|
1566
1561
|
pending.resolve(data.result);
|
|
1567
1562
|
}
|
|
1568
1563
|
return;
|
|
1569
1564
|
}
|
|
1570
|
-
if ("id" in data && !
|
|
1571
|
-
if (
|
|
1565
|
+
if ("id" in data && !pendingRequests.has(data.id)) {
|
|
1566
|
+
if (config.debug) {
|
|
1572
1567
|
console.warn(
|
|
1573
1568
|
"[SDK Debug] \u26A0\uFE0F Received response for unknown request ID:",
|
|
1574
1569
|
data.id
|
|
1575
1570
|
);
|
|
1576
1571
|
console.warn(
|
|
1577
1572
|
"[SDK Debug] Known IDs:",
|
|
1578
|
-
Array.from(
|
|
1573
|
+
Array.from(pendingRequests.keys())
|
|
1579
1574
|
);
|
|
1580
1575
|
}
|
|
1581
1576
|
}
|
|
1582
1577
|
if ("type" in data && data.type) {
|
|
1583
|
-
if (
|
|
1578
|
+
if (config.debug) {
|
|
1584
1579
|
console.log("[SDK Debug] Event received:", data.type);
|
|
1585
1580
|
}
|
|
1586
|
-
|
|
1581
|
+
onEvent(data);
|
|
1587
1582
|
}
|
|
1588
|
-
if (
|
|
1583
|
+
if (config.debug) {
|
|
1589
1584
|
console.log("[SDK Debug] ========== End Message ==========");
|
|
1590
1585
|
}
|
|
1586
|
+
};
|
|
1587
|
+
}
|
|
1588
|
+
function processEvent(event, log, eventListeners, onContextChanged, onExternalRequest) {
|
|
1589
|
+
if (event.type === HAEXTENSION_EVENTS.CONTEXT_CHANGED) {
|
|
1590
|
+
const contextEvent = event;
|
|
1591
|
+
onContextChanged(contextEvent.data.context);
|
|
1592
|
+
log("Context updated:", contextEvent.data.context);
|
|
1593
|
+
}
|
|
1594
|
+
if (event.type === HAEXTENSION_EVENTS.EXTERNAL_REQUEST) {
|
|
1595
|
+
const externalEvent = event;
|
|
1596
|
+
onExternalRequest(externalEvent);
|
|
1597
|
+
return;
|
|
1591
1598
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1599
|
+
emitEvent(event, log, eventListeners);
|
|
1600
|
+
}
|
|
1601
|
+
function emitEvent(event, log, eventListeners) {
|
|
1602
|
+
log("Event received:", event);
|
|
1603
|
+
const listeners = eventListeners.get(event.type);
|
|
1604
|
+
if (listeners) {
|
|
1605
|
+
listeners.forEach((callback) => callback(event));
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
function addEventListener(eventType, callback, eventListeners) {
|
|
1609
|
+
if (!eventListeners.has(eventType)) {
|
|
1610
|
+
eventListeners.set(eventType, /* @__PURE__ */ new Set());
|
|
1611
|
+
}
|
|
1612
|
+
eventListeners.get(eventType).add(callback);
|
|
1613
|
+
}
|
|
1614
|
+
function removeEventListener(eventType, callback, eventListeners) {
|
|
1615
|
+
const listeners = eventListeners.get(eventType);
|
|
1616
|
+
if (listeners) {
|
|
1617
|
+
listeners.delete(callback);
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
1620
|
+
function notifySubscribers(subscribers) {
|
|
1621
|
+
subscribers.forEach((callback) => callback());
|
|
1622
|
+
}
|
|
1623
|
+
function createDrizzleInstance(schema, extensionInfo2, request, log) {
|
|
1624
|
+
if (!extensionInfo2) {
|
|
1625
|
+
throw new HaexVaultSdkError(
|
|
1626
|
+
"EXTENSION_INFO_UNAVAILABLE" /* EXTENSION_INFO_UNAVAILABLE */,
|
|
1627
|
+
"errors.client_not_ready"
|
|
1628
|
+
);
|
|
1629
|
+
}
|
|
1630
|
+
return sqliteProxy.drizzle(
|
|
1631
|
+
async (sql, params, method) => {
|
|
1632
|
+
try {
|
|
1633
|
+
if (method === "run" || method === "all") {
|
|
1634
|
+
const result2 = await request(
|
|
1635
|
+
HAEXTENSION_METHODS.database.execute,
|
|
1636
|
+
{
|
|
1637
|
+
query: sql,
|
|
1638
|
+
params
|
|
1639
|
+
}
|
|
1640
|
+
);
|
|
1641
|
+
if (method === "all") {
|
|
1642
|
+
return { rows: result2.rows || [] };
|
|
1643
|
+
}
|
|
1644
|
+
if (result2.rows && Array.isArray(result2.rows) && result2.rows.length > 0) {
|
|
1645
|
+
return { rows: result2.rows };
|
|
1646
|
+
}
|
|
1647
|
+
return result2;
|
|
1648
|
+
}
|
|
1649
|
+
const result = await request(HAEXTENSION_METHODS.database.query, {
|
|
1650
|
+
query: sql,
|
|
1651
|
+
params
|
|
1652
|
+
});
|
|
1653
|
+
const rows = result.rows;
|
|
1654
|
+
if (method === "get") {
|
|
1655
|
+
return { rows: rows.length > 0 ? rows.at(0) : void 0 };
|
|
1656
|
+
}
|
|
1657
|
+
return { rows };
|
|
1658
|
+
} catch (error) {
|
|
1659
|
+
log("Database operation failed:", error);
|
|
1660
|
+
throw error;
|
|
1661
|
+
}
|
|
1662
|
+
},
|
|
1663
|
+
{
|
|
1664
|
+
schema,
|
|
1665
|
+
logger: false
|
|
1598
1666
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
async function queryRaw(sql, params, request, debug) {
|
|
1670
|
+
const result = await request(
|
|
1671
|
+
HAEXTENSION_METHODS.database.query,
|
|
1672
|
+
{ query: sql, params }
|
|
1673
|
+
);
|
|
1674
|
+
if (debug) {
|
|
1675
|
+
console.log("[SDK query()] Raw result:", JSON.stringify(result, null, 2));
|
|
1676
|
+
}
|
|
1677
|
+
return result.rows;
|
|
1678
|
+
}
|
|
1679
|
+
async function executeRaw(sql, params, request) {
|
|
1680
|
+
const result = await request(
|
|
1681
|
+
HAEXTENSION_METHODS.database.execute,
|
|
1682
|
+
{ query: sql, params }
|
|
1683
|
+
);
|
|
1684
|
+
return {
|
|
1685
|
+
rowsAffected: result.rowsAffected,
|
|
1686
|
+
lastInsertId: result.lastInsertId
|
|
1687
|
+
};
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
// src/client/external.ts
|
|
1691
|
+
function registerExternalHandler(action, handler, handlers, log) {
|
|
1692
|
+
handlers.set(action, handler);
|
|
1693
|
+
log(`[ExternalRequest] Registered handler for action: ${action}`);
|
|
1694
|
+
return () => {
|
|
1695
|
+
handlers.delete(action);
|
|
1696
|
+
log(`[ExternalRequest] Unregistered handler for action: ${action}`);
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
async function handleExternalRequest(request, handlers, respond, log) {
|
|
1700
|
+
log(`[ExternalRequest] Received request: ${request.action} from ${request.publicKey.substring(0, 20)}...`);
|
|
1701
|
+
const handler = handlers.get(request.action);
|
|
1702
|
+
if (!handler) {
|
|
1703
|
+
log(`[ExternalRequest] No handler for action: ${request.action}`);
|
|
1704
|
+
await respond({
|
|
1705
|
+
requestId: request.requestId,
|
|
1706
|
+
success: false,
|
|
1707
|
+
error: `No handler registered for action: ${request.action}`
|
|
1708
|
+
});
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
try {
|
|
1712
|
+
const response = await handler(request);
|
|
1713
|
+
await respond(response);
|
|
1714
|
+
log(`[ExternalRequest] Response sent for: ${request.action}`);
|
|
1715
|
+
} catch (error) {
|
|
1716
|
+
log(`[ExternalRequest] Handler error:`, error);
|
|
1717
|
+
await respond({
|
|
1718
|
+
requestId: request.requestId,
|
|
1719
|
+
success: false,
|
|
1720
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
async function respondToExternalRequest(response, request) {
|
|
1725
|
+
await request("external.respond", response);
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// src/client.ts
|
|
1729
|
+
var HaexVaultClient = class {
|
|
1730
|
+
constructor(config = {}) {
|
|
1731
|
+
// State
|
|
1732
|
+
this.initialized = false;
|
|
1733
|
+
this.isNativeWindow = false;
|
|
1734
|
+
this.requestCounter = 0;
|
|
1735
|
+
this._extensionInfo = null;
|
|
1736
|
+
this._context = null;
|
|
1737
|
+
this._setupCompleted = false;
|
|
1738
|
+
// Collections
|
|
1739
|
+
this.pendingRequests = /* @__PURE__ */ new Map();
|
|
1740
|
+
this.eventListeners = /* @__PURE__ */ new Map();
|
|
1741
|
+
this.externalRequestHandlers = /* @__PURE__ */ new Map();
|
|
1742
|
+
this.reactiveSubscribers = /* @__PURE__ */ new Set();
|
|
1743
|
+
// Handlers
|
|
1744
|
+
this.messageHandler = null;
|
|
1745
|
+
this.setupPromise = null;
|
|
1746
|
+
this.setupHook = null;
|
|
1747
|
+
// Public APIs
|
|
1748
|
+
this.orm = null;
|
|
1749
|
+
this.config = {
|
|
1750
|
+
debug: config.debug ?? false,
|
|
1751
|
+
timeout: config.timeout ?? DEFAULT_TIMEOUT,
|
|
1752
|
+
manifest: config.manifest
|
|
1753
|
+
};
|
|
1754
|
+
this.storage = new StorageAPI(this);
|
|
1755
|
+
this.database = new DatabaseAPI(this);
|
|
1756
|
+
this.filesystem = new FilesystemAPI(this);
|
|
1757
|
+
this.web = new WebAPI(this);
|
|
1758
|
+
this.permissions = new PermissionsAPI(this);
|
|
1759
|
+
installConsoleForwarding(this.config.debug);
|
|
1760
|
+
this.readyPromise = new Promise((resolve) => {
|
|
1761
|
+
this.resolveReady = resolve;
|
|
1762
|
+
});
|
|
1763
|
+
this.init();
|
|
1764
|
+
}
|
|
1765
|
+
// ==========================================================================
|
|
1766
|
+
// Lifecycle
|
|
1767
|
+
// ==========================================================================
|
|
1768
|
+
async ready() {
|
|
1769
|
+
return this.readyPromise;
|
|
1770
|
+
}
|
|
1771
|
+
get setupCompleted() {
|
|
1772
|
+
return this._setupCompleted;
|
|
1773
|
+
}
|
|
1774
|
+
onSetup(setupFn) {
|
|
1775
|
+
if (this.setupHook) {
|
|
1776
|
+
throw new Error("Setup hook already registered");
|
|
1603
1777
|
}
|
|
1604
|
-
this.
|
|
1605
|
-
}
|
|
1606
|
-
async
|
|
1607
|
-
this.
|
|
1608
|
-
|
|
1609
|
-
if (!handler) {
|
|
1610
|
-
this.log(`[ExternalRequest] No handler for action: ${request.action}`);
|
|
1611
|
-
await this.respondToExternalRequest({
|
|
1612
|
-
requestId: request.requestId,
|
|
1613
|
-
success: false,
|
|
1614
|
-
error: `No handler registered for action: ${request.action}`
|
|
1615
|
-
});
|
|
1778
|
+
this.setupHook = setupFn;
|
|
1779
|
+
}
|
|
1780
|
+
async setupComplete() {
|
|
1781
|
+
await this.readyPromise;
|
|
1782
|
+
if (!this.setupHook || this.setupCompleted) {
|
|
1616
1783
|
return;
|
|
1617
1784
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
await this.respondToExternalRequest(response);
|
|
1621
|
-
this.log(`[ExternalRequest] Response sent for: ${request.action}`);
|
|
1622
|
-
} catch (error) {
|
|
1623
|
-
this.log(`[ExternalRequest] Handler error:`, error);
|
|
1624
|
-
await this.respondToExternalRequest({
|
|
1625
|
-
requestId: request.requestId,
|
|
1626
|
-
success: false,
|
|
1627
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1628
|
-
});
|
|
1785
|
+
if (!this.setupPromise) {
|
|
1786
|
+
this.setupPromise = this.runSetupAsync();
|
|
1629
1787
|
}
|
|
1788
|
+
return this.setupPromise;
|
|
1630
1789
|
}
|
|
1631
|
-
|
|
1632
|
-
this.
|
|
1633
|
-
|
|
1634
|
-
if (listeners) {
|
|
1635
|
-
listeners.forEach((callback) => callback(event));
|
|
1790
|
+
destroy() {
|
|
1791
|
+
if (this.messageHandler) {
|
|
1792
|
+
window.removeEventListener("message", this.messageHandler);
|
|
1636
1793
|
}
|
|
1794
|
+
this.pendingRequests.forEach(({ timeout }) => clearTimeout(timeout));
|
|
1795
|
+
this.pendingRequests.clear();
|
|
1796
|
+
this.eventListeners.clear();
|
|
1797
|
+
this.initialized = false;
|
|
1798
|
+
this.log("HaexVault SDK destroyed");
|
|
1637
1799
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1800
|
+
// ==========================================================================
|
|
1801
|
+
// Properties
|
|
1802
|
+
// ==========================================================================
|
|
1803
|
+
get extensionInfo() {
|
|
1804
|
+
return this._extensionInfo;
|
|
1640
1805
|
}
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
throw new HaexHubError(
|
|
1644
|
-
"INVALID_PUBLIC_KEY" /* INVALID_PUBLIC_KEY */,
|
|
1645
|
-
"errors.invalid_public_key",
|
|
1646
|
-
{ publicKey }
|
|
1647
|
-
);
|
|
1648
|
-
}
|
|
1806
|
+
get context() {
|
|
1807
|
+
return this._context;
|
|
1649
1808
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
);
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1809
|
+
// ==========================================================================
|
|
1810
|
+
// Subscriptions
|
|
1811
|
+
// ==========================================================================
|
|
1812
|
+
subscribe(callback) {
|
|
1813
|
+
this.reactiveSubscribers.add(callback);
|
|
1814
|
+
return () => {
|
|
1815
|
+
this.reactiveSubscribers.delete(callback);
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
// ==========================================================================
|
|
1819
|
+
// Table Name Utilities
|
|
1820
|
+
// ==========================================================================
|
|
1821
|
+
getTableName(tableName) {
|
|
1822
|
+
return getExtensionTableName(this._extensionInfo, tableName);
|
|
1823
|
+
}
|
|
1824
|
+
getDependencyTableName(publicKey, extensionName, tableName) {
|
|
1825
|
+
return getDependencyTableName(publicKey, extensionName, tableName);
|
|
1826
|
+
}
|
|
1827
|
+
parseTableName(fullTableName) {
|
|
1828
|
+
return parseTableName(fullTableName);
|
|
1829
|
+
}
|
|
1830
|
+
// ==========================================================================
|
|
1831
|
+
// Database
|
|
1832
|
+
// ==========================================================================
|
|
1833
|
+
initializeDatabase(schema) {
|
|
1834
|
+
const db = createDrizzleInstance(schema, this._extensionInfo, this.request.bind(this), this.log.bind(this));
|
|
1835
|
+
this.orm = db;
|
|
1836
|
+
return db;
|
|
1837
|
+
}
|
|
1838
|
+
async query(sql, params = []) {
|
|
1839
|
+
return queryRaw(sql, params, this.request.bind(this), this.config.debug);
|
|
1840
|
+
}
|
|
1841
|
+
async select(sql, params = []) {
|
|
1842
|
+
return this.query(sql, params);
|
|
1843
|
+
}
|
|
1844
|
+
async execute(sql, params = []) {
|
|
1845
|
+
return executeRaw(sql, params, this.request.bind(this));
|
|
1846
|
+
}
|
|
1847
|
+
async registerMigrationsAsync(extensionVersion, migrations) {
|
|
1848
|
+
return this.database.registerMigrationsAsync(extensionVersion, migrations);
|
|
1849
|
+
}
|
|
1850
|
+
// ==========================================================================
|
|
1851
|
+
// Dependencies
|
|
1852
|
+
// ==========================================================================
|
|
1853
|
+
async getDependencies() {
|
|
1854
|
+
return this.request("extensions.getDependencies");
|
|
1855
|
+
}
|
|
1856
|
+
// ==========================================================================
|
|
1857
|
+
// Permissions
|
|
1858
|
+
// ==========================================================================
|
|
1859
|
+
async requestDatabasePermission(request) {
|
|
1860
|
+
return this.request("permissions.database.request", {
|
|
1861
|
+
resource: request.resource,
|
|
1862
|
+
operation: request.operation,
|
|
1863
|
+
reason: request.reason
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
async checkDatabasePermission(resource, operation) {
|
|
1867
|
+
const response = await this.request("permissions.database.check", { resource, operation });
|
|
1868
|
+
return response.status === "granted";
|
|
1869
|
+
}
|
|
1870
|
+
// ==========================================================================
|
|
1871
|
+
// Search
|
|
1872
|
+
// ==========================================================================
|
|
1873
|
+
async respondToSearch(requestId, results) {
|
|
1874
|
+
await this.request("search.respond", { requestId, results });
|
|
1875
|
+
}
|
|
1876
|
+
// ==========================================================================
|
|
1877
|
+
// External Requests
|
|
1878
|
+
// ==========================================================================
|
|
1879
|
+
onExternalRequest(action, handler) {
|
|
1880
|
+
return registerExternalHandler(action, handler, this.externalRequestHandlers, this.log.bind(this));
|
|
1881
|
+
}
|
|
1882
|
+
async respondToExternalRequest(response) {
|
|
1883
|
+
await respondToExternalRequest(response, this.request.bind(this));
|
|
1884
|
+
}
|
|
1885
|
+
// ==========================================================================
|
|
1886
|
+
// Events
|
|
1887
|
+
// ==========================================================================
|
|
1888
|
+
on(eventType, callback) {
|
|
1889
|
+
addEventListener(eventType, callback, this.eventListeners);
|
|
1890
|
+
}
|
|
1891
|
+
off(eventType, callback) {
|
|
1892
|
+
removeEventListener(eventType, callback, this.eventListeners);
|
|
1893
|
+
}
|
|
1894
|
+
// ==========================================================================
|
|
1895
|
+
// Communication
|
|
1896
|
+
// ==========================================================================
|
|
1897
|
+
async request(method, params) {
|
|
1898
|
+
const resolvedParams = params ?? {};
|
|
1899
|
+
if (this.isNativeWindow && hasTauri()) {
|
|
1900
|
+
return sendInvoke(method, resolvedParams, this.config, this.log.bind(this));
|
|
1664
1901
|
}
|
|
1902
|
+
const requestId = generateRequestId(++this.requestCounter);
|
|
1903
|
+
return sendPostMessage(method, resolvedParams, requestId, this.config, this._extensionInfo, this.pendingRequests);
|
|
1665
1904
|
}
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1905
|
+
// ==========================================================================
|
|
1906
|
+
// Private: Initialization
|
|
1907
|
+
// ==========================================================================
|
|
1908
|
+
async init() {
|
|
1909
|
+
if (this.initialized) return;
|
|
1910
|
+
if (!isInIframe() && hasTauri()) {
|
|
1911
|
+
try {
|
|
1912
|
+
await this.initNative();
|
|
1913
|
+
return;
|
|
1914
|
+
} catch (error) {
|
|
1915
|
+
this.log("Tauri commands failed, falling back to iframe mode", error);
|
|
1916
|
+
}
|
|
1672
1917
|
}
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1918
|
+
await this.initIframe();
|
|
1919
|
+
}
|
|
1920
|
+
async initNative() {
|
|
1921
|
+
const { extensionInfo: extensionInfo2, context: context2 } = await initNativeMode(
|
|
1922
|
+
{
|
|
1923
|
+
config: this.config,
|
|
1924
|
+
state: {
|
|
1925
|
+
initialized: this.initialized,
|
|
1926
|
+
isNativeWindow: this.isNativeWindow,
|
|
1927
|
+
requestCounter: this.requestCounter,
|
|
1928
|
+
setupCompleted: this._setupCompleted,
|
|
1929
|
+
extensionInfo: this._extensionInfo,
|
|
1930
|
+
context: this._context,
|
|
1931
|
+
orm: this.orm
|
|
1932
|
+
},
|
|
1933
|
+
collections: {
|
|
1934
|
+
pendingRequests: this.pendingRequests,
|
|
1935
|
+
eventListeners: this.eventListeners,
|
|
1936
|
+
externalRequestHandlers: this.externalRequestHandlers,
|
|
1937
|
+
reactiveSubscribers: this.reactiveSubscribers
|
|
1938
|
+
},
|
|
1939
|
+
promises: {
|
|
1940
|
+
readyPromise: this.readyPromise,
|
|
1941
|
+
resolveReady: this.resolveReady,
|
|
1942
|
+
setupPromise: this.setupPromise,
|
|
1943
|
+
setupHook: this.setupHook
|
|
1944
|
+
},
|
|
1945
|
+
handlers: {
|
|
1946
|
+
messageHandler: this.messageHandler
|
|
1947
|
+
}
|
|
1948
|
+
},
|
|
1949
|
+
this.log.bind(this),
|
|
1950
|
+
this.handleEvent.bind(this),
|
|
1951
|
+
(ctx) => {
|
|
1952
|
+
this._context = ctx;
|
|
1953
|
+
this.notifySubscribersInternal();
|
|
1954
|
+
}
|
|
1955
|
+
);
|
|
1956
|
+
this._extensionInfo = extensionInfo2;
|
|
1957
|
+
this._context = context2;
|
|
1958
|
+
this.isNativeWindow = true;
|
|
1959
|
+
this.initialized = true;
|
|
1960
|
+
this.notifySubscribersInternal();
|
|
1961
|
+
this.resolveReady();
|
|
1962
|
+
}
|
|
1963
|
+
async initIframe() {
|
|
1964
|
+
this.messageHandler = createMessageHandler(
|
|
1965
|
+
this.config,
|
|
1966
|
+
this.pendingRequests,
|
|
1967
|
+
() => this._extensionInfo,
|
|
1968
|
+
this.handleEvent.bind(this)
|
|
1969
|
+
);
|
|
1970
|
+
const { context: context2 } = await initIframeMode(
|
|
1971
|
+
{
|
|
1972
|
+
config: this.config,
|
|
1973
|
+
state: {
|
|
1974
|
+
initialized: this.initialized,
|
|
1975
|
+
isNativeWindow: this.isNativeWindow,
|
|
1976
|
+
requestCounter: this.requestCounter,
|
|
1977
|
+
setupCompleted: this._setupCompleted,
|
|
1978
|
+
extensionInfo: this._extensionInfo,
|
|
1979
|
+
context: this._context,
|
|
1980
|
+
orm: this.orm
|
|
1981
|
+
},
|
|
1982
|
+
collections: {
|
|
1983
|
+
pendingRequests: this.pendingRequests,
|
|
1984
|
+
eventListeners: this.eventListeners,
|
|
1985
|
+
externalRequestHandlers: this.externalRequestHandlers,
|
|
1986
|
+
reactiveSubscribers: this.reactiveSubscribers
|
|
1987
|
+
},
|
|
1988
|
+
promises: {
|
|
1989
|
+
readyPromise: this.readyPromise,
|
|
1990
|
+
resolveReady: this.resolveReady,
|
|
1991
|
+
setupPromise: this.setupPromise,
|
|
1992
|
+
setupHook: this.setupHook
|
|
1993
|
+
},
|
|
1994
|
+
handlers: {
|
|
1995
|
+
messageHandler: this.messageHandler
|
|
1996
|
+
}
|
|
1997
|
+
},
|
|
1998
|
+
this.log.bind(this),
|
|
1999
|
+
this.messageHandler,
|
|
2000
|
+
this.request.bind(this)
|
|
2001
|
+
);
|
|
2002
|
+
if (this.config.manifest) {
|
|
2003
|
+
this._extensionInfo = {
|
|
2004
|
+
publicKey: this.config.manifest.publicKey,
|
|
2005
|
+
name: this.config.manifest.name,
|
|
2006
|
+
version: this.config.manifest.version,
|
|
2007
|
+
displayName: this.config.manifest.name
|
|
2008
|
+
};
|
|
2009
|
+
this.notifySubscribersInternal();
|
|
1679
2010
|
}
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
2011
|
+
this._context = context2;
|
|
2012
|
+
this.isNativeWindow = false;
|
|
2013
|
+
this.initialized = true;
|
|
2014
|
+
this.notifySubscribersInternal();
|
|
2015
|
+
this.resolveReady();
|
|
2016
|
+
}
|
|
2017
|
+
// ==========================================================================
|
|
2018
|
+
// Private: Event Handling
|
|
2019
|
+
// ==========================================================================
|
|
2020
|
+
handleEvent(event) {
|
|
2021
|
+
processEvent(
|
|
2022
|
+
event,
|
|
2023
|
+
this.log.bind(this),
|
|
2024
|
+
this.eventListeners,
|
|
2025
|
+
(ctx) => {
|
|
2026
|
+
this._context = ctx;
|
|
2027
|
+
this.notifySubscribersInternal();
|
|
2028
|
+
},
|
|
2029
|
+
(extEvent) => this.handleExternalRequestInternal(extEvent.data)
|
|
2030
|
+
);
|
|
2031
|
+
}
|
|
2032
|
+
async handleExternalRequestInternal(request) {
|
|
2033
|
+
await handleExternalRequest(request, this.externalRequestHandlers, this.respondToExternalRequest.bind(this), this.log.bind(this));
|
|
2034
|
+
}
|
|
2035
|
+
// ==========================================================================
|
|
2036
|
+
// Private: Setup
|
|
2037
|
+
// ==========================================================================
|
|
2038
|
+
async runSetupAsync() {
|
|
2039
|
+
if (!this.setupHook) return;
|
|
2040
|
+
try {
|
|
2041
|
+
this.log("[HaexVault] Running setup hook...");
|
|
2042
|
+
await this.setupHook();
|
|
2043
|
+
this._setupCompleted = true;
|
|
2044
|
+
this.log("[HaexVault] Setup completed successfully");
|
|
2045
|
+
this.notifySubscribersInternal();
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
this.log("[HaexVault] Setup failed:", error);
|
|
2048
|
+
throw error;
|
|
1686
2049
|
}
|
|
1687
2050
|
}
|
|
2051
|
+
// ==========================================================================
|
|
2052
|
+
// Private: Utilities
|
|
2053
|
+
// ==========================================================================
|
|
2054
|
+
notifySubscribersInternal() {
|
|
2055
|
+
notifySubscribers(this.reactiveSubscribers);
|
|
2056
|
+
}
|
|
1688
2057
|
log(...args) {
|
|
1689
2058
|
if (this.config.debug) {
|
|
1690
|
-
console.log("[
|
|
2059
|
+
console.log("[HaexVault SDK]", ...args);
|
|
1691
2060
|
}
|
|
1692
2061
|
}
|
|
1693
2062
|
};
|