@haex-space/vault-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1551 -0
  2. package/dist/cli/index.d.mts +1 -0
  3. package/dist/cli/index.d.ts +1 -0
  4. package/dist/cli/index.js +455 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/cli/index.mjs +430 -0
  7. package/dist/cli/index.mjs.map +1 -0
  8. package/dist/client-O_JEOzfx.d.mts +491 -0
  9. package/dist/client-O_JEOzfx.d.ts +491 -0
  10. package/dist/index.d.mts +124 -0
  11. package/dist/index.d.ts +124 -0
  12. package/dist/index.js +1429 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/index.mjs +1409 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/node.d.mts +25 -0
  17. package/dist/node.d.ts +25 -0
  18. package/dist/node.js +28 -0
  19. package/dist/node.js.map +1 -0
  20. package/dist/node.mjs +25 -0
  21. package/dist/node.mjs.map +1 -0
  22. package/dist/nuxt.d.mts +19 -0
  23. package/dist/nuxt.d.ts +19 -0
  24. package/dist/nuxt.js +473 -0
  25. package/dist/nuxt.js.map +1 -0
  26. package/dist/nuxt.mjs +470 -0
  27. package/dist/nuxt.mjs.map +1 -0
  28. package/dist/react.d.mts +28 -0
  29. package/dist/react.d.ts +28 -0
  30. package/dist/react.js +1389 -0
  31. package/dist/react.js.map +1 -0
  32. package/dist/react.mjs +1386 -0
  33. package/dist/react.mjs.map +1 -0
  34. package/dist/runtime/nuxt.plugin.client.d.mts +43 -0
  35. package/dist/runtime/nuxt.plugin.client.d.ts +43 -0
  36. package/dist/runtime/nuxt.plugin.client.js +1137 -0
  37. package/dist/runtime/nuxt.plugin.client.js.map +1 -0
  38. package/dist/runtime/nuxt.plugin.client.mjs +1135 -0
  39. package/dist/runtime/nuxt.plugin.client.mjs.map +1 -0
  40. package/dist/runtime/nuxt.types.d.ts +15 -0
  41. package/dist/svelte.d.mts +48 -0
  42. package/dist/svelte.d.ts +48 -0
  43. package/dist/svelte.js +1398 -0
  44. package/dist/svelte.js.map +1 -0
  45. package/dist/svelte.mjs +1391 -0
  46. package/dist/svelte.mjs.map +1 -0
  47. package/dist/vite.d.mts +37 -0
  48. package/dist/vite.d.ts +37 -0
  49. package/dist/vite.js +346 -0
  50. package/dist/vite.js.map +1 -0
  51. package/dist/vite.mjs +341 -0
  52. package/dist/vite.mjs.map +1 -0
  53. package/dist/vue.d.mts +49 -0
  54. package/dist/vue.d.ts +49 -0
  55. package/dist/vue.js +1388 -0
  56. package/dist/vue.js.map +1 -0
  57. package/dist/vue.mjs +1385 -0
  58. package/dist/vue.mjs.map +1 -0
  59. package/package.json +121 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1409 @@
1
+ import { drizzle } from 'drizzle-orm/sqlite-proxy';
2
+
3
+ // src/polyfills/localStorage.ts
4
+ function installLocalStoragePolyfill() {
5
+ if (typeof window === "undefined") {
6
+ return;
7
+ }
8
+ console.log("[HaexHub] Storage Polyfill loading immediately");
9
+ let localStorageWorks = false;
10
+ try {
11
+ const testKey = "__ls_test__";
12
+ localStorage.setItem(testKey, testKey);
13
+ localStorage.removeItem(testKey);
14
+ localStorageWorks = true;
15
+ } catch (e) {
16
+ console.warn("[HaexHub] localStorage blocked \u2013 using in-memory fallback");
17
+ }
18
+ if (!localStorageWorks) {
19
+ const lsStorage = /* @__PURE__ */ new Map();
20
+ const localStoragePoly = {
21
+ getItem(key) {
22
+ return lsStorage.get(key) || null;
23
+ },
24
+ setItem(key, value) {
25
+ lsStorage.set(key, String(value));
26
+ },
27
+ removeItem(key) {
28
+ lsStorage.delete(key);
29
+ },
30
+ clear() {
31
+ lsStorage.clear();
32
+ },
33
+ get length() {
34
+ return lsStorage.size;
35
+ },
36
+ key(index) {
37
+ return Array.from(lsStorage.keys())[index] || null;
38
+ }
39
+ };
40
+ try {
41
+ Object.defineProperty(window, "localStorage", {
42
+ value: localStoragePoly,
43
+ writable: true,
44
+ configurable: true
45
+ });
46
+ } catch (e) {
47
+ window.localStorage = localStoragePoly;
48
+ }
49
+ console.log("[HaexHub] localStorage replaced with in-memory polyfill");
50
+ }
51
+ }
52
+ function installSessionStoragePolyfill() {
53
+ if (typeof window === "undefined") {
54
+ return;
55
+ }
56
+ try {
57
+ const sessionStoragePoly = {
58
+ getItem() {
59
+ return null;
60
+ },
61
+ setItem() {
62
+ },
63
+ removeItem() {
64
+ },
65
+ clear() {
66
+ },
67
+ get length() {
68
+ return 0;
69
+ },
70
+ key() {
71
+ return null;
72
+ }
73
+ };
74
+ Object.defineProperty(window, "sessionStorage", {
75
+ value: sessionStoragePoly,
76
+ writable: true,
77
+ configurable: true
78
+ });
79
+ } catch (e) {
80
+ window.sessionStorage = {
81
+ getItem: () => null,
82
+ setItem: () => {
83
+ },
84
+ removeItem: () => {
85
+ },
86
+ clear: () => {
87
+ },
88
+ get length() {
89
+ return 0;
90
+ },
91
+ key: () => null
92
+ };
93
+ }
94
+ console.log("[HaexHub] sessionStorage polyfill installed");
95
+ }
96
+
97
+ // src/polyfills/cookies.ts
98
+ function installCookiePolyfill() {
99
+ if (typeof window === "undefined" || typeof document === "undefined") {
100
+ return;
101
+ }
102
+ let cookiesWork = false;
103
+ try {
104
+ document.cookie = "__cookie_test__=1";
105
+ cookiesWork = document.cookie.indexOf("__cookie_test__") !== -1;
106
+ } catch (e) {
107
+ console.warn("[HaexHub] Cookies blocked \u2013 using in-memory fallback");
108
+ }
109
+ if (!cookiesWork) {
110
+ const cookieStore = /* @__PURE__ */ new Map();
111
+ Object.defineProperty(document, "cookie", {
112
+ get() {
113
+ const cookies = [];
114
+ cookieStore.forEach((value, key) => {
115
+ cookies.push(`${key}=${value}`);
116
+ });
117
+ return cookies.join("; ");
118
+ },
119
+ set(cookieString) {
120
+ const parts = cookieString.split(";").map((p) => p.trim());
121
+ const [keyValue] = parts;
122
+ if (!keyValue) return;
123
+ const [key, value] = keyValue.split("=");
124
+ if (!key) return;
125
+ const options = {};
126
+ for (let i = 1; i < parts.length; i++) {
127
+ const part = parts[i];
128
+ if (!part) continue;
129
+ const parts_split = part.split("=");
130
+ const optKey = parts_split[0];
131
+ const optValue = parts_split[1];
132
+ if (optKey) {
133
+ options[optKey.toLowerCase()] = optValue || true;
134
+ }
135
+ }
136
+ const expiresValue = options.expires;
137
+ if (expiresValue && typeof expiresValue === "string") {
138
+ const expiresDate = new Date(expiresValue);
139
+ if (expiresDate < /* @__PURE__ */ new Date()) {
140
+ cookieStore.delete(key);
141
+ return;
142
+ }
143
+ }
144
+ const maxAgeValue = options["max-age"];
145
+ if (typeof maxAgeValue === "string" && maxAgeValue === "0") {
146
+ cookieStore.delete(key);
147
+ return;
148
+ }
149
+ cookieStore.set(key, value || "");
150
+ },
151
+ configurable: true
152
+ });
153
+ console.log("[HaexHub] Cookie polyfill installed");
154
+ }
155
+ }
156
+
157
+ // src/polyfills/history.ts
158
+ function installHistoryPolyfill() {
159
+ if (typeof window === "undefined" || typeof history === "undefined") {
160
+ return;
161
+ }
162
+ const install = () => {
163
+ console.log("[HaexHub] History Patch loading");
164
+ const originalPushState = history.pushState;
165
+ const originalReplaceState = history.replaceState;
166
+ let skipNextPush = false;
167
+ let skipNextReplace = false;
168
+ history.pushState = function(state, title, url) {
169
+ console.log("[HaexHub] pushState called:", url, "skip:", skipNextPush);
170
+ if (skipNextPush) {
171
+ skipNextPush = false;
172
+ console.log("[HaexHub] pushState skipped");
173
+ return;
174
+ }
175
+ try {
176
+ return originalPushState.call(this, state, title, url);
177
+ } catch (e) {
178
+ if (e.name === "SecurityError" && url) {
179
+ const urlString = url.toString();
180
+ let hashUrl = urlString.replace(/^\/#/, "");
181
+ hashUrl = hashUrl.startsWith("#") ? hashUrl : "#" + hashUrl;
182
+ console.log("[HaexHub] SecurityError - setting hash to:", hashUrl);
183
+ skipNextPush = true;
184
+ window.location.hash = hashUrl.replace(/^#/, "");
185
+ return;
186
+ }
187
+ throw e;
188
+ }
189
+ };
190
+ history.replaceState = function(state, title, url) {
191
+ console.log("[HaexHub] replaceState called:", url, "skip:", skipNextReplace);
192
+ if (skipNextReplace) {
193
+ skipNextReplace = false;
194
+ console.log("[HaexHub] replaceState skipped");
195
+ return;
196
+ }
197
+ try {
198
+ return originalReplaceState.call(this, state, title, url);
199
+ } catch (e) {
200
+ if (e.name === "SecurityError" && url) {
201
+ const urlString = url.toString();
202
+ let hashUrl = urlString.replace(/^\/#/, "");
203
+ hashUrl = hashUrl.startsWith("#") ? hashUrl : "#" + hashUrl;
204
+ console.log("[HaexHub] SecurityError - setting hash to:", hashUrl);
205
+ skipNextReplace = true;
206
+ window.location.hash = hashUrl.replace(/^#/, "");
207
+ return;
208
+ }
209
+ throw e;
210
+ }
211
+ };
212
+ console.log("[HaexHub] History API patched");
213
+ };
214
+ if (document.readyState === "loading") {
215
+ document.addEventListener("DOMContentLoaded", install, { once: true });
216
+ } else {
217
+ install();
218
+ }
219
+ }
220
+
221
+ // src/polyfills/debug.ts
222
+ function installDebugDiagnostics() {
223
+ if (typeof window === "undefined") {
224
+ return;
225
+ }
226
+ const hasParent = window.parent && window.parent !== window;
227
+ console.log("[HaexHub] hasParent:", hasParent);
228
+ if (hasParent) {
229
+ console.log("[HaexHub] Attempting to send debug message to parent...");
230
+ window.parent.postMessage({
231
+ type: "haexhub:debug",
232
+ data: `[Polyfills] window.parent test: exists=${!!window.parent}, different=${hasParent}, selfIsTop=${window.self === window.top}`
233
+ }, "*");
234
+ console.log("[HaexHub] Debug message sent!");
235
+ } else {
236
+ console.log("[HaexHub] No parent window or parent === window");
237
+ }
238
+ }
239
+
240
+ // src/polyfills/baseTag.ts
241
+ function installBaseTag() {
242
+ if (typeof window === "undefined" || typeof document === "undefined") {
243
+ return;
244
+ }
245
+ if (window.__HAEXHUB_BASE_TAG_INSTALLING__) {
246
+ console.log("[HaexHub] Base tag installation already in progress, skipping");
247
+ return;
248
+ }
249
+ console.log("[HaexHub] Base tag installation starting");
250
+ if (window.self === window.top) {
251
+ console.log("[HaexHub] Not in iframe, skipping base tag");
252
+ return;
253
+ }
254
+ const existingBaseTag = document.querySelector("base#haexhub-base");
255
+ if (existingBaseTag && existingBaseTag.href && existingBaseTag.href !== window.location.origin + "/") {
256
+ console.log("[HaexHub] Base tag already configured, skipping");
257
+ return;
258
+ }
259
+ window.__HAEXHUB_BASE_TAG_INSTALLING__ = true;
260
+ const pathname = window.location.pathname;
261
+ const lastSlashIndex = pathname.lastIndexOf("/");
262
+ const basePath = lastSlashIndex !== -1 ? pathname.substring(0, lastSlashIndex + 1) : "/";
263
+ console.log("[HaexHub] Extracted base path from location:", basePath);
264
+ if (existingBaseTag) {
265
+ existingBaseTag.href = basePath;
266
+ console.log(`[HaexHub] Base tag updated: ${existingBaseTag.href}`);
267
+ } else {
268
+ const baseTag = document.createElement("base");
269
+ baseTag.id = "haexhub-base";
270
+ baseTag.href = basePath;
271
+ const head = document.head || document.querySelector("head");
272
+ if (head) {
273
+ head.insertBefore(baseTag, head.firstChild);
274
+ console.log(`[HaexHub] Base tag created: ${baseTag.href}`);
275
+ } else {
276
+ console.warn("[HaexHub] No <head> found, cannot inject base tag");
277
+ }
278
+ }
279
+ }
280
+
281
+ // src/polyfills/consoleForwarding.ts
282
+ var originalConsole = {
283
+ log: console.log,
284
+ info: console.info,
285
+ warn: console.warn,
286
+ error: console.error,
287
+ debug: console.debug
288
+ };
289
+ function serializeArgs(args) {
290
+ return args.map((arg) => {
291
+ if (arg === null) return "null";
292
+ if (arg === void 0) return "undefined";
293
+ if (typeof arg === "object") {
294
+ try {
295
+ return JSON.stringify(arg, null, 2);
296
+ } catch {
297
+ return String(arg);
298
+ }
299
+ }
300
+ return String(arg);
301
+ }).join(" ");
302
+ }
303
+ function interceptConsole(level) {
304
+ console[level] = function(...args) {
305
+ originalConsole[level].apply(console, args);
306
+ if (window.self !== window.top && window.parent) {
307
+ try {
308
+ const message = serializeArgs(args);
309
+ const timestamp = (/* @__PURE__ */ new Date()).toLocaleTimeString();
310
+ window.parent.postMessage(
311
+ {
312
+ type: "console.forward",
313
+ data: {
314
+ timestamp,
315
+ level,
316
+ message
317
+ },
318
+ timestamp: Date.now()
319
+ },
320
+ "*"
321
+ );
322
+ } catch (error) {
323
+ originalConsole.error("[HaexHub] Failed to forward console message:", error);
324
+ }
325
+ }
326
+ };
327
+ }
328
+ function installConsoleForwarding(debug = false) {
329
+ if (typeof window === "undefined") {
330
+ return;
331
+ }
332
+ if (window.self === window.top) {
333
+ return;
334
+ }
335
+ if (!debug) {
336
+ console.log("[HaexHub] Console forwarding disabled (not in debug mode)");
337
+ return;
338
+ }
339
+ interceptConsole("log");
340
+ interceptConsole("info");
341
+ interceptConsole("warn");
342
+ interceptConsole("error");
343
+ interceptConsole("debug");
344
+ console.log("[HaexHub] Console forwarding installed");
345
+ }
346
+
347
+ // src/polyfills/index.ts
348
+ function installPolyfills() {
349
+ if (typeof window === "undefined") {
350
+ return;
351
+ }
352
+ installLocalStoragePolyfill();
353
+ installSessionStoragePolyfill();
354
+ installCookiePolyfill();
355
+ installHistoryPolyfill();
356
+ console.log("[HaexHub] All polyfills loaded successfully");
357
+ installDebugDiagnostics();
358
+ }
359
+ if (typeof window !== "undefined") {
360
+ installPolyfills();
361
+ }
362
+
363
+ // src/events.ts
364
+ var HAEXTENSION_EVENTS = {
365
+ /** Context (theme, locale, platform) has changed */
366
+ CONTEXT_CHANGED: "haextension:context:changed",
367
+ /** Search request from HaexHub */
368
+ SEARCH_REQUEST: "haextension:search:request"
369
+ };
370
+
371
+ // src/methods.ts
372
+ var HAEXTENSION_METHODS = {
373
+ context: {
374
+ get: "haextension:context:get"
375
+ },
376
+ database: {
377
+ query: "haextension:database:query",
378
+ execute: "haextension:database:execute",
379
+ transaction: "haextension:database:transaction",
380
+ registerMigrations: "haextension:database:register-migrations"
381
+ },
382
+ filesystem: {
383
+ saveFile: "haextension:filesystem:save-file",
384
+ openFile: "haextension:filesystem:open-file",
385
+ showImage: "haextension:filesystem:show-image"
386
+ },
387
+ storage: {
388
+ getItem: "haextension:storage:get-item",
389
+ setItem: "haextension:storage:set-item",
390
+ removeItem: "haextension:storage:remove-item",
391
+ clear: "haextension:storage:clear",
392
+ keys: "haextension:storage:keys"
393
+ },
394
+ web: {
395
+ fetch: "haextension:web:fetch"
396
+ },
397
+ application: {
398
+ open: "haextension:application:open"
399
+ }
400
+ };
401
+
402
+ // src/types.ts
403
+ var DEFAULT_TIMEOUT = 3e4;
404
+ var TABLE_SEPARATOR = "__";
405
+ var PermissionStatus = /* @__PURE__ */ ((PermissionStatus2) => {
406
+ PermissionStatus2["GRANTED"] = "granted";
407
+ PermissionStatus2["DENIED"] = "denied";
408
+ PermissionStatus2["ASK"] = "ask";
409
+ return PermissionStatus2;
410
+ })(PermissionStatus || {});
411
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
412
+ ErrorCode2["TIMEOUT"] = "TIMEOUT";
413
+ ErrorCode2["NOT_IN_IFRAME"] = "NOT_IN_IFRAME";
414
+ ErrorCode2["UNAUTHORIZED_ORIGIN"] = "UNAUTHORIZED_ORIGIN";
415
+ ErrorCode2["PERMISSION_DENIED"] = "PERMISSION_DENIED";
416
+ ErrorCode2["INVALID_PUBLIC_KEY"] = "INVALID_PUBLIC_KEY";
417
+ ErrorCode2["INVALID_EXTENSION_NAME"] = "INVALID_EXTENSION_NAME";
418
+ ErrorCode2["INVALID_TABLE_NAME"] = "INVALID_TABLE_NAME";
419
+ ErrorCode2["INVALID_PARAMS"] = "INVALID_PARAMS";
420
+ ErrorCode2["EXTENSION_NOT_INITIALIZED"] = "EXTENSION_NOT_INITIALIZED";
421
+ ErrorCode2["EXTENSION_INFO_UNAVAILABLE"] = "EXTENSION_INFO_UNAVAILABLE";
422
+ ErrorCode2["METHOD_NOT_FOUND"] = "METHOD_NOT_FOUND";
423
+ ErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
424
+ ErrorCode2["DATABASE_ERROR"] = "DATABASE_ERROR";
425
+ ErrorCode2["WEB_ERROR"] = "WEB_ERROR";
426
+ return ErrorCode2;
427
+ })(ErrorCode || {});
428
+ var HaexHubError = class extends Error {
429
+ constructor(code, messageKey, details) {
430
+ super(messageKey);
431
+ this.code = code;
432
+ this.messageKey = messageKey;
433
+ this.details = details;
434
+ this.name = "HaexHubError";
435
+ }
436
+ /**
437
+ * Get localized error message
438
+ * @param locale - Locale code (e.g., 'en', 'de')
439
+ * @param translations - Translation object
440
+ */
441
+ getLocalizedMessage(locale = "en", translations) {
442
+ if (!translations || !translations[locale]) {
443
+ return this.messageKey;
444
+ }
445
+ let message = translations[locale][this.messageKey] || this.messageKey;
446
+ if (this.details) {
447
+ Object.entries(this.details).forEach(([key, value]) => {
448
+ message = message.replace(`{${key}}`, String(value));
449
+ });
450
+ }
451
+ return message;
452
+ }
453
+ toJSON() {
454
+ return {
455
+ code: this.code,
456
+ message: this.messageKey,
457
+ details: this.details
458
+ };
459
+ }
460
+ };
461
+
462
+ // src/api/storage.ts
463
+ var StorageAPI = class {
464
+ constructor(client) {
465
+ this.client = client;
466
+ }
467
+ async getItem(key) {
468
+ return this.client.request(HAEXTENSION_METHODS.storage.getItem, { key });
469
+ }
470
+ async setItem(key, value) {
471
+ await this.client.request(HAEXTENSION_METHODS.storage.setItem, { key, value });
472
+ }
473
+ async removeItem(key) {
474
+ await this.client.request(HAEXTENSION_METHODS.storage.removeItem, { key });
475
+ }
476
+ async clear() {
477
+ await this.client.request(HAEXTENSION_METHODS.storage.clear);
478
+ }
479
+ async keys() {
480
+ return this.client.request(HAEXTENSION_METHODS.storage.keys);
481
+ }
482
+ };
483
+
484
+ // src/api/database.ts
485
+ var DatabaseAPI = class {
486
+ constructor(client) {
487
+ this.client = client;
488
+ }
489
+ async query(query, params) {
490
+ const result = await this.client.request(
491
+ HAEXTENSION_METHODS.database.query,
492
+ {
493
+ query,
494
+ params: params || []
495
+ }
496
+ );
497
+ return result.rows;
498
+ }
499
+ async queryOne(query, params) {
500
+ const rows = await this.query(query, params);
501
+ return rows.length > 0 ? rows[0] ?? null : null;
502
+ }
503
+ async execute(query, params) {
504
+ return this.client.request(HAEXTENSION_METHODS.database.execute, {
505
+ query,
506
+ params: params || []
507
+ });
508
+ }
509
+ async transaction(statements) {
510
+ await this.client.request(HAEXTENSION_METHODS.database.transaction, {
511
+ statements
512
+ });
513
+ }
514
+ async createTable(tableName, columns) {
515
+ const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns})`;
516
+ await this.execute(query);
517
+ }
518
+ async dropTable(tableName) {
519
+ const query = `DROP TABLE IF EXISTS ${tableName}`;
520
+ await this.execute(query);
521
+ }
522
+ /**
523
+ * Registers extension migrations with HaexVault for CRDT synchronization
524
+ * HaexVault will validate and execute these migrations, ensuring only
525
+ * tables with the correct prefix are manipulated
526
+ * @param extensionVersion - The version of the extension
527
+ * @param migrations - Array of migration objects with name and SQL content
528
+ * @returns Promise that resolves when migrations are registered
529
+ */
530
+ async registerMigrationsAsync(extensionVersion, migrations) {
531
+ await this.client.request(HAEXTENSION_METHODS.database.registerMigrations, {
532
+ extensionVersion,
533
+ migrations
534
+ });
535
+ }
536
+ async insert(tableName, data) {
537
+ const keys = Object.keys(data);
538
+ const values = Object.values(data);
539
+ const placeholders = keys.map(() => "?").join(", ");
540
+ const query = `INSERT INTO ${tableName} (${keys.join(
541
+ ", "
542
+ )}) VALUES (${placeholders})`;
543
+ const result = await this.execute(query, values);
544
+ return result.lastInsertId ?? -1;
545
+ }
546
+ async update(tableName, data, where, whereParams) {
547
+ const keys = Object.keys(data);
548
+ const values = Object.values(data);
549
+ const setClause = keys.map((key) => `${key} = ?`).join(", ");
550
+ const query = `UPDATE ${tableName} SET ${setClause} WHERE ${where}`;
551
+ const result = await this.execute(query, [
552
+ ...values,
553
+ ...whereParams || []
554
+ ]);
555
+ return result.rowsAffected;
556
+ }
557
+ async delete(tableName, where, whereParams) {
558
+ const query = `DELETE FROM ${tableName} WHERE ${where}`;
559
+ const result = await this.execute(query, whereParams);
560
+ return result.rowsAffected;
561
+ }
562
+ async count(tableName, where, whereParams) {
563
+ const query = where ? `SELECT COUNT(*) as count FROM ${tableName} WHERE ${where}` : `SELECT COUNT(*) as count FROM ${tableName}`;
564
+ const result = await this.queryOne(query, whereParams);
565
+ return result?.count ?? 0;
566
+ }
567
+ };
568
+
569
+ // src/api/filesystem.ts
570
+ var FilesystemAPI = class {
571
+ constructor(client) {
572
+ this.client = client;
573
+ }
574
+ /**
575
+ * Opens a save file dialog and saves the provided data to the selected location
576
+ * @param data The file data as Uint8Array
577
+ * @param options Options for the save dialog
578
+ * @returns The path where the file was saved, or null if cancelled
579
+ */
580
+ async saveFileAsync(data, options = {}) {
581
+ const result = await this.client.request(
582
+ HAEXTENSION_METHODS.filesystem.saveFile,
583
+ {
584
+ data: Array.from(data),
585
+ // Convert Uint8Array to regular array for postMessage
586
+ defaultPath: options.defaultPath,
587
+ title: options.title,
588
+ filters: options.filters
589
+ }
590
+ );
591
+ return result;
592
+ }
593
+ /**
594
+ * Opens a file with the system's default viewer
595
+ * @param data The file data as Uint8Array
596
+ * @param options Options for opening the file
597
+ * @returns The result of the operation
598
+ */
599
+ async openFileAsync(data, options) {
600
+ const result = await this.client.request(
601
+ HAEXTENSION_METHODS.filesystem.openFile,
602
+ {
603
+ data: Array.from(data),
604
+ // Convert Uint8Array to regular array for postMessage
605
+ fileName: options.fileName,
606
+ mimeType: options.mimeType
607
+ }
608
+ );
609
+ return result;
610
+ }
611
+ /**
612
+ * Shows an image using a data URL (safe, read-only viewing)
613
+ * This is safe to use without special permissions as it only displays images
614
+ * and doesn't execute any code or open files with external applications
615
+ * @param options Options containing the data URL
616
+ * @returns The result of the operation
617
+ */
618
+ async showImageAsync(options) {
619
+ const result = await this.client.request(
620
+ HAEXTENSION_METHODS.filesystem.showImage,
621
+ {
622
+ dataUrl: options.dataUrl
623
+ }
624
+ );
625
+ return result;
626
+ }
627
+ };
628
+
629
+ // src/api/web.ts
630
+ var WebAPI = class {
631
+ constructor(client) {
632
+ this.client = client;
633
+ }
634
+ /**
635
+ * Performs a web request through the HaexHub host application
636
+ * @param url The URL to fetch
637
+ * @param options Request options (method, headers, body, timeout)
638
+ * @returns Promise resolving to the web response
639
+ */
640
+ async fetchAsync(url, options = {}) {
641
+ let bodyParam;
642
+ if (options.body) {
643
+ if (options.body instanceof ArrayBuffer) {
644
+ bodyParam = this.arrayBufferToBase64(options.body);
645
+ } else if (options.body instanceof Blob) {
646
+ bodyParam = await this.blobToBase64(options.body);
647
+ } else {
648
+ bodyParam = options.body;
649
+ }
650
+ }
651
+ const response = await this.client.request(HAEXTENSION_METHODS.web.fetch, {
652
+ url,
653
+ method: options.method || "GET",
654
+ headers: options.headers,
655
+ body: bodyParam,
656
+ timeout: options.timeout
657
+ });
658
+ const bodyBuffer = this.base64ToArrayBuffer(response.body);
659
+ return {
660
+ status: response.status,
661
+ statusText: response.statusText,
662
+ headers: response.headers,
663
+ body: bodyBuffer,
664
+ url: response.url
665
+ };
666
+ }
667
+ /**
668
+ * Convenience method for JSON requests
669
+ */
670
+ async fetchJsonAsync(url, options = {}) {
671
+ const response = await this.fetchAsync(url, options);
672
+ const text = new TextDecoder().decode(response.body);
673
+ return JSON.parse(text);
674
+ }
675
+ /**
676
+ * Convenience method for text requests
677
+ */
678
+ async fetchTextAsync(url, options = {}) {
679
+ const response = await this.fetchAsync(url, options);
680
+ return new TextDecoder().decode(response.body);
681
+ }
682
+ /**
683
+ * Convenience method for blob requests
684
+ */
685
+ async fetchBlobAsync(url, options = {}) {
686
+ const response = await this.fetchAsync(url, options);
687
+ return new Blob([response.body]);
688
+ }
689
+ /**
690
+ * Opens a URL in the user's default browser
691
+ * @param url The URL to open
692
+ */
693
+ async openAsync(url) {
694
+ await this.client.request(HAEXTENSION_METHODS.application.open, {
695
+ application: "browser",
696
+ url
697
+ });
698
+ }
699
+ arrayBufferToBase64(buffer) {
700
+ const bytes = new Uint8Array(buffer);
701
+ let binary = "";
702
+ for (let i = 0; i < bytes.byteLength; i++) {
703
+ const byte = bytes[i];
704
+ if (byte === void 0) {
705
+ throw new Error("Invalid byte at index " + i);
706
+ }
707
+ binary += String.fromCharCode(byte);
708
+ }
709
+ return btoa(binary);
710
+ }
711
+ async blobToBase64(blob) {
712
+ return new Promise((resolve, reject) => {
713
+ const reader = new FileReader();
714
+ reader.onloadend = () => {
715
+ const result = reader.result;
716
+ if (typeof result !== "string") {
717
+ reject(new Error("Failed to read blob as data URL"));
718
+ return;
719
+ }
720
+ const parts = result.split(",");
721
+ const base64 = parts[1];
722
+ if (!base64) {
723
+ reject(new Error("Failed to extract base64 from data URL"));
724
+ return;
725
+ }
726
+ resolve(base64);
727
+ };
728
+ reader.onerror = reject;
729
+ reader.readAsDataURL(blob);
730
+ });
731
+ }
732
+ base64ToArrayBuffer(base64) {
733
+ const binaryString = atob(base64);
734
+ const bytes = new Uint8Array(binaryString.length);
735
+ for (let i = 0; i < binaryString.length; i++) {
736
+ bytes[i] = binaryString.charCodeAt(i);
737
+ }
738
+ return bytes.buffer;
739
+ }
740
+ };
741
+
742
+ // src/api/permissions.ts
743
+ var PermissionsAPI = class {
744
+ constructor(client) {
745
+ this.client = client;
746
+ }
747
+ /**
748
+ * Checks if the extension has permission for a database operation
749
+ * @param resource The database resource (table name or "*" for all tables)
750
+ * @param operation The operation type ("read" or "write")
751
+ * @returns Promise<boolean> indicating if permission is granted
752
+ */
753
+ async checkDatabaseAsync(resource, operation) {
754
+ const response = await this.client.request(
755
+ "permissions.database.check",
756
+ {
757
+ resource,
758
+ operation
759
+ }
760
+ );
761
+ return response.status === "granted";
762
+ }
763
+ /**
764
+ * Checks if the extension has permission for a web request
765
+ * @param url The URL to check (e.g., "https://example.com/path")
766
+ * @returns Promise<boolean> indicating if permission is granted
767
+ * @note Method/operation is not checked - permissions apply to all HTTP methods
768
+ */
769
+ async checkWebAsync(url) {
770
+ const response = await this.client.request(
771
+ "permissions.web.check",
772
+ {
773
+ url
774
+ }
775
+ );
776
+ return response.status === "granted";
777
+ }
778
+ /**
779
+ * Checks if the extension has permission for a filesystem operation
780
+ * @param path The file or directory path
781
+ * @param operation The operation type ("read" or "write")
782
+ * @returns Promise<boolean> indicating if permission is granted
783
+ */
784
+ async checkFilesystemAsync(path, operation) {
785
+ const response = await this.client.request(
786
+ "permissions.filesystem.check",
787
+ {
788
+ path,
789
+ operation
790
+ }
791
+ );
792
+ return response.status === "granted";
793
+ }
794
+ };
795
+ var HaexVaultClient = class {
796
+ constructor(config = {}) {
797
+ this.pendingRequests = /* @__PURE__ */ new Map();
798
+ this.eventListeners = /* @__PURE__ */ new Map();
799
+ this.messageHandler = null;
800
+ this.initialized = false;
801
+ this.requestCounter = 0;
802
+ this._extensionInfo = null;
803
+ this._context = null;
804
+ this.reactiveSubscribers = /* @__PURE__ */ new Set();
805
+ this.isNativeWindow = false;
806
+ // Wird im Konstruktor initialisiert
807
+ this.setupPromise = null;
808
+ this.setupHook = null;
809
+ this._setupCompleted = false;
810
+ this.orm = null;
811
+ this.config = {
812
+ debug: config.debug ?? false,
813
+ timeout: config.timeout ?? DEFAULT_TIMEOUT,
814
+ manifest: config.manifest
815
+ };
816
+ this.storage = new StorageAPI(this);
817
+ this.database = new DatabaseAPI(this);
818
+ this.filesystem = new FilesystemAPI(this);
819
+ this.web = new WebAPI(this);
820
+ this.permissions = new PermissionsAPI(this);
821
+ installConsoleForwarding(this.config.debug);
822
+ this.readyPromise = new Promise((resolve) => {
823
+ this.resolveReady = resolve;
824
+ });
825
+ this.init();
826
+ }
827
+ /**
828
+ * Gibt ein Promise zurück, das aufgelöst wird, sobald der Client
829
+ * initialisiert ist und Extension-Infos empfangen hat.
830
+ */
831
+ async ready() {
832
+ return this.readyPromise;
833
+ }
834
+ /**
835
+ * Gibt zurück, ob das Setup bereits abgeschlossen wurde.
836
+ */
837
+ get setupCompleted() {
838
+ return this._setupCompleted;
839
+ }
840
+ /**
841
+ * Registriert eine Setup-Funktion, die nach der Initialisierung ausgeführt wird.
842
+ * Diese Funktion sollte für Aufgaben wie Tabellenerstellung, Migrationen, etc. verwendet werden.
843
+ * @param setupFn Die Setup-Funktion, die ausgeführt werden soll
844
+ */
845
+ onSetup(setupFn) {
846
+ if (this.setupHook) {
847
+ throw new Error("Setup hook already registered");
848
+ }
849
+ this.setupHook = setupFn;
850
+ }
851
+ /**
852
+ * Gibt ein Promise zurück, das aufgelöst wird, sobald der Client vollständig eingerichtet ist.
853
+ * Dies umfasst die Initialisierung UND das Setup (z.B. Tabellenerstellung).
854
+ * Falls kein Setup-Hook registriert wurde, entspricht dies ready().
855
+ */
856
+ async setupComplete() {
857
+ await this.readyPromise;
858
+ if (!this.setupHook || this.setupCompleted) {
859
+ return;
860
+ }
861
+ if (!this.setupPromise) {
862
+ this.setupPromise = this.runSetupAsync();
863
+ }
864
+ return this.setupPromise;
865
+ }
866
+ async runSetupAsync() {
867
+ if (!this.setupHook) return;
868
+ try {
869
+ this.log("[HaexHub] Running setup hook...");
870
+ await this.setupHook();
871
+ this._setupCompleted = true;
872
+ this.log("[HaexHub] Setup completed successfully");
873
+ this.notifySubscribers();
874
+ } catch (error) {
875
+ this.log("[HaexHub] Setup failed:", error);
876
+ throw error;
877
+ }
878
+ }
879
+ /**
880
+ * Initialisiert die Drizzle-Datenbankinstanz.
881
+ * Muss nach der Definition des Schemas aufgerufen werden.
882
+ * @param schema Das Drizzle-Schemaobjekt (mit bereits geprefixten Tabellennamen).
883
+ * @returns Die typsichere Drizzle-Datenbankinstanz.
884
+ */
885
+ initializeDatabase(schema) {
886
+ if (!this._extensionInfo) {
887
+ throw new HaexHubError(
888
+ "EXTENSION_INFO_UNAVAILABLE" /* EXTENSION_INFO_UNAVAILABLE */,
889
+ "errors.client_not_ready"
890
+ );
891
+ }
892
+ const dbInstance = drizzle(
893
+ async (sql, params, method) => {
894
+ try {
895
+ if (method === "run" || method === "all") {
896
+ const result2 = await this.request(
897
+ HAEXTENSION_METHODS.database.execute,
898
+ {
899
+ query: sql,
900
+ params
901
+ }
902
+ );
903
+ if (method === "all") {
904
+ return { rows: result2.rows || [] };
905
+ }
906
+ if (result2.rows && Array.isArray(result2.rows) && result2.rows.length > 0) {
907
+ return { rows: result2.rows };
908
+ }
909
+ return result2;
910
+ }
911
+ const result = await this.request(HAEXTENSION_METHODS.database.query, {
912
+ query: sql,
913
+ params
914
+ });
915
+ const rows = result.rows;
916
+ if (method === "get") {
917
+ return { rows: rows.length > 0 ? rows.at(0) : void 0 };
918
+ }
919
+ return { rows };
920
+ } catch (error) {
921
+ this.log("Database operation failed:", error);
922
+ throw error;
923
+ }
924
+ },
925
+ {
926
+ schema,
927
+ logger: false
928
+ }
929
+ );
930
+ this.orm = dbInstance;
931
+ return dbInstance;
932
+ }
933
+ get extensionInfo() {
934
+ return this._extensionInfo;
935
+ }
936
+ get context() {
937
+ return this._context;
938
+ }
939
+ subscribe(callback) {
940
+ this.reactiveSubscribers.add(callback);
941
+ return () => {
942
+ this.reactiveSubscribers.delete(callback);
943
+ };
944
+ }
945
+ notifySubscribers() {
946
+ this.reactiveSubscribers.forEach((callback) => callback());
947
+ }
948
+ async getDependencies() {
949
+ return this.request("extensions.getDependencies");
950
+ }
951
+ getTableName(tableName) {
952
+ if (!this._extensionInfo) {
953
+ throw new HaexHubError(
954
+ "EXTENSION_INFO_UNAVAILABLE" /* EXTENSION_INFO_UNAVAILABLE */,
955
+ "errors.extension_info_unavailable"
956
+ );
957
+ }
958
+ this.validateTableName(tableName);
959
+ const { publicKey, name } = this._extensionInfo;
960
+ const extensionName = name;
961
+ return `"${publicKey}${TABLE_SEPARATOR}${extensionName}${TABLE_SEPARATOR}${tableName}"`;
962
+ }
963
+ getDependencyTableName(publicKey, extensionName, tableName) {
964
+ this.validatePublicKey(publicKey);
965
+ this.validateExtensionName(extensionName);
966
+ this.validateTableName(tableName);
967
+ return `"${publicKey}${TABLE_SEPARATOR}${extensionName}${TABLE_SEPARATOR}${tableName}"`;
968
+ }
969
+ parseTableName(fullTableName) {
970
+ let cleanTableName = fullTableName;
971
+ if (cleanTableName.startsWith('"') && cleanTableName.endsWith('"')) {
972
+ cleanTableName = cleanTableName.slice(1, -1);
973
+ }
974
+ const parts = cleanTableName.split(TABLE_SEPARATOR);
975
+ if (parts.length !== 3) {
976
+ return null;
977
+ }
978
+ const [publicKey, extensionName, tableName] = parts;
979
+ if (!publicKey || !extensionName || !tableName) {
980
+ return null;
981
+ }
982
+ return {
983
+ publicKey,
984
+ extensionName,
985
+ tableName
986
+ };
987
+ }
988
+ /**
989
+ * Execute a raw SQL query (SELECT)
990
+ * Returns rows as an array of objects
991
+ */
992
+ async query(sql, params = []) {
993
+ const result = await this.request(
994
+ HAEXTENSION_METHODS.database.query,
995
+ { query: sql, params }
996
+ );
997
+ if (this.config.debug) {
998
+ console.log("[SDK query()] Raw result:", JSON.stringify(result, null, 2));
999
+ }
1000
+ return result.rows;
1001
+ }
1002
+ /**
1003
+ * Alias for query() - more intuitive for SELECT statements
1004
+ */
1005
+ async select(sql, params = []) {
1006
+ return this.query(sql, params);
1007
+ }
1008
+ /**
1009
+ * Execute a raw SQL statement (INSERT, UPDATE, DELETE, CREATE, etc.)
1010
+ * Returns rowsAffected and lastInsertId
1011
+ */
1012
+ async execute(sql, params = []) {
1013
+ const result = await this.request(
1014
+ HAEXTENSION_METHODS.database.execute,
1015
+ { query: sql, params }
1016
+ );
1017
+ return {
1018
+ rowsAffected: result.rowsAffected,
1019
+ lastInsertId: result.lastInsertId
1020
+ };
1021
+ }
1022
+ /**
1023
+ * Registers extension migrations with HaexVault for CRDT synchronization
1024
+ * HaexVault will validate and execute these migrations
1025
+ * @param extensionVersion - The version of the extension
1026
+ * @param migrations - Array of migration objects with name and SQL content
1027
+ * @returns Promise that resolves when migrations are registered
1028
+ */
1029
+ async registerMigrationsAsync(extensionVersion, migrations) {
1030
+ return this.database.registerMigrationsAsync(extensionVersion, migrations);
1031
+ }
1032
+ async requestDatabasePermission(request) {
1033
+ return this.request("permissions.database.request", {
1034
+ resource: request.resource,
1035
+ operation: request.operation,
1036
+ reason: request.reason
1037
+ });
1038
+ }
1039
+ async checkDatabasePermission(resource, operation) {
1040
+ const response = await this.request(
1041
+ "permissions.database.check",
1042
+ {
1043
+ resource,
1044
+ operation
1045
+ }
1046
+ );
1047
+ return response.status === "granted";
1048
+ }
1049
+ async respondToSearch(requestId, results) {
1050
+ await this.request("search.respond", {
1051
+ requestId,
1052
+ results
1053
+ });
1054
+ }
1055
+ async request(method, params = {}) {
1056
+ if (this.isNativeWindow && typeof window.__TAURI__ !== "undefined") {
1057
+ return this.invoke(method, params);
1058
+ }
1059
+ return this.postMessage(method, params);
1060
+ }
1061
+ async postMessage(method, params) {
1062
+ const requestId = this.generateRequestId();
1063
+ const request = {
1064
+ method,
1065
+ params,
1066
+ timestamp: Date.now()
1067
+ };
1068
+ return new Promise((resolve, reject) => {
1069
+ const timeout = setTimeout(() => {
1070
+ this.pendingRequests.delete(requestId);
1071
+ reject(
1072
+ new HaexHubError("TIMEOUT" /* TIMEOUT */, "errors.timeout", {
1073
+ timeout: this.config.timeout
1074
+ })
1075
+ );
1076
+ }, this.config.timeout);
1077
+ this.pendingRequests.set(requestId, { resolve, reject, timeout });
1078
+ const targetOrigin = "*";
1079
+ if (this.config.debug) {
1080
+ console.log("[SDK Debug] ========== Sending Request ==========");
1081
+ console.log("[SDK Debug] Request ID:", requestId);
1082
+ console.log("[SDK Debug] Method:", request.method);
1083
+ console.log("[SDK Debug] Params:", request.params);
1084
+ console.log("[SDK Debug] Target origin:", targetOrigin);
1085
+ console.log("[SDK Debug] Extension info:", this._extensionInfo);
1086
+ console.log("[SDK Debug] ========================================");
1087
+ }
1088
+ window.parent.postMessage({ id: requestId, ...request }, targetOrigin);
1089
+ });
1090
+ }
1091
+ async invoke(method, params) {
1092
+ const { invoke } = window.__TAURI__.core;
1093
+ if (this.config.debug) {
1094
+ console.log("[SDK Debug] ========== Invoke Request ==========");
1095
+ console.log("[SDK Debug] Method:", method);
1096
+ console.log("[SDK Debug] Params:", params);
1097
+ console.log("[SDK Debug] =======================================");
1098
+ }
1099
+ switch (method) {
1100
+ case HAEXTENSION_METHODS.database.query:
1101
+ return invoke("webview_extension_db_query", {
1102
+ query: params.query,
1103
+ params: params.params || []
1104
+ });
1105
+ case HAEXTENSION_METHODS.database.execute:
1106
+ return invoke("webview_extension_db_execute", {
1107
+ query: params.query,
1108
+ params: params.params || []
1109
+ });
1110
+ case "permissions.web.check":
1111
+ return invoke("webview_extension_check_web_permission", {
1112
+ url: params.url
1113
+ });
1114
+ case "permissions.database.check":
1115
+ return invoke("webview_extension_check_database_permission", {
1116
+ resource: params.resource,
1117
+ operation: params.operation
1118
+ });
1119
+ case "permissions.filesystem.check":
1120
+ return invoke("webview_extension_check_filesystem_permission", {
1121
+ path: params.path,
1122
+ actionStr: params.action
1123
+ });
1124
+ case HAEXTENSION_METHODS.application.open:
1125
+ return invoke("webview_extension_web_open", {
1126
+ url: params.url
1127
+ });
1128
+ case HAEXTENSION_METHODS.web.fetch:
1129
+ return invoke("webview_extension_web_request", {
1130
+ url: params.url,
1131
+ method: params.method,
1132
+ headers: params.headers,
1133
+ body: params.body
1134
+ });
1135
+ case HAEXTENSION_METHODS.filesystem.saveFile:
1136
+ return invoke("webview_extension_fs_save_file", {
1137
+ data: params.data,
1138
+ defaultPath: params.defaultPath,
1139
+ title: params.title,
1140
+ filters: params.filters
1141
+ });
1142
+ case HAEXTENSION_METHODS.filesystem.openFile:
1143
+ return invoke("webview_extension_fs_open_file", {
1144
+ data: params.data,
1145
+ fileName: params.fileName
1146
+ });
1147
+ default:
1148
+ throw new HaexHubError(
1149
+ "METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
1150
+ "errors.method_not_found",
1151
+ { method }
1152
+ );
1153
+ }
1154
+ }
1155
+ on(eventType, callback) {
1156
+ if (!this.eventListeners.has(eventType)) {
1157
+ this.eventListeners.set(eventType, /* @__PURE__ */ new Set());
1158
+ }
1159
+ this.eventListeners.get(eventType).add(callback);
1160
+ }
1161
+ off(eventType, callback) {
1162
+ const listeners = this.eventListeners.get(eventType);
1163
+ if (listeners) {
1164
+ listeners.delete(callback);
1165
+ }
1166
+ }
1167
+ destroy() {
1168
+ if (this.messageHandler) {
1169
+ window.removeEventListener("message", this.messageHandler);
1170
+ }
1171
+ this.pendingRequests.forEach(({ timeout }) => clearTimeout(timeout));
1172
+ this.pendingRequests.clear();
1173
+ this.eventListeners.clear();
1174
+ this.initialized = false;
1175
+ this.log("HaexHub SDK destroyed");
1176
+ }
1177
+ async init() {
1178
+ if (this.initialized) return;
1179
+ const isInIframe = window.self !== window.top;
1180
+ if (!isInIframe) {
1181
+ try {
1182
+ if (typeof window.__TAURI__ !== "undefined") {
1183
+ const { invoke } = window.__TAURI__.core;
1184
+ this._extensionInfo = await invoke("webview_extension_get_info");
1185
+ this._context = await invoke("webview_extension_context_get");
1186
+ this.isNativeWindow = true;
1187
+ this.initialized = true;
1188
+ this.log("HaexHub SDK initialized in native WebViewWindow mode");
1189
+ this.log("Extension info:", this._extensionInfo);
1190
+ this.log("Application context:", this._context);
1191
+ this.notifySubscribers();
1192
+ const { listen } = window.__TAURI__.event;
1193
+ console.log("[HaexHub SDK] Setting up Tauri event listener for:", HAEXTENSION_EVENTS.CONTEXT_CHANGED);
1194
+ try {
1195
+ await listen(HAEXTENSION_EVENTS.CONTEXT_CHANGED, (event) => {
1196
+ console.log("[HaexHub SDK] Received Tauri event:", HAEXTENSION_EVENTS.CONTEXT_CHANGED, event);
1197
+ this.log("Received context change event:", event);
1198
+ if (event.payload?.context) {
1199
+ this._context = event.payload.context;
1200
+ console.log("[HaexHub SDK] Updated context to:", this._context);
1201
+ this.handleEvent({
1202
+ type: HAEXTENSION_EVENTS.CONTEXT_CHANGED,
1203
+ data: { context: this._context },
1204
+ timestamp: Date.now()
1205
+ });
1206
+ } else {
1207
+ console.warn("[HaexHub SDK] Event received but no context in payload:", event);
1208
+ }
1209
+ });
1210
+ console.log("[HaexHub SDK] Context change listener registered successfully");
1211
+ } catch (error) {
1212
+ console.error("[HaexHub SDK] Failed to setup context change listener:", error);
1213
+ this.log("Failed to setup context change listener:", error);
1214
+ }
1215
+ this.resolveReady();
1216
+ return;
1217
+ }
1218
+ } catch (error) {
1219
+ this.log("Tauri commands failed, falling back to iframe mode", error);
1220
+ }
1221
+ }
1222
+ if (window.self === window.top) {
1223
+ throw new HaexHubError("NOT_IN_IFRAME" /* NOT_IN_IFRAME */, "errors.not_in_iframe");
1224
+ }
1225
+ this.messageHandler = this.handleMessage.bind(this);
1226
+ window.addEventListener("message", this.messageHandler);
1227
+ this.isNativeWindow = false;
1228
+ this.initialized = true;
1229
+ this.log("HaexHub SDK initialized in iframe mode");
1230
+ try {
1231
+ if (this.config.manifest) {
1232
+ this._extensionInfo = {
1233
+ publicKey: this.config.manifest.publicKey,
1234
+ name: this.config.manifest.name,
1235
+ version: this.config.manifest.version,
1236
+ displayName: this.config.manifest.name
1237
+ };
1238
+ this.log("Extension info loaded from manifest:", this._extensionInfo);
1239
+ this.notifySubscribers();
1240
+ }
1241
+ if (typeof window !== "undefined" && window.parent) {
1242
+ const debugInfo = `SDK Debug:
1243
+ window.parent exists: ${!!window.parent}
1244
+ window.parent === window: ${window.parent === window}
1245
+ window.self === window.top: ${window.self === window.top}`;
1246
+ try {
1247
+ window.parent.postMessage({
1248
+ type: "haexhub:debug",
1249
+ data: debugInfo
1250
+ }, "*");
1251
+ } catch (e) {
1252
+ alert(debugInfo + `
1253
+ postMessage error: ${e}`);
1254
+ }
1255
+ }
1256
+ this._context = await this.request(HAEXTENSION_METHODS.context.get);
1257
+ this.log("Application context received:", this._context);
1258
+ this.notifySubscribers();
1259
+ this.resolveReady();
1260
+ } catch (error) {
1261
+ this.log("Failed to load extension info or context:", error);
1262
+ throw error;
1263
+ }
1264
+ }
1265
+ handleMessage(event) {
1266
+ if (this.config.debug) {
1267
+ console.log("[SDK Debug] ========== Message Received ==========");
1268
+ console.log("[SDK Debug] Event origin:", event.origin);
1269
+ console.log(
1270
+ "[SDK Debug] Event source:",
1271
+ event.source === window.parent ? "parent window" : "unknown"
1272
+ );
1273
+ console.log("[SDK Debug] Event data:", event.data);
1274
+ console.log("[SDK Debug] Extension info loaded:", !!this._extensionInfo);
1275
+ console.log(
1276
+ "[SDK Debug] Pending requests count:",
1277
+ this.pendingRequests.size
1278
+ );
1279
+ }
1280
+ if (event.source !== window.parent) {
1281
+ if (this.config.debug) {
1282
+ console.error("[SDK Debug] \u274C REJECTED: Message not from parent window!");
1283
+ }
1284
+ return;
1285
+ }
1286
+ const data = event.data;
1287
+ if ("id" in data && this.pendingRequests.has(data.id)) {
1288
+ if (this.config.debug) {
1289
+ console.log("[SDK Debug] \u2705 Found pending request for ID:", data.id);
1290
+ }
1291
+ const pending = this.pendingRequests.get(data.id);
1292
+ clearTimeout(pending.timeout);
1293
+ this.pendingRequests.delete(data.id);
1294
+ if (data.error) {
1295
+ if (this.config.debug) {
1296
+ console.error("[SDK Debug] \u274C Request failed:", data.error);
1297
+ }
1298
+ pending.reject(data.error);
1299
+ } else {
1300
+ if (this.config.debug) {
1301
+ console.log("[SDK Debug] \u2705 Request succeeded:", data.result);
1302
+ }
1303
+ pending.resolve(data.result);
1304
+ }
1305
+ return;
1306
+ }
1307
+ if ("id" in data && !this.pendingRequests.has(data.id)) {
1308
+ if (this.config.debug) {
1309
+ console.warn(
1310
+ "[SDK Debug] \u26A0\uFE0F Received response for unknown request ID:",
1311
+ data.id
1312
+ );
1313
+ console.warn(
1314
+ "[SDK Debug] Known IDs:",
1315
+ Array.from(this.pendingRequests.keys())
1316
+ );
1317
+ }
1318
+ }
1319
+ if ("type" in data && data.type) {
1320
+ if (this.config.debug) {
1321
+ console.log("[SDK Debug] Event received:", data.type);
1322
+ }
1323
+ this.handleEvent(data);
1324
+ }
1325
+ if (this.config.debug) {
1326
+ console.log("[SDK Debug] ========== End Message ==========");
1327
+ }
1328
+ }
1329
+ handleEvent(event) {
1330
+ if (event.type === HAEXTENSION_EVENTS.CONTEXT_CHANGED) {
1331
+ const contextEvent = event;
1332
+ this._context = contextEvent.data.context;
1333
+ this.log("Context updated:", this._context);
1334
+ this.notifySubscribers();
1335
+ }
1336
+ this.emitEvent(event);
1337
+ }
1338
+ emitEvent(event) {
1339
+ this.log("Event received:", event);
1340
+ const listeners = this.eventListeners.get(event.type);
1341
+ if (listeners) {
1342
+ listeners.forEach((callback) => callback(event));
1343
+ }
1344
+ }
1345
+ generateRequestId() {
1346
+ return `req_${++this.requestCounter}`;
1347
+ }
1348
+ validatePublicKey(publicKey) {
1349
+ if (!publicKey || typeof publicKey !== "string" || publicKey.trim() === "") {
1350
+ throw new HaexHubError(
1351
+ "INVALID_PUBLIC_KEY" /* INVALID_PUBLIC_KEY */,
1352
+ "errors.invalid_public_key",
1353
+ { publicKey }
1354
+ );
1355
+ }
1356
+ }
1357
+ validateExtensionName(extensionName) {
1358
+ if (!extensionName || !/^[a-z][a-z0-9-]*$/i.test(extensionName)) {
1359
+ throw new HaexHubError(
1360
+ "INVALID_EXTENSION_NAME" /* INVALID_EXTENSION_NAME */,
1361
+ "errors.invalid_extension_name",
1362
+ { extensionName }
1363
+ );
1364
+ }
1365
+ if (extensionName.includes(TABLE_SEPARATOR)) {
1366
+ throw new HaexHubError(
1367
+ "INVALID_EXTENSION_NAME" /* INVALID_EXTENSION_NAME */,
1368
+ "errors.extension_name_contains_separator",
1369
+ { extensionName, separator: TABLE_SEPARATOR }
1370
+ );
1371
+ }
1372
+ }
1373
+ validateTableName(tableName) {
1374
+ if (!tableName || typeof tableName !== "string") {
1375
+ throw new HaexHubError(
1376
+ "INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
1377
+ "errors.table_name_empty"
1378
+ );
1379
+ }
1380
+ if (tableName.includes(TABLE_SEPARATOR)) {
1381
+ throw new HaexHubError(
1382
+ "INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
1383
+ "errors.table_name_contains_separator",
1384
+ { tableName, separator: TABLE_SEPARATOR }
1385
+ );
1386
+ }
1387
+ if (!/^[a-z][a-z0-9-_]*$/i.test(tableName)) {
1388
+ throw new HaexHubError(
1389
+ "INVALID_TABLE_NAME" /* INVALID_TABLE_NAME */,
1390
+ "errors.table_name_format",
1391
+ { tableName }
1392
+ );
1393
+ }
1394
+ }
1395
+ log(...args) {
1396
+ if (this.config.debug) {
1397
+ console.log("[HaexHub SDK]", ...args);
1398
+ }
1399
+ }
1400
+ };
1401
+
1402
+ // src/index.ts
1403
+ function createHaexVaultClient(config = {}) {
1404
+ return new HaexVaultClient(config);
1405
+ }
1406
+
1407
+ export { DEFAULT_TIMEOUT, DatabaseAPI, ErrorCode, FilesystemAPI, HAEXTENSION_EVENTS, HAEXTENSION_METHODS, HaexHubError, HaexVaultClient, PermissionStatus, PermissionsAPI, TABLE_SEPARATOR, WebAPI, createHaexVaultClient, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill };
1408
+ //# sourceMappingURL=index.mjs.map
1409
+ //# sourceMappingURL=index.mjs.map