@kodexa-ai/document-wasm-ts 2026.2.0-develop-21783247139 → 2026.2.0-develop-21948235892
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/kodexa-shared-worker.js +94 -22
- package/dist/kodexa-shared-worker.js.map +2 -2
- package/dist/kodexa.wasm +0 -0
- package/dist/wasm/types.d.ts +0 -2
- package/dist/wasm/types.d.ts.map +1 -1
- package/dist/wasm/types.js.map +1 -1
- package/dist/worker/KodexaSharedWorker.d.ts +20 -0
- package/dist/worker/KodexaSharedWorker.d.ts.map +1 -1
- package/dist/worker/KodexaSharedWorker.js +85 -8
- package/dist/worker/KodexaSharedWorker.js.map +1 -1
- package/dist/worker/KodexaWorkerDocument.d.ts +5 -0
- package/dist/worker/KodexaWorkerDocument.d.ts.map +1 -1
- package/dist/worker/KodexaWorkerDocument.js +12 -0
- package/dist/worker/KodexaWorkerDocument.js.map +1 -1
- package/dist/worker/kodexa-shared-worker.js +116 -20
- package/dist/worker/kodexa-shared-worker.js.map +1 -1
- package/dist/worker/types.d.ts +23 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -465,6 +465,10 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
465
465
|
"src/worker/kodexa-shared-worker.ts"(exports, module) {
|
|
466
466
|
init_sqljs_core();
|
|
467
467
|
var ports = /* @__PURE__ */ new Map();
|
|
468
|
+
var lastHeartbeat = /* @__PURE__ */ new Map();
|
|
469
|
+
var heartbeatIntervalId = null;
|
|
470
|
+
var STALE_PORT_THRESHOLD_MS = 6e4;
|
|
471
|
+
var HEARTBEAT_CHECK_INTERVAL_MS = 3e4;
|
|
468
472
|
var nextPortId = 1;
|
|
469
473
|
function generatePortId() {
|
|
470
474
|
return `port_${nextPortId++}_${Date.now()}`;
|
|
@@ -510,20 +514,50 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
510
514
|
function loadSharedDocument(documentFamilyId, portId, kddbBytes) {
|
|
511
515
|
if (sharedDocuments.has(documentFamilyId)) {
|
|
512
516
|
const existingDocRef = sharedDocuments.get(documentFamilyId);
|
|
513
|
-
let
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
517
|
+
let isValid = false;
|
|
518
|
+
const docUsers = documentUsers.get(existingDocRef);
|
|
519
|
+
if (docUsers && docUsers.size > 0) {
|
|
520
|
+
const documentGetRoot = self.documentGetRoot;
|
|
521
|
+
if (typeof documentGetRoot === "function") {
|
|
522
|
+
try {
|
|
523
|
+
const root = documentGetRoot(existingDocRef);
|
|
524
|
+
isValid = root !== null && root !== void 0;
|
|
525
|
+
} catch {
|
|
526
|
+
isValid = false;
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
isValid = true;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (!isValid) {
|
|
533
|
+
console.warn(`[shared-worker] Stale shared document ${documentFamilyId} (docRef: ${existingDocRef}), cleaning up`);
|
|
534
|
+
const staleUsers = sharedDocumentUsers.get(documentFamilyId);
|
|
535
|
+
if (staleUsers) {
|
|
536
|
+
for (const uid of staleUsers) {
|
|
537
|
+
unsubscribeFromDocument(existingDocRef, uid);
|
|
538
|
+
unregisterDocumentUser(existingDocRef, uid);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
sharedDocuments.delete(documentFamilyId);
|
|
542
|
+
sharedDocumentUsers.delete(documentFamilyId);
|
|
543
|
+
documentSubscriptions.delete(existingDocRef);
|
|
544
|
+
documentUsers.delete(existingDocRef);
|
|
545
|
+
} else {
|
|
546
|
+
let users2 = sharedDocumentUsers.get(documentFamilyId);
|
|
547
|
+
if (!users2) {
|
|
548
|
+
users2 = /* @__PURE__ */ new Set();
|
|
549
|
+
sharedDocumentUsers.set(documentFamilyId, users2);
|
|
550
|
+
}
|
|
551
|
+
users2.add(portId);
|
|
552
|
+
registerDocumentUser(existingDocRef, portId);
|
|
553
|
+
subscribeToDocument(existingDocRef, portId);
|
|
554
|
+
console.log(`[shared-worker] Port ${portId} joined shared document ${documentFamilyId} (docRef: ${existingDocRef}), ${users2.size} users`);
|
|
555
|
+
return {
|
|
556
|
+
docRef: existingDocRef,
|
|
557
|
+
shared: true,
|
|
558
|
+
userCount: users2.size
|
|
559
|
+
};
|
|
560
|
+
}
|
|
527
561
|
}
|
|
528
562
|
if (!kddbBytes) {
|
|
529
563
|
throw new Error(`Document ${documentFamilyId} not loaded and no bytes provided`);
|
|
@@ -666,7 +700,25 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
666
700
|
documentUsers.delete(docRef);
|
|
667
701
|
}
|
|
668
702
|
}
|
|
703
|
+
lastHeartbeat.delete(portId);
|
|
669
704
|
ports.delete(portId);
|
|
705
|
+
if (ports.size === 0 && heartbeatIntervalId) {
|
|
706
|
+
clearInterval(heartbeatIntervalId);
|
|
707
|
+
heartbeatIntervalId = null;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
function checkForStalePorts() {
|
|
711
|
+
const now = Date.now();
|
|
712
|
+
const stalePorts = [];
|
|
713
|
+
for (const [portId, lastBeat] of lastHeartbeat) {
|
|
714
|
+
if (now - lastBeat >= STALE_PORT_THRESHOLD_MS) {
|
|
715
|
+
stalePorts.push(portId);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
for (const portId of stalePorts) {
|
|
719
|
+
console.log(`[shared-worker] Port ${portId} stale (no heartbeat for ${STALE_PORT_THRESHOLD_MS}ms), cleaning up`);
|
|
720
|
+
cleanupPort(portId);
|
|
721
|
+
}
|
|
670
722
|
}
|
|
671
723
|
function broadcastToSubscribers(docRef, eventType, detail) {
|
|
672
724
|
const subscribers = documentSubscriptions.get(docRef);
|
|
@@ -910,22 +962,24 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
910
962
|
return;
|
|
911
963
|
}
|
|
912
964
|
if ("type" in data && data.type === "loadSharedDocument") {
|
|
965
|
+
const { documentFamilyId, kddbBytes, requestId } = data;
|
|
913
966
|
if (!initialized) {
|
|
914
967
|
port.postMessage({
|
|
915
968
|
type: "sharedDocumentResponse",
|
|
916
969
|
success: false,
|
|
917
970
|
error: "Worker not initialized",
|
|
918
|
-
requestType: "loadSharedDocument"
|
|
971
|
+
requestType: "loadSharedDocument",
|
|
972
|
+
requestId
|
|
919
973
|
});
|
|
920
974
|
return;
|
|
921
975
|
}
|
|
922
976
|
try {
|
|
923
|
-
const { documentFamilyId, kddbBytes } = data;
|
|
924
977
|
const result = loadSharedDocument(documentFamilyId, portId, kddbBytes);
|
|
925
978
|
port.postMessage({
|
|
926
979
|
type: "sharedDocumentResponse",
|
|
927
980
|
success: true,
|
|
928
981
|
requestType: "loadSharedDocument",
|
|
982
|
+
requestId,
|
|
929
983
|
...result
|
|
930
984
|
});
|
|
931
985
|
} catch (error) {
|
|
@@ -933,19 +987,21 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
933
987
|
type: "sharedDocumentResponse",
|
|
934
988
|
success: false,
|
|
935
989
|
error: error instanceof Error ? error.message : String(error),
|
|
936
|
-
requestType: "loadSharedDocument"
|
|
990
|
+
requestType: "loadSharedDocument",
|
|
991
|
+
requestId
|
|
937
992
|
});
|
|
938
993
|
}
|
|
939
994
|
return;
|
|
940
995
|
}
|
|
941
996
|
if ("type" in data && data.type === "releaseSharedDocument") {
|
|
997
|
+
const { documentFamilyId, requestId } = data;
|
|
942
998
|
try {
|
|
943
|
-
const { documentFamilyId } = data;
|
|
944
999
|
const result = releaseSharedDocument(documentFamilyId, portId);
|
|
945
1000
|
port.postMessage({
|
|
946
1001
|
type: "sharedDocumentResponse",
|
|
947
1002
|
success: true,
|
|
948
1003
|
requestType: "releaseSharedDocument",
|
|
1004
|
+
requestId,
|
|
949
1005
|
...result
|
|
950
1006
|
});
|
|
951
1007
|
} catch (error) {
|
|
@@ -953,34 +1009,46 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
953
1009
|
type: "sharedDocumentResponse",
|
|
954
1010
|
success: false,
|
|
955
1011
|
error: error instanceof Error ? error.message : String(error),
|
|
956
|
-
requestType: "releaseSharedDocument"
|
|
1012
|
+
requestType: "releaseSharedDocument",
|
|
1013
|
+
requestId
|
|
957
1014
|
});
|
|
958
1015
|
}
|
|
959
1016
|
return;
|
|
960
1017
|
}
|
|
961
1018
|
if ("type" in data && data.type === "isDocumentShared") {
|
|
962
|
-
const { documentFamilyId } = data;
|
|
1019
|
+
const { documentFamilyId, requestId } = data;
|
|
963
1020
|
const shared = isDocumentShared(documentFamilyId);
|
|
964
1021
|
const docRef = getSharedDocumentRef(documentFamilyId);
|
|
965
1022
|
port.postMessage({
|
|
966
1023
|
type: "sharedDocumentResponse",
|
|
967
1024
|
success: true,
|
|
968
1025
|
requestType: "isDocumentShared",
|
|
1026
|
+
requestId,
|
|
969
1027
|
shared,
|
|
970
1028
|
docRef
|
|
971
1029
|
});
|
|
972
1030
|
return;
|
|
973
1031
|
}
|
|
974
1032
|
if ("type" in data && data.type === "invalidateSharedDocument") {
|
|
975
|
-
const { documentFamilyId, reason } = data;
|
|
1033
|
+
const { documentFamilyId, reason, requestId } = data;
|
|
976
1034
|
invalidateSharedDocument(documentFamilyId, portId, reason || "reload");
|
|
977
1035
|
port.postMessage({
|
|
978
1036
|
type: "sharedDocumentResponse",
|
|
979
1037
|
success: true,
|
|
980
|
-
requestType: "invalidateSharedDocument"
|
|
1038
|
+
requestType: "invalidateSharedDocument",
|
|
1039
|
+
requestId
|
|
981
1040
|
});
|
|
982
1041
|
return;
|
|
983
1042
|
}
|
|
1043
|
+
if ("type" in data && data.type === "heartbeat") {
|
|
1044
|
+
lastHeartbeat.set(portId, Date.now());
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
if ("type" in data && data.type === "disconnect") {
|
|
1048
|
+
console.log(`[shared-worker] Port ${portId} sent disconnect message, cleaning up`);
|
|
1049
|
+
cleanupPort(portId);
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
984
1052
|
if ("type" in data && data.type === "call") {
|
|
985
1053
|
if (!initialized) {
|
|
986
1054
|
const response3 = {
|
|
@@ -1002,12 +1070,16 @@ var require_kodexa_shared_worker = __commonJS({
|
|
|
1002
1070
|
const portId = generatePortId();
|
|
1003
1071
|
console.log(`[shared-worker] New port connected: ${portId}`);
|
|
1004
1072
|
ports.set(portId, port);
|
|
1073
|
+
lastHeartbeat.set(portId, Date.now());
|
|
1005
1074
|
port.onmessage = (e) => handlePortMessage(portId, port, e);
|
|
1006
1075
|
port.onmessageerror = () => {
|
|
1007
1076
|
console.log(`[shared-worker] Port ${portId} message error, cleaning up`);
|
|
1008
1077
|
cleanupPort(portId);
|
|
1009
1078
|
};
|
|
1010
1079
|
port.start();
|
|
1080
|
+
if (!heartbeatIntervalId) {
|
|
1081
|
+
heartbeatIntervalId = setInterval(checkForStalePorts, HEARTBEAT_CHECK_INTERVAL_MS);
|
|
1082
|
+
}
|
|
1011
1083
|
if (initialized) {
|
|
1012
1084
|
const readyMessage = { type: "ready", portId };
|
|
1013
1085
|
port.postMessage(readyMessage);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/wasm/sqljs-core.ts", "../src/worker/kodexa-shared-worker.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Core sql.js bridge operations - shared between environments\n *\n * This module contains all the database operations that are common between\n * the npm package (sqljs-bridge.ts) and browser CDN (browser-bridge.ts) implementations.\n *\n * The SQL instance is passed in from the wrapper modules, allowing them to\n * load sql.js in different ways (npm import vs CDN global).\n */\n\n// Database handle management\nconst databases = new Map<number, any>();\nlet nextHandle = 1;\n\n// Store SQL instance reference for operations that need it\nlet sqlInstance: any = null;\n\n// ============================================================================\n// Performance Tracing\n// ============================================================================\n\ninterface SqlStats {\n count: number;\n totalMs: number;\n minMs: number;\n maxMs: number;\n errors: number;\n}\n\ninterface QueryTrace {\n sql: string;\n paramsJson: string;\n startTime: number;\n endTime: number;\n duration: number;\n rowCount: number;\n error?: string;\n}\n\nclass SqlPerformanceTracer {\n private enabled = false;\n private stats: Map<string, SqlStats> = new Map();\n private recentTraces: QueryTrace[] = [];\n private maxRecentTraces = 100;\n private sessionStart = 0;\n private logQueries = false;\n private slowQueryThreshold = 10; // ms\n\n enable(options?: { logQueries?: boolean; slowQueryThreshold?: number }): void {\n this.enabled = true;\n this.sessionStart = performance.now();\n this.logQueries = options?.logQueries ?? false;\n this.slowQueryThreshold = options?.slowQueryThreshold ?? 10;\n this.reset();\n console.log('[sql.js PERF] Performance tracing ENABLED', {\n logQueries: this.logQueries,\n slowQueryThreshold: this.slowQueryThreshold + 'ms'\n });\n }\n\n disable(): void {\n this.enabled = false;\n console.log('[sql.js PERF] Performance tracing DISABLED');\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n reset(): void {\n this.stats.clear();\n this.recentTraces = [];\n this.sessionStart = performance.now();\n }\n\n private extractQueryType(sql: string): string {\n const trimmed = sql.trim().toUpperCase();\n if (trimmed.startsWith('SELECT')) {\n // Extract table name for SELECT queries\n const match = sql.match(/FROM\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `SELECT:${match[1]}` : 'SELECT';\n }\n if (trimmed.startsWith('INSERT')) {\n const match = sql.match(/INTO\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `INSERT:${match[1]}` : 'INSERT';\n }\n if (trimmed.startsWith('UPDATE')) {\n const match = sql.match(/UPDATE\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `UPDATE:${match[1]}` : 'UPDATE';\n }\n if (trimmed.startsWith('DELETE')) {\n const match = sql.match(/FROM\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `DELETE:${match[1]}` : 'DELETE';\n }\n if (trimmed.startsWith('BEGIN')) return 'BEGIN';\n if (trimmed.startsWith('COMMIT')) return 'COMMIT';\n if (trimmed.startsWith('ROLLBACK')) return 'ROLLBACK';\n if (trimmed.startsWith('PRAGMA')) return 'PRAGMA';\n if (trimmed.startsWith('CREATE')) return 'CREATE';\n return 'OTHER';\n }\n\n recordQuery(sql: string, paramsJson: string, startTime: number, endTime: number, rowCount: number, error?: string): void {\n if (!this.enabled) return;\n\n const duration = endTime - startTime;\n const queryType = this.extractQueryType(sql);\n\n // Update stats\n let stat = this.stats.get(queryType);\n if (!stat) {\n stat = { count: 0, totalMs: 0, minMs: Infinity, maxMs: 0, errors: 0 };\n this.stats.set(queryType, stat);\n }\n stat.count++;\n stat.totalMs += duration;\n stat.minMs = Math.min(stat.minMs, duration);\n stat.maxMs = Math.max(stat.maxMs, duration);\n if (error) stat.errors++;\n\n // Store trace\n const trace: QueryTrace = { sql, paramsJson, startTime, endTime, duration, rowCount, error };\n this.recentTraces.push(trace);\n if (this.recentTraces.length > this.maxRecentTraces) {\n this.recentTraces.shift();\n }\n\n // Log slow queries or all queries if enabled\n if (duration >= this.slowQueryThreshold) {\n console.warn(`[sql.js PERF] SLOW QUERY (${duration.toFixed(2)}ms): ${queryType}`, {\n sql: sql.substring(0, 200),\n rowCount,\n duration: duration.toFixed(2) + 'ms'\n });\n } else if (this.logQueries) {\n console.log(`[sql.js PERF] ${queryType} (${duration.toFixed(2)}ms, ${rowCount} rows)`);\n }\n }\n\n getStats(): Record<string, SqlStats & { avgMs: number }> {\n const result: Record<string, SqlStats & { avgMs: number }> = {};\n for (const [queryType, stat] of this.stats) {\n result[queryType] = {\n ...stat,\n avgMs: stat.count > 0 ? stat.totalMs / stat.count : 0\n };\n }\n return result;\n }\n\n getSummary(): {\n sessionDuration: number;\n totalQueries: number;\n totalTimeMs: number;\n avgQueryMs: number;\n slowQueries: number;\n errors: number;\n topByCount: Array<{ type: string; count: number; totalMs: number; avgMs: number }>;\n topByTime: Array<{ type: string; count: number; totalMs: number; avgMs: number }>;\n } {\n const stats = this.getStats();\n let totalQueries = 0;\n let totalTimeMs = 0;\n let slowQueries = 0;\n let errors = 0;\n\n const entries: Array<{ type: string; count: number; totalMs: number; avgMs: number }> = [];\n\n for (const [type, stat] of Object.entries(stats)) {\n totalQueries += stat.count;\n totalTimeMs += stat.totalMs;\n slowQueries += this.recentTraces.filter(t =>\n this.extractQueryType(t.sql) === type && t.duration >= this.slowQueryThreshold\n ).length;\n errors += stat.errors;\n entries.push({ type, count: stat.count, totalMs: stat.totalMs, avgMs: stat.avgMs });\n }\n\n return {\n sessionDuration: performance.now() - this.sessionStart,\n totalQueries,\n totalTimeMs,\n avgQueryMs: totalQueries > 0 ? totalTimeMs / totalQueries : 0,\n slowQueries,\n errors,\n topByCount: [...entries].sort((a, b) => b.count - a.count).slice(0, 10),\n topByTime: [...entries].sort((a, b) => b.totalMs - a.totalMs).slice(0, 10)\n };\n }\n\n getRecentTraces(count = 20): QueryTrace[] {\n return this.recentTraces.slice(-count);\n }\n\n printReport(): void {\n const summary = this.getSummary();\n console.log('\\n========== SQL.JS PERFORMANCE REPORT ==========');\n console.log(`Session Duration: ${(summary.sessionDuration / 1000).toFixed(2)}s`);\n console.log(`Total Queries: ${summary.totalQueries}`);\n console.log(`Total SQL Time: ${summary.totalTimeMs.toFixed(2)}ms`);\n console.log(`Avg Query Time: ${summary.avgQueryMs.toFixed(3)}ms`);\n console.log(`Slow Queries (>${this.slowQueryThreshold}ms): ${summary.slowQueries}`);\n console.log(`Errors: ${summary.errors}`);\n\n console.log('\\n--- Top by Count ---');\n for (const entry of summary.topByCount) {\n console.log(` ${entry.type}: ${entry.count} calls, ${entry.totalMs.toFixed(2)}ms total, ${entry.avgMs.toFixed(3)}ms avg`);\n }\n\n console.log('\\n--- Top by Total Time ---');\n for (const entry of summary.topByTime) {\n console.log(` ${entry.type}: ${entry.totalMs.toFixed(2)}ms total, ${entry.count} calls, ${entry.avgMs.toFixed(3)}ms avg`);\n }\n\n console.log('================================================\\n');\n }\n}\n\n// Global tracer instance\nconst perfTracer = new SqlPerformanceTracer();\n\n/**\n * Convert Uint8Array to base64 string efficiently.\n * Uses chunked processing to handle large arrays without stack overflow.\n * @param bytes Uint8Array to convert\n * @returns Base64 encoded string\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // For small arrays, use the simple method\n if (bytes.length < 32768) {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n // For large arrays, process in chunks to avoid stack overflow\n const chunkSize = 32768;\n let binary = '';\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));\n binary += String.fromCharCode.apply(null, Array.from(chunk));\n }\n return btoa(binary);\n}\n\n/**\n * Convert a row object for JSON serialization.\n * Converts Uint8Array (BLOB) to base64-encoded string with \"base64:\" prefix.\n * @param obj Row object from sql.js\n * @returns Object safe for JSON.stringify\n */\nfunction processRowForJson(obj: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n for (const key in obj) {\n const value = obj[key];\n if (value instanceof Uint8Array) {\n // Convert BLOB to base64 with prefix for Go to recognize\n try {\n const base64 = uint8ArrayToBase64(value);\n result[key] = 'base64:' + base64;\n } catch (err) {\n console.error(`[sql.js] Failed to convert BLOB column '${key}' (${value.length} bytes):`, err);\n result[key] = null;\n }\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n// ============================================================================\n// Database Operations\n// ============================================================================\n\n/**\n * Create a new in-memory database\n * @returns Database handle (positive integer) or 0 on error\n */\nexport function createDatabaseOp(): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n const db = new sqlInstance.Database();\n const handle = nextHandle++;\n databases.set(handle, db);\n console.log(`[sql.js] Created database with handle ${handle}`);\n return handle;\n } catch (error) {\n console.error('[sql.js] Failed to create database:', error);\n return 0;\n }\n}\n\n/**\n * Execute SQL statement without returning results\n * @param handle Database handle\n * @param sql SQL statement\n * @returns 1 on success, 0 on error\n */\nexport function execOp(handle: number, sql: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return 0;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n try {\n db.run(sql);\n return 1;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Exec failed:', err);\n return 0;\n } finally {\n perfTracer.recordQuery(sql, '[]', startTime, performance.now(), 0, error);\n }\n}\n\n/**\n * Execute SQL query with parameters and return results as JSON\n * @param handle Database handle\n * @param sql SQL query with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns JSON string of results (array of objects) or empty string on error\n */\nexport function queryOp(handle: number, sql: string, paramsJson: string): string {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return '[]';\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n let rowCount = 0;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n }\n\n // Execute query\n const stmt = db.prepare(sql);\n if (params.length > 0) {\n stmt.bind(params);\n }\n\n // Collect results - convert Uint8Array to base64 for Go\n const results: any[] = [];\n while (stmt.step()) {\n results.push(processRowForJson(stmt.getAsObject()));\n }\n stmt.free();\n\n rowCount = results.length;\n return JSON.stringify(results);\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Query failed:', sql, err);\n return '[]';\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), rowCount, error);\n }\n}\n\n/**\n * Convert base64 string to Uint8Array\n * @param base64 Base64 encoded string\n * @returns Uint8Array of decoded bytes\n */\nfunction base64ToUint8Array(base64: string): Uint8Array {\n // Use Buffer in Node.js for correct binary handling\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(base64, 'base64'));\n }\n // Browser fallback using atob\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Process params array, converting \"base64:\" prefixed strings to Uint8Array for BLOB storage\n * @param params Array of SQL parameters\n * @returns Processed params with binary data converted to Uint8Array\n */\nfunction processParamsForBlob(params: any[]): any[] {\n return params.map(param => {\n if (typeof param === 'string' && param.startsWith('base64:')) {\n // Convert base64-prefixed string to Uint8Array for BLOB storage\n return base64ToUint8Array(param.substring(7));\n }\n return param;\n });\n}\n\n/**\n * Execute INSERT statement and return the last inserted row ID\n * @param handle Database handle\n * @param sql INSERT statement with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns Last insert row ID or 0 on error\n */\nexport function insertOp(handle: number, sql: string, paramsJson: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return 0;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n // Convert \"base64:\" prefixed strings to Uint8Array for BLOB storage\n params = processParamsForBlob(params);\n }\n\n // Execute insert\n if (params.length > 0) {\n db.run(sql, params);\n } else {\n db.run(sql);\n }\n\n // Get last insert row ID\n const result = db.exec('SELECT last_insert_rowid() as id');\n if (result.length > 0 && result[0].values.length > 0) {\n return result[0].values[0][0] as number;\n }\n return 0;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Insert failed:', sql, err);\n return 0;\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), 1, error);\n }\n}\n\n/**\n * Execute UPDATE/DELETE statement and return rows affected\n * @param handle Database handle\n * @param sql UPDATE or DELETE statement with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns Number of rows affected or -1 on error\n */\nexport function execParamsOp(handle: number, sql: string, paramsJson: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return -1;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n let rowsAffected = 0;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n // Convert \"base64:\" prefixed strings to Uint8Array for BLOB storage\n params = processParamsForBlob(params);\n }\n\n // Execute statement\n if (params.length > 0) {\n db.run(sql, params);\n } else {\n db.run(sql);\n }\n\n // Get rows affected\n const result = db.exec('SELECT changes() as count');\n if (result.length > 0 && result[0].values.length > 0) {\n rowsAffected = result[0].values[0][0] as number;\n return rowsAffected;\n }\n return 0;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] ExecParams failed:', sql, err);\n return -1;\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), rowsAffected, error);\n }\n}\n\n/**\n * Export database to binary format\n * @param handle Database handle\n * @returns Base64-encoded database bytes or empty string on error\n */\nexport function exportOp(handle: number): string {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return '';\n }\n\n try {\n const data = db.export();\n // Use chunked base64 conversion for potentially large databases\n return uint8ArrayToBase64(data);\n } catch (error) {\n console.error('[sql.js] Export failed:', error);\n return '';\n }\n}\n\n/**\n * Import database from binary format\n * @param base64Data Base64-encoded database bytes\n * @returns Database handle or 0 on error\n */\nexport function importOp(base64Data: string): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n // Decode base64 to Uint8Array\n const binary = atob(base64Data);\n const data = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n data[i] = binary.charCodeAt(i);\n }\n\n const db = new sqlInstance.Database(data);\n const handle = nextHandle++;\n databases.set(handle, db);\n console.log(`[sql.js] Imported database with handle ${handle}`);\n return handle;\n } catch (error) {\n console.error('[sql.js] Import failed:', error);\n return 0;\n }\n}\n\n/**\n * Load database directly from bytes\n * @param bytes Raw database bytes\n * @returns Database handle or 0 on error\n */\nexport function loadDirectOp(bytes: Uint8Array): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n const db = new sqlInstance.Database(bytes);\n const handle = nextHandle++;\n databases.set(handle, db);\n return handle;\n } catch (error) {\n console.error('[sql.js] Failed to load database directly:', error);\n return 0;\n }\n}\n\n/**\n * Close a database\n * @param handle Database handle\n */\nexport function closeOp(handle: number): void {\n const db = databases.get(handle);\n if (db) {\n try {\n db.close();\n } catch (error) {\n console.error('[sql.js] Close failed:', error);\n }\n databases.delete(handle);\n console.log(`[sql.js] Closed database with handle ${handle}`);\n }\n}\n\n/**\n * Get last error message (for debugging)\n * @param _handle Database handle\n * @returns Error message or empty string\n */\nexport function getErrorOp(_handle: number): string {\n // sql.js throws exceptions rather than storing error messages\n // This is a placeholder for API compatibility\n return '';\n}\n\n/**\n * Cleanup all databases and reset state\n */\nexport function cleanupOp(): void {\n for (const [_handle, db] of databases) {\n try {\n db.close();\n } catch (_e) {\n // Ignore close errors during cleanup\n }\n }\n databases.clear();\n nextHandle = 1;\n console.log('[sql.js] Cleaned up all databases');\n}\n\n// ============================================================================\n// Bridge Exposure\n// ============================================================================\n\n/**\n * Set the SQL instance for database operations\n * Must be called before any database operations\n */\nexport function setSqlInstance(SQL: any): void {\n sqlInstance = SQL;\n}\n\n/**\n * Expose sql.js bridge functions to globalThis for Go WASM access\n */\nexport function exposeBridgeFunctions(): void {\n const g = globalThis as any;\n\n g.sqljsCreateDatabase = createDatabaseOp;\n g.sqljsExec = execOp;\n g.sqljsQuery = queryOp;\n g.sqljsInsert = insertOp;\n g.sqljsExecParams = execParamsOp;\n g.sqljsExport = exportOp;\n g.sqljsImport = importOp;\n g.sqljsClose = closeOp;\n g.sqljsGetError = getErrorOp;\n g.sqljsLoadDirect = loadDirectOp;\n\n // Also expose database map for debugging\n g.sqljsDatabases = databases;\n\n // Expose performance tracing API for debugging\n g.sqljsPerf = {\n /**\n * Enable SQL performance tracing\n * @param options.logQueries - Log all queries (default: false, only slow queries are logged)\n * @param options.slowQueryThreshold - Threshold in ms for slow query warnings (default: 10)\n * @example sqljsPerf.enable({ logQueries: true, slowQueryThreshold: 5 })\n */\n enable: (options?: { logQueries?: boolean; slowQueryThreshold?: number }) => perfTracer.enable(options),\n\n /** Disable SQL performance tracing */\n disable: () => perfTracer.disable(),\n\n /** Check if tracing is enabled */\n isEnabled: () => perfTracer.isEnabled(),\n\n /** Reset all statistics and traces */\n reset: () => perfTracer.reset(),\n\n /** Get detailed statistics by query type */\n getStats: () => perfTracer.getStats(),\n\n /** Get summary with top queries by count and time */\n getSummary: () => perfTracer.getSummary(),\n\n /** Get recent query traces (default: last 20) */\n getRecentTraces: (count?: number) => perfTracer.getRecentTraces(count),\n\n /** Print formatted performance report to console */\n printReport: () => perfTracer.printReport(),\n };\n\n console.log('[sql.js] Bridge functions exposed to globalThis');\n console.log('[sql.js] Performance tracing available via sqljsPerf.enable()');\n}\n\n/**\n * Get a database by handle (for debugging from console)\n */\nexport function getDatabase(handle: number): any {\n return databases.get(handle);\n}\n\n// ============================================================================\n// Performance Tracing Exports\n// ============================================================================\n\n/**\n * Enable SQL performance tracing\n * @param options.logQueries - Log all queries (default: false, only slow queries are logged)\n * @param options.slowQueryThreshold - Threshold in ms for slow query warnings (default: 10)\n */\nexport function enableSqlPerformanceTracing(options?: { logQueries?: boolean; slowQueryThreshold?: number }): void {\n perfTracer.enable(options);\n}\n\n/** Disable SQL performance tracing */\nexport function disableSqlPerformanceTracing(): void {\n perfTracer.disable();\n}\n\n/** Get SQL performance statistics */\nexport function getSqlPerformanceStats() {\n return perfTracer.getStats();\n}\n\n/** Get SQL performance summary */\nexport function getSqlPerformanceSummary() {\n return perfTracer.getSummary();\n}\n\n/** Print SQL performance report to console */\nexport function printSqlPerformanceReport(): void {\n perfTracer.printReport();\n}\n\n/** Get recent SQL query traces */\nexport function getRecentSqlTraces(count = 20) {\n return perfTracer.getRecentTraces(count);\n}\n\n/** Reset SQL performance statistics */\nexport function resetSqlPerformanceStats(): void {\n perfTracer.reset();\n}\n", "/**\n * Kodexa SharedWorker Entry Point\n *\n * This SharedWorker owns the Go WASM instance and exposes an RPC-style API\n * via MessagePort. Multiple tabs/windows can connect and share the same\n * WASM instance and documents, with events broadcast to all interested ports.\n *\n * Key differences from dedicated worker:\n * - Uses onconnect to handle multiple port connections\n * - Tracks document subscriptions per port for event broadcasting\n * - Reference counts documents to know when to clean up\n *\n * Initialization order (critical):\n * 1. sql.js WASM loaded and bridge exposed to globalThis\n * 2. wasm_exec.js loaded (defines globalThis.Go)\n * 3. kodexa.wasm instantiated and Go runtime started\n * 4. Worker signals 'ready' to each connected port\n */\n\n/// <reference lib=\"webworker\" />\n\nimport type {\n WorkerConfig,\n WorkerErrorMessage,\n WorkerWasmEventMessage,\n SharedWorkerRequest,\n SharedWorkerResponse,\n SharedWorkerReadyMessage,\n SharedWorkerInboundMessage,\n} from './types';\nimport { setSqlInstance, exposeBridgeFunctions, loadDirectOp } from '../wasm/sqljs-core';\n\ndeclare const self: SharedWorkerGlobalScope;\n\n// ============================================================================\n// Port Management\n// ============================================================================\n\n/** Connected ports by ID */\nconst ports = new Map<string, MessagePort>();\n\n/** Counter for generating unique port IDs */\nlet nextPortId = 1;\n\n/** Generate a unique port ID */\nfunction generatePortId(): string {\n return `port_${nextPortId++}_${Date.now()}`;\n}\n\n// ============================================================================\n// Document State Management\n// ============================================================================\n\n/** Track which ports are subscribed to which documents for event broadcasting */\nconst documentSubscriptions = new Map<number, Set<string>>(); // docRef -> Set<portId>\n\n/** Track which ports are using which documents (for cleanup) */\nconst documentUsers = new Map<number, Set<string>>(); // docRef -> Set<portId>\n\n// ============================================================================\n// Shared Document Registry (by documentFamilyId)\n// Enables multiple tabs to share the same WASM document instance\n// ============================================================================\n\n/** Map documentFamilyId -> docRef for sharing documents across tabs */\nconst sharedDocuments = new Map<string, number>();\n\n/** Track which ports are using each shared document (by documentFamilyId) */\nconst sharedDocumentUsers = new Map<string, Set<string>>(); // documentFamilyId -> Set<portId>\n\n/**\n * Subscribe a port to document events.\n */\nfunction subscribeToDocument(docRef: number, portId: string): void {\n if (!documentSubscriptions.has(docRef)) {\n documentSubscriptions.set(docRef, new Set());\n }\n documentSubscriptions.get(docRef)!.add(portId);\n console.log(`[shared-worker] Port ${portId} subscribed to document ${docRef}`);\n}\n\n/**\n * Unsubscribe a port from document events.\n */\nfunction unsubscribeFromDocument(docRef: number, portId: string): void {\n const subscribers = documentSubscriptions.get(docRef);\n if (subscribers) {\n subscribers.delete(portId);\n if (subscribers.size === 0) {\n documentSubscriptions.delete(docRef);\n }\n console.log(`[shared-worker] Port ${portId} unsubscribed from document ${docRef}`);\n }\n}\n\n/**\n * Register a port as using a document (for reference counting).\n */\nfunction registerDocumentUser(docRef: number, portId: string): void {\n if (!documentUsers.has(docRef)) {\n documentUsers.set(docRef, new Set());\n }\n documentUsers.get(docRef)!.add(portId);\n}\n\n/**\n * Unregister a port from a document. Returns true if document should be freed.\n */\nfunction unregisterDocumentUser(docRef: number, portId: string): boolean {\n const users = documentUsers.get(docRef);\n if (users) {\n users.delete(portId);\n if (users.size === 0) {\n documentUsers.delete(docRef);\n return true; // No more users, safe to free\n }\n }\n return false;\n}\n\n// ============================================================================\n// Shared Document Functions (by documentFamilyId)\n// ============================================================================\n\n/**\n * Load or join a shared document by documentFamilyId.\n * If another tab has already loaded this document, returns the existing docRef.\n * If not loaded, loads from provided kddbBytes and registers as shared.\n *\n * @param documentFamilyId - Unique identifier for the document family\n * @param portId - Port ID of the requesting tab\n * @param kddbBytes - KDDB bytes (required if document not already loaded)\n * @returns Object with docRef, shared status, and user count\n */\nfunction loadSharedDocument(\n documentFamilyId: string,\n portId: string,\n kddbBytes?: Uint8Array\n): { docRef: number; shared: boolean; userCount: number } {\n // Check if already loaded by another tab\n if (sharedDocuments.has(documentFamilyId)) {\n const existingDocRef = sharedDocuments.get(documentFamilyId)!;\n\n // Register this port as a user\n let users = sharedDocumentUsers.get(documentFamilyId);\n if (!users) {\n users = new Set();\n sharedDocumentUsers.set(documentFamilyId, users);\n }\n users.add(portId);\n\n // Also register in the regular document users tracking\n registerDocumentUser(existingDocRef, portId);\n\n // Auto-subscribe to document events\n subscribeToDocument(existingDocRef, portId);\n\n console.log(`[shared-worker] Port ${portId} joined shared document ${documentFamilyId} (docRef: ${existingDocRef}), ${users.size} users`);\n\n return {\n docRef: existingDocRef,\n shared: true,\n userCount: users.size,\n };\n }\n\n // Not loaded - need kddbBytes\n if (!kddbBytes) {\n throw new Error(`Document ${documentFamilyId} not loaded and no bytes provided`);\n }\n\n // Load new document using loadDocument\n const loadDocument = (self as any).loadDocument;\n if (typeof loadDocument !== 'function') {\n throw new Error('loadDocument function not available');\n }\n\n const docRef = loadDocument(kddbBytes);\n if (docRef === 0) {\n throw new Error('Failed to load document from KDDB bytes');\n }\n\n // Register as shared document\n sharedDocuments.set(documentFamilyId, docRef);\n const users = new Set<string>([portId]);\n sharedDocumentUsers.set(documentFamilyId, users);\n\n // Register in regular tracking\n registerDocumentUser(docRef, portId);\n\n // Auto-subscribe to events\n subscribeToDocument(docRef, portId);\n\n console.log(`[shared-worker] Port ${portId} loaded shared document ${documentFamilyId} (docRef: ${docRef})`);\n\n return {\n docRef,\n shared: false,\n userCount: 1,\n };\n}\n\n/**\n * Release this tab's reference to a shared document.\n * Document is freed when all tabs release it.\n *\n * @param documentFamilyId - Document family ID to release\n * @param portId - Port ID releasing the document\n * @returns Object with freed status and remaining user count\n */\nfunction releaseSharedDocument(\n documentFamilyId: string,\n portId: string\n): { freed: boolean; remainingUsers?: number; notFound?: boolean } {\n const docRef = sharedDocuments.get(documentFamilyId);\n\n if (docRef === undefined) {\n return { freed: false, notFound: true };\n }\n\n // Remove this port from shared document users\n const users = sharedDocumentUsers.get(documentFamilyId);\n if (users) {\n users.delete(portId);\n\n // Unsubscribe from events\n unsubscribeFromDocument(docRef, portId);\n\n // Unregister from regular tracking\n unregisterDocumentUser(docRef, portId);\n\n // If no users left, free the document\n if (users.size === 0) {\n console.log(`[shared-worker] Freeing shared document ${documentFamilyId} (docRef: ${docRef}) - no more users`);\n\n // Free the document\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n\n // Clean up registry\n sharedDocuments.delete(documentFamilyId);\n sharedDocumentUsers.delete(documentFamilyId);\n documentSubscriptions.delete(docRef);\n\n return { freed: true };\n }\n\n console.log(`[shared-worker] Port ${portId} released shared document ${documentFamilyId}, ${users.size} users remaining`);\n return { freed: false, remainingUsers: users.size };\n }\n\n return { freed: false, notFound: true };\n}\n\n/**\n * Check if a document is already loaded as a shared document.\n *\n * @param documentFamilyId - Document family ID to check\n * @returns true if document is loaded, false otherwise\n */\nfunction isDocumentShared(documentFamilyId: string): boolean {\n return sharedDocuments.has(documentFamilyId);\n}\n\n/**\n * Get the docRef for a shared document by documentFamilyId.\n *\n * @param documentFamilyId - Document family ID to look up\n * @returns docRef if found, undefined otherwise\n */\nfunction getSharedDocumentRef(documentFamilyId: string): number | undefined {\n return sharedDocuments.get(documentFamilyId);\n}\n\n/**\n * Invalidate a shared document and notify other tabs.\n * Called when one tab force-reloads a document.\n *\n * @param documentFamilyId - Document family ID being invalidated\n * @param portId - Port ID of the tab initiating the invalidation\n * @param reason - Reason for invalidation (e.g., 'reload', 'server-update')\n */\nfunction invalidateSharedDocument(\n documentFamilyId: string,\n portId: string,\n reason: string\n): void {\n const docRef = sharedDocuments.get(documentFamilyId);\n\n if (docRef === undefined) {\n return;\n }\n\n const users = sharedDocumentUsers.get(documentFamilyId);\n if (!users) {\n return;\n }\n\n // Notify all OTHER tabs using this document\n for (const userPortId of users) {\n if (userPortId !== portId) {\n const port = ports.get(userPortId);\n if (port) {\n try {\n port.postMessage({\n type: 'documentInvalidated',\n documentFamilyId,\n reason,\n initiatorPortId: portId,\n });\n console.log(`[shared-worker] Notified port ${userPortId} of document invalidation: ${documentFamilyId}`);\n } catch (error) {\n console.error(`[shared-worker] Error notifying port ${userPortId}:`, error);\n }\n }\n }\n }\n}\n\n/**\n * Cleanup all resources associated with a port.\n */\nfunction cleanupPort(portId: string): void {\n console.log(`[shared-worker] Cleaning up port ${portId}`);\n\n // Remove from all document subscriptions\n for (const [docRef, subscribers] of documentSubscriptions) {\n subscribers.delete(portId);\n if (subscribers.size === 0) {\n documentSubscriptions.delete(docRef);\n }\n }\n\n // Release all shared documents this port was using\n for (const [documentFamilyId, users] of sharedDocumentUsers) {\n if (users.has(portId)) {\n users.delete(portId);\n\n // If last user, free document and clean up\n if (users.size === 0) {\n const docRef = sharedDocuments.get(documentFamilyId);\n if (docRef !== undefined) {\n console.log(`[shared-worker] Freeing shared document ${documentFamilyId} (docRef: ${docRef}) - port ${portId} was last user`);\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n sharedDocuments.delete(documentFamilyId);\n documentUsers.delete(docRef);\n }\n sharedDocumentUsers.delete(documentFamilyId);\n }\n }\n }\n\n // Unregister from all non-shared document users\n for (const [docRef, users] of documentUsers) {\n users.delete(portId);\n if (users.size === 0) {\n // Check if this is a shared document - if so, it's already handled above\n let isShared = false;\n for (const [, sharedDocRef] of sharedDocuments) {\n if (sharedDocRef === docRef) {\n isShared = true;\n break;\n }\n }\n\n if (!isShared) {\n // No ports using this non-shared document, free it\n console.log(`[shared-worker] Freeing non-shared document ${docRef} - no more users`);\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n }\n documentUsers.delete(docRef);\n }\n }\n\n // Remove port\n ports.delete(portId);\n}\n\n// ============================================================================\n// Event Broadcasting\n// ============================================================================\n\n/**\n * Broadcast an event to all ports subscribed to a document.\n */\nfunction broadcastToSubscribers(docRef: number, eventType: string, detail: unknown): void {\n const subscribers = documentSubscriptions.get(docRef);\n console.log(`[shared-worker] broadcastToSubscribers called docRef=${docRef} eventType=${eventType} subscriberCount=${subscribers?.size ?? 0}`);\n if (!subscribers || subscribers.size === 0) {\n console.log(`[shared-worker] No subscribers for document ${docRef}, event not broadcast`);\n return;\n }\n\n const message: WorkerWasmEventMessage = {\n type: 'wasmEvent',\n eventType,\n detail,\n documentRef: docRef,\n };\n\n for (const portId of subscribers) {\n const port = ports.get(portId);\n if (port) {\n try {\n console.log(`[shared-worker] Posting wasmEvent to port ${portId}`);\n port.postMessage(message);\n console.log(`[shared-worker] Posted wasmEvent to port ${portId} successfully`);\n } catch (error) {\n console.error(`[shared-worker] Error posting to port ${portId}:`, error);\n }\n } else {\n console.warn(`[shared-worker] Port ${portId} not found in ports map, cannot send event`);\n }\n }\n}\n\n/**\n * Broadcast an event to ALL connected ports.\n */\nfunction broadcastToAll(message: unknown): void {\n for (const [portId, port] of ports) {\n try {\n port.postMessage(message);\n } catch (error) {\n console.error(`[shared-worker] Error posting to port ${portId}:`, error);\n }\n }\n}\n\n// ============================================================================\n// Worker State\n// ============================================================================\n\nlet initialized = false;\nlet initPromise: Promise<void> | null = null;\nlet config: WorkerConfig = {};\n\n// ============================================================================\n// Event Forwarding from WASM\n// ============================================================================\n\n/**\n * Set up event forwarding from WASM to connected ports.\n *\n * SIMPLIFIED ARCHITECTURE:\n * Go WASM calls document.dispatchEvent(CustomEvent) with JSON string detail.\n * We parse the JSON once here and broadcast directly to subscribers.\n * No intermediate self.dispatchEvent \u2192 addEventListener dance needed.\n */\nfunction setupEventForwarding(): void {\n // Create a document shim for Go WASM to dispatch events\n const documentShim = {\n addEventListener: (type: string, handler: EventListener) => {\n // Go WASM may register listeners, but we handle events directly in dispatchEvent\n console.log(`[shared-worker] Event listener registered for: ${type} (handled in dispatchEvent)`);\n },\n removeEventListener: (type: string, handler: EventListener) => {\n // No-op - we don't use addEventListener\n },\n dispatchEvent: (event: Event) => {\n // Handle CustomEvents from Go WASM directly - no intermediate dispatch needed\n if (!(event instanceof CustomEvent)) {\n return true;\n }\n\n const eventType = event.type;\n const rawDetail = event.detail;\n\n // Parse JSON detail once (Go sends it as a JSON string)\n let parsedDetail: any;\n try {\n parsedDetail = typeof rawDetail === 'string' ? JSON.parse(rawDetail) : rawDetail;\n } catch (e) {\n console.warn(`[shared-worker] Failed to parse ${eventType} detail:`, e);\n parsedDetail = rawDetail;\n }\n\n const docRef = parsedDetail?.documentRef;\n console.log(`[shared-worker] dispatchEvent: ${eventType}`, { docRef, eventType: parsedDetail?.eventType });\n\n if (docRef !== undefined) {\n // Document-specific event - broadcast to subscribers only\n // Pass the PARSED detail so UI doesn't need to parse again\n broadcastToSubscribers(docRef, eventType, parsedDetail);\n } else {\n // Global event - broadcast to all ports\n broadcastToAll({\n type: 'wasmEvent',\n eventType: eventType,\n detail: parsedDetail,\n } as WorkerWasmEventMessage);\n }\n\n return true;\n },\n createElement: () => null,\n body: null,\n documentElement: null,\n };\n\n (self as any).document = documentShim;\n\n console.log('[shared-worker] Event forwarding configured (simplified architecture)');\n}\n\n// ============================================================================\n// WASM Loading (same as dedicated worker)\n// ============================================================================\n\nasync function initializeSqlJs(): Promise<void> {\n const sqlJsUrl = 'https://sql.js.org/dist/sql-wasm.js';\n const sqlWasmUrl = 'https://sql.js.org/dist/sql-wasm.wasm';\n\n try {\n const response = await fetch(sqlJsUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch sql-wasm.js: ${response.statusText}`);\n }\n const code = await response.text();\n\n const wrappedCode = `\n (function(module, exports) {\n ${code}\n return module.exports;\n })\n `;\n\n // eslint-disable-next-line no-eval\n const moduleFactory = eval(wrappedCode);\n const mockModule = { exports: {} as any };\n const initSqlJs = moduleFactory(mockModule, mockModule.exports);\n\n if (typeof initSqlJs !== 'function') {\n throw new Error('initSqlJs not found after loading sql-wasm.js');\n }\n\n const sqlConfig = {\n locateFile: () => sqlWasmUrl,\n };\n\n const SQL = await initSqlJs(sqlConfig);\n setSqlInstance(SQL);\n exposeBridgeFunctions();\n\n // Expose loadDocument function\n (self as any).loadDocument = (bytes: Uint8Array): number => {\n const handle = loadDirectOp(bytes);\n if (handle === 0) {\n console.error('[shared-worker] Failed to load database');\n return 0;\n }\n return (self as any).createDocumentFromHandle(handle);\n };\n\n console.log('[shared-worker] sql.js initialized from official CDN');\n } catch (error) {\n console.error('[shared-worker] Failed to initialize sql.js:', error);\n throw new Error(`Failed to initialize sql.js: ${error}`);\n }\n}\n\nasync function loadWasmExec(): Promise<void> {\n if ((self as any).Go) {\n return;\n }\n\n const baseUrl = config.wasmBaseUrl || self.location.origin;\n const wasmExecUrl = `${baseUrl}/wasm_exec.js`;\n\n try {\n const response = await fetch(wasmExecUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch wasm_exec.js: ${response.statusText}`);\n }\n const code = await response.text();\n // eslint-disable-next-line no-eval\n eval(code);\n console.log('[shared-worker] wasm_exec.js loaded');\n } catch (error) {\n throw new Error(`Failed to load wasm_exec.js: ${error}`);\n }\n}\n\nasync function loadGoWasm(): Promise<void> {\n const baseUrl = config.wasmBaseUrl || self.location.origin;\n // Add cache-busting version if provided\n const versionParam = config.wasmVersion ? `?v=${config.wasmVersion}` : '';\n const wasmUrl = `${baseUrl}/kodexa.wasm${versionParam}`;\n\n const response = await fetch(wasmUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch kodexa.wasm: ${response.statusText}`);\n }\n const wasmBytes = await response.arrayBuffer();\n\n const go = new (self as any).Go();\n const result = await WebAssembly.instantiate(wasmBytes, go.importObject);\n go.run(result.instance);\n\n const logLevel = config.logLevel || 'warn';\n if ((self as any).kodexa_setLogLevel) {\n (self as any).kodexa_setLogLevel(logLevel);\n }\n\n console.log('[shared-worker] Go WASM loaded');\n}\n\nasync function initialize(workerConfig?: WorkerConfig): Promise<void> {\n if (initialized) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n config = workerConfig || {};\n\n initPromise = (async () => {\n try {\n setupEventForwarding();\n await initializeSqlJs();\n await loadWasmExec();\n await loadGoWasm();\n initialized = true;\n console.log('[shared-worker] Kodexa WASM fully initialized');\n } catch (error) {\n console.error('[shared-worker] Initialization failed:', error);\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n// ============================================================================\n// Message Handling\n// ============================================================================\n\n/**\n * Handle RPC call from a port.\n */\nfunction handleCall(request: SharedWorkerRequest): SharedWorkerResponse {\n const { id, method, args, portId } = request;\n\n try {\n const fn = (self as any)[method];\n if (typeof fn !== 'function') {\n return {\n id,\n portId,\n success: false,\n error: `Function '${method}' not found on globalThis`,\n };\n }\n\n const result = fn(...(args || []));\n\n // Track document usage when creating/loading documents\n if (method === 'createDocument' || method === 'createDocumentFromText' ||\n method === 'createDocumentFromJson' || method === 'createDocumentFromKddbBytes' ||\n method === 'loadDocument') {\n if (typeof result === 'number' && result > 0) {\n registerDocumentUser(result, portId);\n }\n }\n\n // Track document disposal\n if (method === 'freeDocument' && args && args.length > 0) {\n const docRef = args[0] as number;\n const shouldFree = unregisterDocumentUser(docRef, portId);\n if (!shouldFree) {\n // Other ports still using this document, don't actually free it\n return { id, portId, success: true, result: undefined };\n }\n }\n\n return { id, portId, success: true, result };\n } catch (error) {\n return {\n id,\n portId,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Handle messages from a connected port.\n */\nfunction handlePortMessage(portId: string, port: MessagePort, event: MessageEvent<SharedWorkerInboundMessage>): void {\n const data = event.data;\n\n // Handle init message\n if ('type' in data && data.type === 'init') {\n (async () => {\n try {\n await initialize(data.config);\n const readyMessage: SharedWorkerReadyMessage = { type: 'ready', portId };\n port.postMessage(readyMessage);\n } catch (error) {\n const errorMessage: WorkerErrorMessage = {\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n port.postMessage(errorMessage);\n }\n })();\n return;\n }\n\n // Handle subscription messages\n if ('type' in data && data.type === 'subscribe') {\n subscribeToDocument(data.docRef, portId);\n return;\n }\n\n if ('type' in data && data.type === 'unsubscribe') {\n unsubscribeFromDocument(data.docRef, portId);\n return;\n }\n\n // Handle shared document messages\n if ('type' in data && data.type === 'loadSharedDocument') {\n if (!initialized) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: 'Worker not initialized',\n requestType: 'loadSharedDocument',\n });\n return;\n }\n\n try {\n const { documentFamilyId, kddbBytes } = data as any;\n const result = loadSharedDocument(documentFamilyId, portId, kddbBytes);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'loadSharedDocument',\n ...result,\n });\n } catch (error) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: error instanceof Error ? error.message : String(error),\n requestType: 'loadSharedDocument',\n });\n }\n return;\n }\n\n if ('type' in data && data.type === 'releaseSharedDocument') {\n try {\n const { documentFamilyId } = data as any;\n const result = releaseSharedDocument(documentFamilyId, portId);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'releaseSharedDocument',\n ...result,\n });\n } catch (error) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: error instanceof Error ? error.message : String(error),\n requestType: 'releaseSharedDocument',\n });\n }\n return;\n }\n\n if ('type' in data && data.type === 'isDocumentShared') {\n const { documentFamilyId } = data as any;\n const shared = isDocumentShared(documentFamilyId);\n const docRef = getSharedDocumentRef(documentFamilyId);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'isDocumentShared',\n shared,\n docRef,\n });\n return;\n }\n\n if ('type' in data && data.type === 'invalidateSharedDocument') {\n const { documentFamilyId, reason } = data as any;\n invalidateSharedDocument(documentFamilyId, portId, reason || 'reload');\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'invalidateSharedDocument',\n });\n return;\n }\n\n // Handle RPC call\n if ('type' in data && data.type === 'call') {\n if (!initialized) {\n const response: SharedWorkerResponse = {\n id: (data as SharedWorkerRequest).id,\n portId,\n success: false,\n error: 'Worker not initialized. Send init message first.',\n };\n port.postMessage(response);\n return;\n }\n\n // Add portId to the request\n const request = { ...data, portId } as SharedWorkerRequest;\n const response = handleCall(request);\n port.postMessage(response);\n }\n}\n\n// ============================================================================\n// SharedWorker Connection Handler\n// ============================================================================\n\nself.onconnect = (event: MessageEvent) => {\n const port = event.ports[0];\n const portId = generatePortId();\n\n console.log(`[shared-worker] New port connected: ${portId}`);\n ports.set(portId, port);\n\n // Set up message handler for this port\n port.onmessage = (e) => handlePortMessage(portId, port, e);\n\n // Handle port closure (tab closed)\n // Note: Not all browsers reliably fire this event\n port.onmessageerror = () => {\n console.log(`[shared-worker] Port ${portId} message error, cleaning up`);\n cleanupPort(portId);\n };\n\n // Start the port\n port.start();\n\n // If already initialized, send ready immediately\n if (initialized) {\n const readyMessage: SharedWorkerReadyMessage = { type: 'ready', portId };\n port.postMessage(readyMessage);\n }\n\n // Send connected message so port knows its ID\n port.postMessage({ type: 'connected', portId });\n};\n\n// Log that shared worker is ready for connections\nconsole.log('[shared-worker] Kodexa SharedWorker ready for connections');\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Core sql.js bridge operations - shared between environments\n *\n * This module contains all the database operations that are common between\n * the npm package (sqljs-bridge.ts) and browser CDN (browser-bridge.ts) implementations.\n *\n * The SQL instance is passed in from the wrapper modules, allowing them to\n * load sql.js in different ways (npm import vs CDN global).\n */\n\n// Database handle management\nconst databases = new Map<number, any>();\nlet nextHandle = 1;\n\n// Store SQL instance reference for operations that need it\nlet sqlInstance: any = null;\n\n// ============================================================================\n// Performance Tracing\n// ============================================================================\n\ninterface SqlStats {\n count: number;\n totalMs: number;\n minMs: number;\n maxMs: number;\n errors: number;\n}\n\ninterface QueryTrace {\n sql: string;\n paramsJson: string;\n startTime: number;\n endTime: number;\n duration: number;\n rowCount: number;\n error?: string;\n}\n\nclass SqlPerformanceTracer {\n private enabled = false;\n private stats: Map<string, SqlStats> = new Map();\n private recentTraces: QueryTrace[] = [];\n private maxRecentTraces = 100;\n private sessionStart = 0;\n private logQueries = false;\n private slowQueryThreshold = 10; // ms\n\n enable(options?: { logQueries?: boolean; slowQueryThreshold?: number }): void {\n this.enabled = true;\n this.sessionStart = performance.now();\n this.logQueries = options?.logQueries ?? false;\n this.slowQueryThreshold = options?.slowQueryThreshold ?? 10;\n this.reset();\n console.log('[sql.js PERF] Performance tracing ENABLED', {\n logQueries: this.logQueries,\n slowQueryThreshold: this.slowQueryThreshold + 'ms'\n });\n }\n\n disable(): void {\n this.enabled = false;\n console.log('[sql.js PERF] Performance tracing DISABLED');\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n reset(): void {\n this.stats.clear();\n this.recentTraces = [];\n this.sessionStart = performance.now();\n }\n\n private extractQueryType(sql: string): string {\n const trimmed = sql.trim().toUpperCase();\n if (trimmed.startsWith('SELECT')) {\n // Extract table name for SELECT queries\n const match = sql.match(/FROM\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `SELECT:${match[1]}` : 'SELECT';\n }\n if (trimmed.startsWith('INSERT')) {\n const match = sql.match(/INTO\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `INSERT:${match[1]}` : 'INSERT';\n }\n if (trimmed.startsWith('UPDATE')) {\n const match = sql.match(/UPDATE\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `UPDATE:${match[1]}` : 'UPDATE';\n }\n if (trimmed.startsWith('DELETE')) {\n const match = sql.match(/FROM\\s+[\"']?(\\w+)[\"']?/i);\n return match ? `DELETE:${match[1]}` : 'DELETE';\n }\n if (trimmed.startsWith('BEGIN')) return 'BEGIN';\n if (trimmed.startsWith('COMMIT')) return 'COMMIT';\n if (trimmed.startsWith('ROLLBACK')) return 'ROLLBACK';\n if (trimmed.startsWith('PRAGMA')) return 'PRAGMA';\n if (trimmed.startsWith('CREATE')) return 'CREATE';\n return 'OTHER';\n }\n\n recordQuery(sql: string, paramsJson: string, startTime: number, endTime: number, rowCount: number, error?: string): void {\n if (!this.enabled) return;\n\n const duration = endTime - startTime;\n const queryType = this.extractQueryType(sql);\n\n // Update stats\n let stat = this.stats.get(queryType);\n if (!stat) {\n stat = { count: 0, totalMs: 0, minMs: Infinity, maxMs: 0, errors: 0 };\n this.stats.set(queryType, stat);\n }\n stat.count++;\n stat.totalMs += duration;\n stat.minMs = Math.min(stat.minMs, duration);\n stat.maxMs = Math.max(stat.maxMs, duration);\n if (error) stat.errors++;\n\n // Store trace\n const trace: QueryTrace = { sql, paramsJson, startTime, endTime, duration, rowCount, error };\n this.recentTraces.push(trace);\n if (this.recentTraces.length > this.maxRecentTraces) {\n this.recentTraces.shift();\n }\n\n // Log slow queries or all queries if enabled\n if (duration >= this.slowQueryThreshold) {\n console.warn(`[sql.js PERF] SLOW QUERY (${duration.toFixed(2)}ms): ${queryType}`, {\n sql: sql.substring(0, 200),\n rowCount,\n duration: duration.toFixed(2) + 'ms'\n });\n } else if (this.logQueries) {\n console.log(`[sql.js PERF] ${queryType} (${duration.toFixed(2)}ms, ${rowCount} rows)`);\n }\n }\n\n getStats(): Record<string, SqlStats & { avgMs: number }> {\n const result: Record<string, SqlStats & { avgMs: number }> = {};\n for (const [queryType, stat] of this.stats) {\n result[queryType] = {\n ...stat,\n avgMs: stat.count > 0 ? stat.totalMs / stat.count : 0\n };\n }\n return result;\n }\n\n getSummary(): {\n sessionDuration: number;\n totalQueries: number;\n totalTimeMs: number;\n avgQueryMs: number;\n slowQueries: number;\n errors: number;\n topByCount: Array<{ type: string; count: number; totalMs: number; avgMs: number }>;\n topByTime: Array<{ type: string; count: number; totalMs: number; avgMs: number }>;\n } {\n const stats = this.getStats();\n let totalQueries = 0;\n let totalTimeMs = 0;\n let slowQueries = 0;\n let errors = 0;\n\n const entries: Array<{ type: string; count: number; totalMs: number; avgMs: number }> = [];\n\n for (const [type, stat] of Object.entries(stats)) {\n totalQueries += stat.count;\n totalTimeMs += stat.totalMs;\n slowQueries += this.recentTraces.filter(t =>\n this.extractQueryType(t.sql) === type && t.duration >= this.slowQueryThreshold\n ).length;\n errors += stat.errors;\n entries.push({ type, count: stat.count, totalMs: stat.totalMs, avgMs: stat.avgMs });\n }\n\n return {\n sessionDuration: performance.now() - this.sessionStart,\n totalQueries,\n totalTimeMs,\n avgQueryMs: totalQueries > 0 ? totalTimeMs / totalQueries : 0,\n slowQueries,\n errors,\n topByCount: [...entries].sort((a, b) => b.count - a.count).slice(0, 10),\n topByTime: [...entries].sort((a, b) => b.totalMs - a.totalMs).slice(0, 10)\n };\n }\n\n getRecentTraces(count = 20): QueryTrace[] {\n return this.recentTraces.slice(-count);\n }\n\n printReport(): void {\n const summary = this.getSummary();\n console.log('\\n========== SQL.JS PERFORMANCE REPORT ==========');\n console.log(`Session Duration: ${(summary.sessionDuration / 1000).toFixed(2)}s`);\n console.log(`Total Queries: ${summary.totalQueries}`);\n console.log(`Total SQL Time: ${summary.totalTimeMs.toFixed(2)}ms`);\n console.log(`Avg Query Time: ${summary.avgQueryMs.toFixed(3)}ms`);\n console.log(`Slow Queries (>${this.slowQueryThreshold}ms): ${summary.slowQueries}`);\n console.log(`Errors: ${summary.errors}`);\n\n console.log('\\n--- Top by Count ---');\n for (const entry of summary.topByCount) {\n console.log(` ${entry.type}: ${entry.count} calls, ${entry.totalMs.toFixed(2)}ms total, ${entry.avgMs.toFixed(3)}ms avg`);\n }\n\n console.log('\\n--- Top by Total Time ---');\n for (const entry of summary.topByTime) {\n console.log(` ${entry.type}: ${entry.totalMs.toFixed(2)}ms total, ${entry.count} calls, ${entry.avgMs.toFixed(3)}ms avg`);\n }\n\n console.log('================================================\\n');\n }\n}\n\n// Global tracer instance\nconst perfTracer = new SqlPerformanceTracer();\n\n/**\n * Convert Uint8Array to base64 string efficiently.\n * Uses chunked processing to handle large arrays without stack overflow.\n * @param bytes Uint8Array to convert\n * @returns Base64 encoded string\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // For small arrays, use the simple method\n if (bytes.length < 32768) {\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n\n // For large arrays, process in chunks to avoid stack overflow\n const chunkSize = 32768;\n let binary = '';\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));\n binary += String.fromCharCode.apply(null, Array.from(chunk));\n }\n return btoa(binary);\n}\n\n/**\n * Convert a row object for JSON serialization.\n * Converts Uint8Array (BLOB) to base64-encoded string with \"base64:\" prefix.\n * @param obj Row object from sql.js\n * @returns Object safe for JSON.stringify\n */\nfunction processRowForJson(obj: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n for (const key in obj) {\n const value = obj[key];\n if (value instanceof Uint8Array) {\n // Convert BLOB to base64 with prefix for Go to recognize\n try {\n const base64 = uint8ArrayToBase64(value);\n result[key] = 'base64:' + base64;\n } catch (err) {\n console.error(`[sql.js] Failed to convert BLOB column '${key}' (${value.length} bytes):`, err);\n result[key] = null;\n }\n } else {\n result[key] = value;\n }\n }\n return result;\n}\n\n// ============================================================================\n// Database Operations\n// ============================================================================\n\n/**\n * Create a new in-memory database\n * @returns Database handle (positive integer) or 0 on error\n */\nexport function createDatabaseOp(): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n const db = new sqlInstance.Database();\n const handle = nextHandle++;\n databases.set(handle, db);\n console.log(`[sql.js] Created database with handle ${handle}`);\n return handle;\n } catch (error) {\n console.error('[sql.js] Failed to create database:', error);\n return 0;\n }\n}\n\n/**\n * Execute SQL statement without returning results\n * @param handle Database handle\n * @param sql SQL statement\n * @returns 1 on success, 0 on error\n */\nexport function execOp(handle: number, sql: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return 0;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n try {\n db.run(sql);\n return 1;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Exec failed:', err);\n return 0;\n } finally {\n perfTracer.recordQuery(sql, '[]', startTime, performance.now(), 0, error);\n }\n}\n\n/**\n * Execute SQL query with parameters and return results as JSON\n * @param handle Database handle\n * @param sql SQL query with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns JSON string of results (array of objects) or empty string on error\n */\nexport function queryOp(handle: number, sql: string, paramsJson: string): string {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return '[]';\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n let rowCount = 0;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n }\n\n // Execute query\n const stmt = db.prepare(sql);\n if (params.length > 0) {\n stmt.bind(params);\n }\n\n // Collect results - convert Uint8Array to base64 for Go\n const results: any[] = [];\n while (stmt.step()) {\n results.push(processRowForJson(stmt.getAsObject()));\n }\n stmt.free();\n\n rowCount = results.length;\n return JSON.stringify(results);\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Query failed:', sql, err);\n return '[]';\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), rowCount, error);\n }\n}\n\n/**\n * Convert base64 string to Uint8Array\n * @param base64 Base64 encoded string\n * @returns Uint8Array of decoded bytes\n */\nfunction base64ToUint8Array(base64: string): Uint8Array {\n // Use Buffer in Node.js for correct binary handling\n if (typeof Buffer !== 'undefined') {\n return new Uint8Array(Buffer.from(base64, 'base64'));\n }\n // Browser fallback using atob\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * Process params array, converting \"base64:\" prefixed strings to Uint8Array for BLOB storage\n * @param params Array of SQL parameters\n * @returns Processed params with binary data converted to Uint8Array\n */\nfunction processParamsForBlob(params: any[]): any[] {\n return params.map(param => {\n if (typeof param === 'string' && param.startsWith('base64:')) {\n // Convert base64-prefixed string to Uint8Array for BLOB storage\n return base64ToUint8Array(param.substring(7));\n }\n return param;\n });\n}\n\n/**\n * Execute INSERT statement and return the last inserted row ID\n * @param handle Database handle\n * @param sql INSERT statement with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns Last insert row ID or 0 on error\n */\nexport function insertOp(handle: number, sql: string, paramsJson: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return 0;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n // Convert \"base64:\" prefixed strings to Uint8Array for BLOB storage\n params = processParamsForBlob(params);\n }\n\n // Execute insert\n if (params.length > 0) {\n db.run(sql, params);\n } else {\n db.run(sql);\n }\n\n // Get last insert row ID\n const result = db.exec('SELECT last_insert_rowid() as id');\n if (result.length > 0 && result[0].values.length > 0) {\n return result[0].values[0][0] as number;\n }\n return 0;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] Insert failed:', sql, err);\n return 0;\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), 1, error);\n }\n}\n\n/**\n * Execute UPDATE/DELETE statement and return rows affected\n * @param handle Database handle\n * @param sql UPDATE or DELETE statement with ? placeholders\n * @param paramsJson JSON array of parameters\n * @returns Number of rows affected or -1 on error\n */\nexport function execParamsOp(handle: number, sql: string, paramsJson: string): number {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return -1;\n }\n\n const startTime = performance.now();\n let error: string | undefined;\n let rowsAffected = 0;\n try {\n // Parse parameters\n let params: any[] = [];\n if (paramsJson && paramsJson !== '[]' && paramsJson !== 'null') {\n params = JSON.parse(paramsJson);\n // Convert \"base64:\" prefixed strings to Uint8Array for BLOB storage\n params = processParamsForBlob(params);\n }\n\n // Execute statement\n if (params.length > 0) {\n db.run(sql, params);\n } else {\n db.run(sql);\n }\n\n // Get rows affected\n const result = db.exec('SELECT changes() as count');\n if (result.length > 0 && result[0].values.length > 0) {\n rowsAffected = result[0].values[0][0] as number;\n return rowsAffected;\n }\n return 0;\n } catch (err) {\n error = String(err);\n console.error('[sql.js] ExecParams failed:', sql, err);\n return -1;\n } finally {\n perfTracer.recordQuery(sql, paramsJson, startTime, performance.now(), rowsAffected, error);\n }\n}\n\n/**\n * Export database to binary format\n * @param handle Database handle\n * @returns Base64-encoded database bytes or empty string on error\n */\nexport function exportOp(handle: number): string {\n const db = databases.get(handle);\n if (!db) {\n console.error(`[sql.js] Invalid database handle: ${handle}`);\n return '';\n }\n\n try {\n const data = db.export();\n // Use chunked base64 conversion for potentially large databases\n return uint8ArrayToBase64(data);\n } catch (error) {\n console.error('[sql.js] Export failed:', error);\n return '';\n }\n}\n\n/**\n * Import database from binary format\n * @param base64Data Base64-encoded database bytes\n * @returns Database handle or 0 on error\n */\nexport function importOp(base64Data: string): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n // Decode base64 to Uint8Array\n const binary = atob(base64Data);\n const data = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n data[i] = binary.charCodeAt(i);\n }\n\n const db = new sqlInstance.Database(data);\n const handle = nextHandle++;\n databases.set(handle, db);\n console.log(`[sql.js] Imported database with handle ${handle}`);\n return handle;\n } catch (error) {\n console.error('[sql.js] Import failed:', error);\n return 0;\n }\n}\n\n/**\n * Load database directly from bytes\n * @param bytes Raw database bytes\n * @returns Database handle or 0 on error\n */\nexport function loadDirectOp(bytes: Uint8Array): number {\n if (!sqlInstance) {\n console.error('[sql.js] Not initialized');\n return 0;\n }\n\n try {\n const db = new sqlInstance.Database(bytes);\n const handle = nextHandle++;\n databases.set(handle, db);\n return handle;\n } catch (error) {\n console.error('[sql.js] Failed to load database directly:', error);\n return 0;\n }\n}\n\n/**\n * Close a database\n * @param handle Database handle\n */\nexport function closeOp(handle: number): void {\n const db = databases.get(handle);\n if (db) {\n try {\n db.close();\n } catch (error) {\n console.error('[sql.js] Close failed:', error);\n }\n databases.delete(handle);\n console.log(`[sql.js] Closed database with handle ${handle}`);\n }\n}\n\n/**\n * Get last error message (for debugging)\n * @param _handle Database handle\n * @returns Error message or empty string\n */\nexport function getErrorOp(_handle: number): string {\n // sql.js throws exceptions rather than storing error messages\n // This is a placeholder for API compatibility\n return '';\n}\n\n/**\n * Cleanup all databases and reset state\n */\nexport function cleanupOp(): void {\n for (const [_handle, db] of databases) {\n try {\n db.close();\n } catch (_e) {\n // Ignore close errors during cleanup\n }\n }\n databases.clear();\n nextHandle = 1;\n console.log('[sql.js] Cleaned up all databases');\n}\n\n// ============================================================================\n// Bridge Exposure\n// ============================================================================\n\n/**\n * Set the SQL instance for database operations\n * Must be called before any database operations\n */\nexport function setSqlInstance(SQL: any): void {\n sqlInstance = SQL;\n}\n\n/**\n * Expose sql.js bridge functions to globalThis for Go WASM access\n */\nexport function exposeBridgeFunctions(): void {\n const g = globalThis as any;\n\n g.sqljsCreateDatabase = createDatabaseOp;\n g.sqljsExec = execOp;\n g.sqljsQuery = queryOp;\n g.sqljsInsert = insertOp;\n g.sqljsExecParams = execParamsOp;\n g.sqljsExport = exportOp;\n g.sqljsImport = importOp;\n g.sqljsClose = closeOp;\n g.sqljsGetError = getErrorOp;\n g.sqljsLoadDirect = loadDirectOp;\n\n // Also expose database map for debugging\n g.sqljsDatabases = databases;\n\n // Expose performance tracing API for debugging\n g.sqljsPerf = {\n /**\n * Enable SQL performance tracing\n * @param options.logQueries - Log all queries (default: false, only slow queries are logged)\n * @param options.slowQueryThreshold - Threshold in ms for slow query warnings (default: 10)\n * @example sqljsPerf.enable({ logQueries: true, slowQueryThreshold: 5 })\n */\n enable: (options?: { logQueries?: boolean; slowQueryThreshold?: number }) => perfTracer.enable(options),\n\n /** Disable SQL performance tracing */\n disable: () => perfTracer.disable(),\n\n /** Check if tracing is enabled */\n isEnabled: () => perfTracer.isEnabled(),\n\n /** Reset all statistics and traces */\n reset: () => perfTracer.reset(),\n\n /** Get detailed statistics by query type */\n getStats: () => perfTracer.getStats(),\n\n /** Get summary with top queries by count and time */\n getSummary: () => perfTracer.getSummary(),\n\n /** Get recent query traces (default: last 20) */\n getRecentTraces: (count?: number) => perfTracer.getRecentTraces(count),\n\n /** Print formatted performance report to console */\n printReport: () => perfTracer.printReport(),\n };\n\n console.log('[sql.js] Bridge functions exposed to globalThis');\n console.log('[sql.js] Performance tracing available via sqljsPerf.enable()');\n}\n\n/**\n * Get a database by handle (for debugging from console)\n */\nexport function getDatabase(handle: number): any {\n return databases.get(handle);\n}\n\n// ============================================================================\n// Performance Tracing Exports\n// ============================================================================\n\n/**\n * Enable SQL performance tracing\n * @param options.logQueries - Log all queries (default: false, only slow queries are logged)\n * @param options.slowQueryThreshold - Threshold in ms for slow query warnings (default: 10)\n */\nexport function enableSqlPerformanceTracing(options?: { logQueries?: boolean; slowQueryThreshold?: number }): void {\n perfTracer.enable(options);\n}\n\n/** Disable SQL performance tracing */\nexport function disableSqlPerformanceTracing(): void {\n perfTracer.disable();\n}\n\n/** Get SQL performance statistics */\nexport function getSqlPerformanceStats() {\n return perfTracer.getStats();\n}\n\n/** Get SQL performance summary */\nexport function getSqlPerformanceSummary() {\n return perfTracer.getSummary();\n}\n\n/** Print SQL performance report to console */\nexport function printSqlPerformanceReport(): void {\n perfTracer.printReport();\n}\n\n/** Get recent SQL query traces */\nexport function getRecentSqlTraces(count = 20) {\n return perfTracer.getRecentTraces(count);\n}\n\n/** Reset SQL performance statistics */\nexport function resetSqlPerformanceStats(): void {\n perfTracer.reset();\n}\n", "/**\n * Kodexa SharedWorker Entry Point\n *\n * This SharedWorker owns the Go WASM instance and exposes an RPC-style API\n * via MessagePort. Multiple tabs/windows can connect and share the same\n * WASM instance and documents, with events broadcast to all interested ports.\n *\n * Key differences from dedicated worker:\n * - Uses onconnect to handle multiple port connections\n * - Tracks document subscriptions per port for event broadcasting\n * - Reference counts documents to know when to clean up\n *\n * Initialization order (critical):\n * 1. sql.js WASM loaded and bridge exposed to globalThis\n * 2. wasm_exec.js loaded (defines globalThis.Go)\n * 3. kodexa.wasm instantiated and Go runtime started\n * 4. Worker signals 'ready' to each connected port\n */\n\n/// <reference lib=\"webworker\" />\n\nimport type {\n WorkerConfig,\n WorkerErrorMessage,\n WorkerWasmEventMessage,\n SharedWorkerRequest,\n SharedWorkerResponse,\n SharedWorkerReadyMessage,\n SharedWorkerInboundMessage,\n} from './types';\nimport { setSqlInstance, exposeBridgeFunctions, loadDirectOp } from '../wasm/sqljs-core';\n\ndeclare const self: SharedWorkerGlobalScope;\n\n// ============================================================================\n// Port Management\n// ============================================================================\n\n/** Connected ports by ID */\nconst ports = new Map<string, MessagePort>();\n\n/** Last heartbeat timestamp per port (for stale port detection) */\nconst lastHeartbeat = new Map<string, number>();\n\n/** Interval for checking stale ports */\nlet heartbeatIntervalId: ReturnType<typeof setInterval> | null = null;\n\n/** Ports are considered stale after this many ms without a heartbeat */\nconst STALE_PORT_THRESHOLD_MS = 60_000;\n\n/** How often to check for stale ports */\nconst HEARTBEAT_CHECK_INTERVAL_MS = 30_000;\n\n/** Counter for generating unique port IDs */\nlet nextPortId = 1;\n\n/** Generate a unique port ID */\nfunction generatePortId(): string {\n return `port_${nextPortId++}_${Date.now()}`;\n}\n\n// ============================================================================\n// Document State Management\n// ============================================================================\n\n/** Track which ports are subscribed to which documents for event broadcasting */\nconst documentSubscriptions = new Map<number, Set<string>>(); // docRef -> Set<portId>\n\n/** Track which ports are using which documents (for cleanup) */\nconst documentUsers = new Map<number, Set<string>>(); // docRef -> Set<portId>\n\n// ============================================================================\n// Shared Document Registry (by documentFamilyId)\n// Enables multiple tabs to share the same WASM document instance\n// ============================================================================\n\n/** Map documentFamilyId -> docRef for sharing documents across tabs */\nconst sharedDocuments = new Map<string, number>();\n\n/** Track which ports are using each shared document (by documentFamilyId) */\nconst sharedDocumentUsers = new Map<string, Set<string>>(); // documentFamilyId -> Set<portId>\n\n/**\n * Subscribe a port to document events.\n */\nfunction subscribeToDocument(docRef: number, portId: string): void {\n if (!documentSubscriptions.has(docRef)) {\n documentSubscriptions.set(docRef, new Set());\n }\n documentSubscriptions.get(docRef)!.add(portId);\n console.log(`[shared-worker] Port ${portId} subscribed to document ${docRef}`);\n}\n\n/**\n * Unsubscribe a port from document events.\n */\nfunction unsubscribeFromDocument(docRef: number, portId: string): void {\n const subscribers = documentSubscriptions.get(docRef);\n if (subscribers) {\n subscribers.delete(portId);\n if (subscribers.size === 0) {\n documentSubscriptions.delete(docRef);\n }\n console.log(`[shared-worker] Port ${portId} unsubscribed from document ${docRef}`);\n }\n}\n\n/**\n * Register a port as using a document (for reference counting).\n */\nfunction registerDocumentUser(docRef: number, portId: string): void {\n if (!documentUsers.has(docRef)) {\n documentUsers.set(docRef, new Set());\n }\n documentUsers.get(docRef)!.add(portId);\n}\n\n/**\n * Unregister a port from a document. Returns true if document should be freed.\n */\nfunction unregisterDocumentUser(docRef: number, portId: string): boolean {\n const users = documentUsers.get(docRef);\n if (users) {\n users.delete(portId);\n if (users.size === 0) {\n documentUsers.delete(docRef);\n return true; // No more users, safe to free\n }\n }\n return false;\n}\n\n// ============================================================================\n// Shared Document Functions (by documentFamilyId)\n// ============================================================================\n\n/**\n * Load or join a shared document by documentFamilyId.\n * If another tab has already loaded this document, returns the existing docRef.\n * If not loaded, loads from provided kddbBytes and registers as shared.\n *\n * @param documentFamilyId - Unique identifier for the document family\n * @param portId - Port ID of the requesting tab\n * @param kddbBytes - KDDB bytes (required if document not already loaded)\n * @returns Object with docRef, shared status, and user count\n */\nfunction loadSharedDocument(\n documentFamilyId: string,\n portId: string,\n kddbBytes?: Uint8Array\n): { docRef: number; shared: boolean; userCount: number } {\n // Check if already loaded by another tab\n if (sharedDocuments.has(documentFamilyId)) {\n const existingDocRef = sharedDocuments.get(documentFamilyId)!;\n\n // Validate docRef is still alive - first check tracking maps, then WASM\n let isValid = false;\n const docUsers = documentUsers.get(existingDocRef);\n if (docUsers && docUsers.size > 0) {\n // Tracking maps show active users - verify WASM doc is still valid\n const documentGetRoot = (self as any).documentGetRoot;\n if (typeof documentGetRoot === 'function') {\n try {\n const root = documentGetRoot(existingDocRef);\n isValid = root !== null && root !== undefined;\n } catch {\n isValid = false;\n }\n } else {\n // Can't validate WASM - trust tracking maps\n isValid = true;\n }\n }\n // If no users in tracking maps, docRef is definitely stale\n\n if (!isValid) {\n console.warn(`[shared-worker] Stale shared document ${documentFamilyId} (docRef: ${existingDocRef}), cleaning up`);\n // Clean up all tracking for this stale entry\n const staleUsers = sharedDocumentUsers.get(documentFamilyId);\n if (staleUsers) {\n for (const uid of staleUsers) {\n unsubscribeFromDocument(existingDocRef, uid);\n unregisterDocumentUser(existingDocRef, uid);\n }\n }\n sharedDocuments.delete(documentFamilyId);\n sharedDocumentUsers.delete(documentFamilyId);\n documentSubscriptions.delete(existingDocRef);\n documentUsers.delete(existingDocRef);\n // Fall through to load from bytes below\n } else {\n // Valid doc - register port as user\n let users = sharedDocumentUsers.get(documentFamilyId);\n if (!users) {\n users = new Set();\n sharedDocumentUsers.set(documentFamilyId, users);\n }\n users.add(portId);\n\n // Also register in the regular document users tracking\n registerDocumentUser(existingDocRef, portId);\n\n // Auto-subscribe to document events\n subscribeToDocument(existingDocRef, portId);\n\n console.log(`[shared-worker] Port ${portId} joined shared document ${documentFamilyId} (docRef: ${existingDocRef}), ${users.size} users`);\n\n return {\n docRef: existingDocRef,\n shared: true,\n userCount: users.size,\n };\n }\n }\n\n // Not loaded - need kddbBytes\n if (!kddbBytes) {\n throw new Error(`Document ${documentFamilyId} not loaded and no bytes provided`);\n }\n\n // Load new document using loadDocument\n const loadDocument = (self as any).loadDocument;\n if (typeof loadDocument !== 'function') {\n throw new Error('loadDocument function not available');\n }\n\n const docRef = loadDocument(kddbBytes);\n if (docRef === 0) {\n throw new Error('Failed to load document from KDDB bytes');\n }\n\n // Register as shared document\n sharedDocuments.set(documentFamilyId, docRef);\n const users = new Set<string>([portId]);\n sharedDocumentUsers.set(documentFamilyId, users);\n\n // Register in regular tracking\n registerDocumentUser(docRef, portId);\n\n // Auto-subscribe to events\n subscribeToDocument(docRef, portId);\n\n console.log(`[shared-worker] Port ${portId} loaded shared document ${documentFamilyId} (docRef: ${docRef})`);\n\n return {\n docRef,\n shared: false,\n userCount: 1,\n };\n}\n\n/**\n * Release this tab's reference to a shared document.\n * Document is freed when all tabs release it.\n *\n * @param documentFamilyId - Document family ID to release\n * @param portId - Port ID releasing the document\n * @returns Object with freed status and remaining user count\n */\nfunction releaseSharedDocument(\n documentFamilyId: string,\n portId: string\n): { freed: boolean; remainingUsers?: number; notFound?: boolean } {\n const docRef = sharedDocuments.get(documentFamilyId);\n\n if (docRef === undefined) {\n return { freed: false, notFound: true };\n }\n\n // Remove this port from shared document users\n const users = sharedDocumentUsers.get(documentFamilyId);\n if (users) {\n users.delete(portId);\n\n // Unsubscribe from events\n unsubscribeFromDocument(docRef, portId);\n\n // Unregister from regular tracking\n unregisterDocumentUser(docRef, portId);\n\n // If no users left, free the document\n if (users.size === 0) {\n console.log(`[shared-worker] Freeing shared document ${documentFamilyId} (docRef: ${docRef}) - no more users`);\n\n // Free the document\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n\n // Clean up registry\n sharedDocuments.delete(documentFamilyId);\n sharedDocumentUsers.delete(documentFamilyId);\n documentSubscriptions.delete(docRef);\n\n return { freed: true };\n }\n\n console.log(`[shared-worker] Port ${portId} released shared document ${documentFamilyId}, ${users.size} users remaining`);\n return { freed: false, remainingUsers: users.size };\n }\n\n return { freed: false, notFound: true };\n}\n\n/**\n * Check if a document is already loaded as a shared document.\n *\n * @param documentFamilyId - Document family ID to check\n * @returns true if document is loaded, false otherwise\n */\nfunction isDocumentShared(documentFamilyId: string): boolean {\n return sharedDocuments.has(documentFamilyId);\n}\n\n/**\n * Get the docRef for a shared document by documentFamilyId.\n *\n * @param documentFamilyId - Document family ID to look up\n * @returns docRef if found, undefined otherwise\n */\nfunction getSharedDocumentRef(documentFamilyId: string): number | undefined {\n return sharedDocuments.get(documentFamilyId);\n}\n\n/**\n * Invalidate a shared document and notify other tabs.\n * Called when one tab force-reloads a document.\n *\n * @param documentFamilyId - Document family ID being invalidated\n * @param portId - Port ID of the tab initiating the invalidation\n * @param reason - Reason for invalidation (e.g., 'reload', 'server-update')\n */\nfunction invalidateSharedDocument(\n documentFamilyId: string,\n portId: string,\n reason: string\n): void {\n const docRef = sharedDocuments.get(documentFamilyId);\n\n if (docRef === undefined) {\n return;\n }\n\n const users = sharedDocumentUsers.get(documentFamilyId);\n if (!users) {\n return;\n }\n\n // Notify all OTHER tabs using this document\n for (const userPortId of users) {\n if (userPortId !== portId) {\n const port = ports.get(userPortId);\n if (port) {\n try {\n port.postMessage({\n type: 'documentInvalidated',\n documentFamilyId,\n reason,\n initiatorPortId: portId,\n });\n console.log(`[shared-worker] Notified port ${userPortId} of document invalidation: ${documentFamilyId}`);\n } catch (error) {\n console.error(`[shared-worker] Error notifying port ${userPortId}:`, error);\n }\n }\n }\n }\n}\n\n/**\n * Cleanup all resources associated with a port.\n */\nfunction cleanupPort(portId: string): void {\n console.log(`[shared-worker] Cleaning up port ${portId}`);\n\n // Remove from all document subscriptions\n for (const [docRef, subscribers] of documentSubscriptions) {\n subscribers.delete(portId);\n if (subscribers.size === 0) {\n documentSubscriptions.delete(docRef);\n }\n }\n\n // Release all shared documents this port was using\n for (const [documentFamilyId, users] of sharedDocumentUsers) {\n if (users.has(portId)) {\n users.delete(portId);\n\n // If last user, free document and clean up\n if (users.size === 0) {\n const docRef = sharedDocuments.get(documentFamilyId);\n if (docRef !== undefined) {\n console.log(`[shared-worker] Freeing shared document ${documentFamilyId} (docRef: ${docRef}) - port ${portId} was last user`);\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n sharedDocuments.delete(documentFamilyId);\n documentUsers.delete(docRef);\n }\n sharedDocumentUsers.delete(documentFamilyId);\n }\n }\n }\n\n // Unregister from all non-shared document users\n for (const [docRef, users] of documentUsers) {\n users.delete(portId);\n if (users.size === 0) {\n // Check if this is a shared document - if so, it's already handled above\n let isShared = false;\n for (const [, sharedDocRef] of sharedDocuments) {\n if (sharedDocRef === docRef) {\n isShared = true;\n break;\n }\n }\n\n if (!isShared) {\n // No ports using this non-shared document, free it\n console.log(`[shared-worker] Freeing non-shared document ${docRef} - no more users`);\n try {\n const freeDocument = (self as any).freeDocument;\n if (typeof freeDocument === 'function') {\n freeDocument(docRef);\n }\n } catch (error) {\n console.error(`[shared-worker] Error freeing document ${docRef}:`, error);\n }\n }\n documentUsers.delete(docRef);\n }\n }\n\n // Remove heartbeat tracking\n lastHeartbeat.delete(portId);\n\n // Remove port\n ports.delete(portId);\n\n // Stop heartbeat checking if no ports remain\n if (ports.size === 0 && heartbeatIntervalId) {\n clearInterval(heartbeatIntervalId);\n heartbeatIntervalId = null;\n }\n}\n\n/**\n * Check for and clean up stale ports that haven't sent a heartbeat recently.\n * This catches tab crashes, mobile eviction, and other cases where\n * beforeunload doesn't fire.\n */\nfunction checkForStalePorts(): void {\n const now = Date.now();\n // Collect stale ports first to avoid modifying map during iteration\n const stalePorts: string[] = [];\n for (const [portId, lastBeat] of lastHeartbeat) {\n if (now - lastBeat >= STALE_PORT_THRESHOLD_MS) {\n stalePorts.push(portId);\n }\n }\n for (const portId of stalePorts) {\n console.log(`[shared-worker] Port ${portId} stale (no heartbeat for ${STALE_PORT_THRESHOLD_MS}ms), cleaning up`);\n cleanupPort(portId); // cleanupPort already removes from lastHeartbeat\n }\n}\n\n// ============================================================================\n// Event Broadcasting\n// ============================================================================\n\n/**\n * Broadcast an event to all ports subscribed to a document.\n */\nfunction broadcastToSubscribers(docRef: number, eventType: string, detail: unknown): void {\n const subscribers = documentSubscriptions.get(docRef);\n console.log(`[shared-worker] broadcastToSubscribers called docRef=${docRef} eventType=${eventType} subscriberCount=${subscribers?.size ?? 0}`);\n if (!subscribers || subscribers.size === 0) {\n console.log(`[shared-worker] No subscribers for document ${docRef}, event not broadcast`);\n return;\n }\n\n const message: WorkerWasmEventMessage = {\n type: 'wasmEvent',\n eventType,\n detail,\n documentRef: docRef,\n };\n\n for (const portId of subscribers) {\n const port = ports.get(portId);\n if (port) {\n try {\n console.log(`[shared-worker] Posting wasmEvent to port ${portId}`);\n port.postMessage(message);\n console.log(`[shared-worker] Posted wasmEvent to port ${portId} successfully`);\n } catch (error) {\n console.error(`[shared-worker] Error posting to port ${portId}:`, error);\n }\n } else {\n console.warn(`[shared-worker] Port ${portId} not found in ports map, cannot send event`);\n }\n }\n}\n\n/**\n * Broadcast an event to ALL connected ports.\n */\nfunction broadcastToAll(message: unknown): void {\n for (const [portId, port] of ports) {\n try {\n port.postMessage(message);\n } catch (error) {\n console.error(`[shared-worker] Error posting to port ${portId}:`, error);\n }\n }\n}\n\n// ============================================================================\n// Worker State\n// ============================================================================\n\nlet initialized = false;\nlet initPromise: Promise<void> | null = null;\nlet config: WorkerConfig = {};\n\n// ============================================================================\n// Event Forwarding from WASM\n// ============================================================================\n\n/**\n * Set up event forwarding from WASM to connected ports.\n *\n * SIMPLIFIED ARCHITECTURE:\n * Go WASM calls document.dispatchEvent(CustomEvent) with JSON string detail.\n * We parse the JSON once here and broadcast directly to subscribers.\n * No intermediate self.dispatchEvent \u2192 addEventListener dance needed.\n */\nfunction setupEventForwarding(): void {\n // Create a document shim for Go WASM to dispatch events\n const documentShim = {\n addEventListener: (type: string, handler: EventListener) => {\n // Go WASM may register listeners, but we handle events directly in dispatchEvent\n console.log(`[shared-worker] Event listener registered for: ${type} (handled in dispatchEvent)`);\n },\n removeEventListener: (type: string, handler: EventListener) => {\n // No-op - we don't use addEventListener\n },\n dispatchEvent: (event: Event) => {\n // Handle CustomEvents from Go WASM directly - no intermediate dispatch needed\n if (!(event instanceof CustomEvent)) {\n return true;\n }\n\n const eventType = event.type;\n const rawDetail = event.detail;\n\n // Parse JSON detail once (Go sends it as a JSON string)\n let parsedDetail: any;\n try {\n parsedDetail = typeof rawDetail === 'string' ? JSON.parse(rawDetail) : rawDetail;\n } catch (e) {\n console.warn(`[shared-worker] Failed to parse ${eventType} detail:`, e);\n parsedDetail = rawDetail;\n }\n\n const docRef = parsedDetail?.documentRef;\n console.log(`[shared-worker] dispatchEvent: ${eventType}`, { docRef, eventType: parsedDetail?.eventType });\n\n if (docRef !== undefined) {\n // Document-specific event - broadcast to subscribers only\n // Pass the PARSED detail so UI doesn't need to parse again\n broadcastToSubscribers(docRef, eventType, parsedDetail);\n } else {\n // Global event - broadcast to all ports\n broadcastToAll({\n type: 'wasmEvent',\n eventType: eventType,\n detail: parsedDetail,\n } as WorkerWasmEventMessage);\n }\n\n return true;\n },\n createElement: () => null,\n body: null,\n documentElement: null,\n };\n\n (self as any).document = documentShim;\n\n console.log('[shared-worker] Event forwarding configured (simplified architecture)');\n}\n\n// ============================================================================\n// WASM Loading (same as dedicated worker)\n// ============================================================================\n\nasync function initializeSqlJs(): Promise<void> {\n const sqlJsUrl = 'https://sql.js.org/dist/sql-wasm.js';\n const sqlWasmUrl = 'https://sql.js.org/dist/sql-wasm.wasm';\n\n try {\n const response = await fetch(sqlJsUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch sql-wasm.js: ${response.statusText}`);\n }\n const code = await response.text();\n\n const wrappedCode = `\n (function(module, exports) {\n ${code}\n return module.exports;\n })\n `;\n\n // eslint-disable-next-line no-eval\n const moduleFactory = eval(wrappedCode);\n const mockModule = { exports: {} as any };\n const initSqlJs = moduleFactory(mockModule, mockModule.exports);\n\n if (typeof initSqlJs !== 'function') {\n throw new Error('initSqlJs not found after loading sql-wasm.js');\n }\n\n const sqlConfig = {\n locateFile: () => sqlWasmUrl,\n };\n\n const SQL = await initSqlJs(sqlConfig);\n setSqlInstance(SQL);\n exposeBridgeFunctions();\n\n // Expose loadDocument function\n (self as any).loadDocument = (bytes: Uint8Array): number => {\n const handle = loadDirectOp(bytes);\n if (handle === 0) {\n console.error('[shared-worker] Failed to load database');\n return 0;\n }\n return (self as any).createDocumentFromHandle(handle);\n };\n\n console.log('[shared-worker] sql.js initialized from official CDN');\n } catch (error) {\n console.error('[shared-worker] Failed to initialize sql.js:', error);\n throw new Error(`Failed to initialize sql.js: ${error}`);\n }\n}\n\nasync function loadWasmExec(): Promise<void> {\n if ((self as any).Go) {\n return;\n }\n\n const baseUrl = config.wasmBaseUrl || self.location.origin;\n const wasmExecUrl = `${baseUrl}/wasm_exec.js`;\n\n try {\n const response = await fetch(wasmExecUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch wasm_exec.js: ${response.statusText}`);\n }\n const code = await response.text();\n // eslint-disable-next-line no-eval\n eval(code);\n console.log('[shared-worker] wasm_exec.js loaded');\n } catch (error) {\n throw new Error(`Failed to load wasm_exec.js: ${error}`);\n }\n}\n\nasync function loadGoWasm(): Promise<void> {\n const baseUrl = config.wasmBaseUrl || self.location.origin;\n // Add cache-busting version if provided\n const versionParam = config.wasmVersion ? `?v=${config.wasmVersion}` : '';\n const wasmUrl = `${baseUrl}/kodexa.wasm${versionParam}`;\n\n const response = await fetch(wasmUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch kodexa.wasm: ${response.statusText}`);\n }\n const wasmBytes = await response.arrayBuffer();\n\n const go = new (self as any).Go();\n const result = await WebAssembly.instantiate(wasmBytes, go.importObject);\n go.run(result.instance);\n\n const logLevel = config.logLevel || 'warn';\n if ((self as any).kodexa_setLogLevel) {\n (self as any).kodexa_setLogLevel(logLevel);\n }\n\n console.log('[shared-worker] Go WASM loaded');\n}\n\nasync function initialize(workerConfig?: WorkerConfig): Promise<void> {\n if (initialized) {\n return;\n }\n\n if (initPromise) {\n return initPromise;\n }\n\n config = workerConfig || {};\n\n initPromise = (async () => {\n try {\n setupEventForwarding();\n await initializeSqlJs();\n await loadWasmExec();\n await loadGoWasm();\n initialized = true;\n console.log('[shared-worker] Kodexa WASM fully initialized');\n } catch (error) {\n console.error('[shared-worker] Initialization failed:', error);\n throw error;\n }\n })();\n\n return initPromise;\n}\n\n// ============================================================================\n// Message Handling\n// ============================================================================\n\n/**\n * Handle RPC call from a port.\n */\nfunction handleCall(request: SharedWorkerRequest): SharedWorkerResponse {\n const { id, method, args, portId } = request;\n\n try {\n const fn = (self as any)[method];\n if (typeof fn !== 'function') {\n return {\n id,\n portId,\n success: false,\n error: `Function '${method}' not found on globalThis`,\n };\n }\n\n const result = fn(...(args || []));\n\n // Track document usage when creating/loading documents\n if (method === 'createDocument' || method === 'createDocumentFromText' ||\n method === 'createDocumentFromJson' || method === 'createDocumentFromKddbBytes' ||\n method === 'loadDocument') {\n if (typeof result === 'number' && result > 0) {\n registerDocumentUser(result, portId);\n }\n }\n\n // Track document disposal\n if (method === 'freeDocument' && args && args.length > 0) {\n const docRef = args[0] as number;\n const shouldFree = unregisterDocumentUser(docRef, portId);\n if (!shouldFree) {\n // Other ports still using this document, don't actually free it\n return { id, portId, success: true, result: undefined };\n }\n }\n\n return { id, portId, success: true, result };\n } catch (error) {\n return {\n id,\n portId,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Handle messages from a connected port.\n */\nfunction handlePortMessage(portId: string, port: MessagePort, event: MessageEvent<SharedWorkerInboundMessage>): void {\n const data = event.data;\n\n // Handle init message\n if ('type' in data && data.type === 'init') {\n (async () => {\n try {\n await initialize(data.config);\n const readyMessage: SharedWorkerReadyMessage = { type: 'ready', portId };\n port.postMessage(readyMessage);\n } catch (error) {\n const errorMessage: WorkerErrorMessage = {\n type: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n port.postMessage(errorMessage);\n }\n })();\n return;\n }\n\n // Handle subscription messages\n if ('type' in data && data.type === 'subscribe') {\n subscribeToDocument(data.docRef, portId);\n return;\n }\n\n if ('type' in data && data.type === 'unsubscribe') {\n unsubscribeFromDocument(data.docRef, portId);\n return;\n }\n\n // Handle shared document messages\n if ('type' in data && data.type === 'loadSharedDocument') {\n const { documentFamilyId, kddbBytes, requestId } = data as any;\n if (!initialized) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: 'Worker not initialized',\n requestType: 'loadSharedDocument',\n requestId,\n });\n return;\n }\n\n try {\n const result = loadSharedDocument(documentFamilyId, portId, kddbBytes);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'loadSharedDocument',\n requestId,\n ...result,\n });\n } catch (error) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: error instanceof Error ? error.message : String(error),\n requestType: 'loadSharedDocument',\n requestId,\n });\n }\n return;\n }\n\n if ('type' in data && data.type === 'releaseSharedDocument') {\n const { documentFamilyId, requestId } = data as any;\n try {\n const result = releaseSharedDocument(documentFamilyId, portId);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'releaseSharedDocument',\n requestId,\n ...result,\n });\n } catch (error) {\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: false,\n error: error instanceof Error ? error.message : String(error),\n requestType: 'releaseSharedDocument',\n requestId,\n });\n }\n return;\n }\n\n if ('type' in data && data.type === 'isDocumentShared') {\n const { documentFamilyId, requestId } = data as any;\n const shared = isDocumentShared(documentFamilyId);\n const docRef = getSharedDocumentRef(documentFamilyId);\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'isDocumentShared',\n requestId,\n shared,\n docRef,\n });\n return;\n }\n\n if ('type' in data && data.type === 'invalidateSharedDocument') {\n const { documentFamilyId, reason, requestId } = data as any;\n invalidateSharedDocument(documentFamilyId, portId, reason || 'reload');\n port.postMessage({\n type: 'sharedDocumentResponse',\n success: true,\n requestType: 'invalidateSharedDocument',\n requestId,\n });\n return;\n }\n\n // Handle heartbeat message\n if ('type' in data && data.type === 'heartbeat') {\n lastHeartbeat.set(portId, Date.now());\n return;\n }\n\n // Handle disconnect message (clean exit from tab close/reload)\n if ('type' in data && data.type === 'disconnect') {\n console.log(`[shared-worker] Port ${portId} sent disconnect message, cleaning up`);\n cleanupPort(portId);\n return;\n }\n\n // Handle RPC call\n if ('type' in data && data.type === 'call') {\n if (!initialized) {\n const response: SharedWorkerResponse = {\n id: (data as SharedWorkerRequest).id,\n portId,\n success: false,\n error: 'Worker not initialized. Send init message first.',\n };\n port.postMessage(response);\n return;\n }\n\n // Add portId to the request\n const request = { ...data, portId } as SharedWorkerRequest;\n const response = handleCall(request);\n port.postMessage(response);\n }\n}\n\n// ============================================================================\n// SharedWorker Connection Handler\n// ============================================================================\n\nself.onconnect = (event: MessageEvent) => {\n const port = event.ports[0];\n const portId = generatePortId();\n\n console.log(`[shared-worker] New port connected: ${portId}`);\n ports.set(portId, port);\n lastHeartbeat.set(portId, Date.now());\n\n // Set up message handler for this port\n port.onmessage = (e) => handlePortMessage(portId, port, e);\n\n // Handle port closure (tab closed)\n // Note: Not all browsers reliably fire this event\n port.onmessageerror = () => {\n console.log(`[shared-worker] Port ${portId} message error, cleaning up`);\n cleanupPort(portId);\n };\n\n // Start the port\n port.start();\n\n // Start heartbeat checking interval if not already running\n if (!heartbeatIntervalId) {\n heartbeatIntervalId = setInterval(checkForStalePorts, HEARTBEAT_CHECK_INTERVAL_MS);\n }\n\n // If already initialized, send ready immediately\n if (initialized) {\n const readyMessage: SharedWorkerReadyMessage = { type: 'ready', portId };\n port.postMessage(readyMessage);\n }\n\n // Send connected message so port knows its ID\n port.postMessage({ type: 'connected', portId });\n};\n\n// Log that shared worker is ready for connections\nconsole.log('[shared-worker] Kodexa SharedWorker ready for connections');\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;AAmOA,SAAS,mBAAmB,OAA2B;AAErD,MAAI,MAAM,SAAS,OAAO;AACxB,QAAIA,UAAS;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,MAAAA,WAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,IACxC;AACA,WAAO,KAAKA,OAAM;AAAA,EACpB;AAGA,QAAM,YAAY;AAClB,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AAChD,UAAM,QAAQ,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,WAAW,MAAM,MAAM,CAAC;AACrE,cAAU,OAAO,aAAa,MAAM,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,EAC7D;AACA,SAAO,KAAK,MAAM;AACpB;AAQA,SAAS,kBAAkB,KAA+C;AACxE,QAAM,SAA8B,CAAC;AACrC,aAAW,OAAO,KAAK;AACrB,UAAM,QAAQ,IAAI,GAAG;AACrB,QAAI,iBAAiB,YAAY;AAE/B,UAAI;AACF,cAAM,SAAS,mBAAmB,KAAK;AACvC,eAAO,GAAG,IAAI,YAAY;AAAA,MAC5B,SAAS,KAAK;AACZ,gBAAQ,MAAM,2CAA2C,GAAG,MAAM,MAAM,MAAM,YAAY,GAAG;AAC7F,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAUO,SAAS,mBAA2B;AACzC,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,0BAA0B;AACxC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,KAAK,IAAI,YAAY,SAAS;AACpC,UAAM,SAAS;AACf,cAAU,IAAI,QAAQ,EAAE;AACxB,YAAQ,IAAI,yCAAyC,MAAM,EAAE;AAC7D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,uCAAuC,KAAK;AAC1D,WAAO;AAAA,EACT;AACF;AAQO,SAAS,OAAO,QAAgB,KAAqB;AAC1D,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,qCAAqC,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACJ,MAAI;AACF,OAAG,IAAI,GAAG;AACV,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,OAAO,GAAG;AAClB,YAAQ,MAAM,yBAAyB,GAAG;AAC1C,WAAO;AAAA,EACT,UAAE;AACA,eAAW,YAAY,KAAK,MAAM,WAAW,YAAY,IAAI,GAAG,GAAG,KAAK;AAAA,EAC1E;AACF;AASO,SAAS,QAAQ,QAAgB,KAAa,YAA4B;AAC/E,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,qCAAqC,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACJ,MAAI,WAAW;AACf,MAAI;AAEF,QAAI,SAAgB,CAAC;AACrB,QAAI,cAAc,eAAe,QAAQ,eAAe,QAAQ;AAC9D,eAAS,KAAK,MAAM,UAAU;AAAA,IAChC;AAGA,UAAM,OAAO,GAAG,QAAQ,GAAG;AAC3B,QAAI,OAAO,SAAS,GAAG;AACrB,WAAK,KAAK,MAAM;AAAA,IAClB;AAGA,UAAM,UAAiB,CAAC;AACxB,WAAO,KAAK,KAAK,GAAG;AAClB,cAAQ,KAAK,kBAAkB,KAAK,YAAY,CAAC,CAAC;AAAA,IACpD;AACA,SAAK,KAAK;AAEV,eAAW,QAAQ;AACnB,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B,SAAS,KAAK;AACZ,YAAQ,OAAO,GAAG;AAClB,YAAQ,MAAM,0BAA0B,KAAK,GAAG;AAChD,WAAO;AAAA,EACT,UAAE;AACA,eAAW,YAAY,KAAK,YAAY,WAAW,YAAY,IAAI,GAAG,UAAU,KAAK;AAAA,EACvF;AACF;AAOA,SAAS,mBAAmB,QAA4B;AAEtD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,IAAI,WAAW,OAAO,KAAK,QAAQ,QAAQ,CAAC;AAAA,EACrD;AAEA,QAAM,SAAS,KAAK,MAAM;AAC1B,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AAOA,SAAS,qBAAqB,QAAsB;AAClD,SAAO,OAAO,IAAI,WAAS;AACzB,QAAI,OAAO,UAAU,YAAY,MAAM,WAAW,SAAS,GAAG;AAE5D,aAAO,mBAAmB,MAAM,UAAU,CAAC,CAAC;AAAA,IAC9C;AACA,WAAO;AAAA,EACT,CAAC;AACH;AASO,SAAS,SAAS,QAAgB,KAAa,YAA4B;AAChF,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,qCAAqC,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACJ,MAAI;AAEF,QAAI,SAAgB,CAAC;AACrB,QAAI,cAAc,eAAe,QAAQ,eAAe,QAAQ;AAC9D,eAAS,KAAK,MAAM,UAAU;AAE9B,eAAS,qBAAqB,MAAM;AAAA,IACtC;AAGA,QAAI,OAAO,SAAS,GAAG;AACrB,SAAG,IAAI,KAAK,MAAM;AAAA,IACpB,OAAO;AACL,SAAG,IAAI,GAAG;AAAA,IACZ;AAGA,UAAM,SAAS,GAAG,KAAK,kCAAkC;AACzD,QAAI,OAAO,SAAS,KAAK,OAAO,CAAC,EAAE,OAAO,SAAS,GAAG;AACpD,aAAO,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;AAAA,IAC9B;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,OAAO,GAAG;AAClB,YAAQ,MAAM,2BAA2B,KAAK,GAAG;AACjD,WAAO;AAAA,EACT,UAAE;AACA,eAAW,YAAY,KAAK,YAAY,WAAW,YAAY,IAAI,GAAG,GAAG,KAAK;AAAA,EAChF;AACF;AASO,SAAS,aAAa,QAAgB,KAAa,YAA4B;AACpF,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,qCAAqC,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,IAAI;AAClC,MAAI;AACJ,MAAI,eAAe;AACnB,MAAI;AAEF,QAAI,SAAgB,CAAC;AACrB,QAAI,cAAc,eAAe,QAAQ,eAAe,QAAQ;AAC9D,eAAS,KAAK,MAAM,UAAU;AAE9B,eAAS,qBAAqB,MAAM;AAAA,IACtC;AAGA,QAAI,OAAO,SAAS,GAAG;AACrB,SAAG,IAAI,KAAK,MAAM;AAAA,IACpB,OAAO;AACL,SAAG,IAAI,GAAG;AAAA,IACZ;AAGA,UAAM,SAAS,GAAG,KAAK,2BAA2B;AAClD,QAAI,OAAO,SAAS,KAAK,OAAO,CAAC,EAAE,OAAO,SAAS,GAAG;AACpD,qBAAe,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;AACpC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ,OAAO,GAAG;AAClB,YAAQ,MAAM,+BAA+B,KAAK,GAAG;AACrD,WAAO;AAAA,EACT,UAAE;AACA,eAAW,YAAY,KAAK,YAAY,WAAW,YAAY,IAAI,GAAG,cAAc,KAAK;AAAA,EAC3F;AACF;AAOO,SAAS,SAAS,QAAwB;AAC/C,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,CAAC,IAAI;AACP,YAAQ,MAAM,qCAAqC,MAAM,EAAE;AAC3D,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,OAAO,GAAG,OAAO;AAEvB,WAAO,mBAAmB,IAAI;AAAA,EAChC,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,WAAO;AAAA,EACT;AACF;AAOO,SAAS,SAAS,YAA4B;AACnD,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,0BAA0B;AACxC,WAAO;AAAA,EACT;AAEA,MAAI;AAEF,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAM,OAAO,IAAI,WAAW,OAAO,MAAM;AACzC,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,WAAK,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,IAC/B;AAEA,UAAM,KAAK,IAAI,YAAY,SAAS,IAAI;AACxC,UAAM,SAAS;AACf,cAAU,IAAI,QAAQ,EAAE;AACxB,YAAQ,IAAI,0CAA0C,MAAM,EAAE;AAC9D,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,WAAO;AAAA,EACT;AACF;AAOO,SAAS,aAAa,OAA2B;AACtD,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,0BAA0B;AACxC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,KAAK,IAAI,YAAY,SAAS,KAAK;AACzC,UAAM,SAAS;AACf,cAAU,IAAI,QAAQ,EAAE;AACxB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,8CAA8C,KAAK;AACjE,WAAO;AAAA,EACT;AACF;AAMO,SAAS,QAAQ,QAAsB;AAC5C,QAAM,KAAK,UAAU,IAAI,MAAM;AAC/B,MAAI,IAAI;AACN,QAAI;AACF,SAAG,MAAM;AAAA,IACX,SAAS,OAAO;AACd,cAAQ,MAAM,0BAA0B,KAAK;AAAA,IAC/C;AACA,cAAU,OAAO,MAAM;AACvB,YAAQ,IAAI,wCAAwC,MAAM,EAAE;AAAA,EAC9D;AACF;AAOO,SAAS,WAAW,SAAyB;AAGlD,SAAO;AACT;AA0BO,SAAS,eAAeC,MAAgB;AAC7C,gBAAcA;AAChB;AAKO,SAAS,wBAA8B;AAC5C,QAAM,IAAI;AAEV,IAAE,sBAAsB;AACxB,IAAE,YAAY;AACd,IAAE,aAAa;AACf,IAAE,cAAc;AAChB,IAAE,kBAAkB;AACpB,IAAE,cAAc;AAChB,IAAE,cAAc;AAChB,IAAE,aAAa;AACf,IAAE,gBAAgB;AAClB,IAAE,kBAAkB;AAGpB,IAAE,iBAAiB;AAGnB,IAAE,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOZ,QAAQ,CAAC,YAAoE,WAAW,OAAO,OAAO;AAAA;AAAA,IAGtG,SAAS,MAAM,WAAW,QAAQ;AAAA;AAAA,IAGlC,WAAW,MAAM,WAAW,UAAU;AAAA;AAAA,IAGtC,OAAO,MAAM,WAAW,MAAM;AAAA;AAAA,IAG9B,UAAU,MAAM,WAAW,SAAS;AAAA;AAAA,IAGpC,YAAY,MAAM,WAAW,WAAW;AAAA;AAAA,IAGxC,iBAAiB,CAAC,UAAmB,WAAW,gBAAgB,KAAK;AAAA;AAAA,IAGrE,aAAa,MAAM,WAAW,YAAY;AAAA,EAC5C;AAEA,UAAQ,IAAI,iDAAiD;AAC7D,UAAQ,IAAI,+DAA+D;AAC7E;AAhrBA,IAWM,WACF,YAGA,aAwBE,sBAoLA;AA3NN;AAAA;AAAA;AAWA,IAAM,YAAY,oBAAI,IAAiB;AACvC,IAAI,aAAa;AAGjB,IAAI,cAAmB;AAwBvB,IAAM,uBAAN,MAA2B;AAAA,MAA3B;AACE,aAAQ,UAAU;AAClB,aAAQ,QAA+B,oBAAI,IAAI;AAC/C,aAAQ,eAA6B,CAAC;AACtC,aAAQ,kBAAkB;AAC1B,aAAQ,eAAe;AACvB,aAAQ,aAAa;AACrB,aAAQ,qBAAqB;AAAA;AAAA;AAAA,MAE7B,OAAO,SAAuE;AAC5E,aAAK,UAAU;AACf,aAAK,eAAe,YAAY,IAAI;AACpC,aAAK,aAAa,SAAS,cAAc;AACzC,aAAK,qBAAqB,SAAS,sBAAsB;AACzD,aAAK,MAAM;AACX,gBAAQ,IAAI,6CAA6C;AAAA,UACvD,YAAY,KAAK;AAAA,UACjB,oBAAoB,KAAK,qBAAqB;AAAA,QAChD,CAAC;AAAA,MACH;AAAA,MAEA,UAAgB;AACd,aAAK,UAAU;AACf,gBAAQ,IAAI,4CAA4C;AAAA,MAC1D;AAAA,MAEA,YAAqB;AACnB,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,QAAc;AACZ,aAAK,MAAM,MAAM;AACjB,aAAK,eAAe,CAAC;AACrB,aAAK,eAAe,YAAY,IAAI;AAAA,MACtC;AAAA,MAEQ,iBAAiB,KAAqB;AAC5C,cAAM,UAAU,IAAI,KAAK,EAAE,YAAY;AACvC,YAAI,QAAQ,WAAW,QAAQ,GAAG;AAEhC,gBAAM,QAAQ,IAAI,MAAM,yBAAyB;AACjD,iBAAO,QAAQ,UAAU,MAAM,CAAC,CAAC,KAAK;AAAA,QACxC;AACA,YAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,gBAAM,QAAQ,IAAI,MAAM,yBAAyB;AACjD,iBAAO,QAAQ,UAAU,MAAM,CAAC,CAAC,KAAK;AAAA,QACxC;AACA,YAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,gBAAM,QAAQ,IAAI,MAAM,2BAA2B;AACnD,iBAAO,QAAQ,UAAU,MAAM,CAAC,CAAC,KAAK;AAAA,QACxC;AACA,YAAI,QAAQ,WAAW,QAAQ,GAAG;AAChC,gBAAM,QAAQ,IAAI,MAAM,yBAAyB;AACjD,iBAAO,QAAQ,UAAU,MAAM,CAAC,CAAC,KAAK;AAAA,QACxC;AACA,YAAI,QAAQ,WAAW,OAAO,EAAG,QAAO;AACxC,YAAI,QAAQ,WAAW,QAAQ,EAAG,QAAO;AACzC,YAAI,QAAQ,WAAW,UAAU,EAAG,QAAO;AAC3C,YAAI,QAAQ,WAAW,QAAQ,EAAG,QAAO;AACzC,YAAI,QAAQ,WAAW,QAAQ,EAAG,QAAO;AACzC,eAAO;AAAA,MACT;AAAA,MAEA,YAAY,KAAa,YAAoB,WAAmB,SAAiB,UAAkB,OAAsB;AACvH,YAAI,CAAC,KAAK,QAAS;AAEnB,cAAM,WAAW,UAAU;AAC3B,cAAM,YAAY,KAAK,iBAAiB,GAAG;AAG3C,YAAI,OAAO,KAAK,MAAM,IAAI,SAAS;AACnC,YAAI,CAAC,MAAM;AACT,iBAAO,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,UAAU,OAAO,GAAG,QAAQ,EAAE;AACpE,eAAK,MAAM,IAAI,WAAW,IAAI;AAAA,QAChC;AACA,aAAK;AACL,aAAK,WAAW;AAChB,aAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,QAAQ;AAC1C,aAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,QAAQ;AAC1C,YAAI,MAAO,MAAK;AAGhB,cAAM,QAAoB,EAAE,KAAK,YAAY,WAAW,SAAS,UAAU,UAAU,MAAM;AAC3F,aAAK,aAAa,KAAK,KAAK;AAC5B,YAAI,KAAK,aAAa,SAAS,KAAK,iBAAiB;AACnD,eAAK,aAAa,MAAM;AAAA,QAC1B;AAGA,YAAI,YAAY,KAAK,oBAAoB;AACvC,kBAAQ,KAAK,6BAA6B,SAAS,QAAQ,CAAC,CAAC,QAAQ,SAAS,IAAI;AAAA,YAChF,KAAK,IAAI,UAAU,GAAG,GAAG;AAAA,YACzB;AAAA,YACA,UAAU,SAAS,QAAQ,CAAC,IAAI;AAAA,UAClC,CAAC;AAAA,QACH,WAAW,KAAK,YAAY;AAC1B,kBAAQ,IAAI,iBAAiB,SAAS,KAAK,SAAS,QAAQ,CAAC,CAAC,OAAO,QAAQ,QAAQ;AAAA,QACvF;AAAA,MACF;AAAA,MAEA,WAAyD;AACvD,cAAM,SAAuD,CAAC;AAC9D,mBAAW,CAAC,WAAW,IAAI,KAAK,KAAK,OAAO;AAC1C,iBAAO,SAAS,IAAI;AAAA,YAClB,GAAG;AAAA,YACH,OAAO,KAAK,QAAQ,IAAI,KAAK,UAAU,KAAK,QAAQ;AAAA,UACtD;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,MAEA,aASE;AACA,cAAM,QAAQ,KAAK,SAAS;AAC5B,YAAI,eAAe;AACnB,YAAI,cAAc;AAClB,YAAI,cAAc;AAClB,YAAI,SAAS;AAEb,cAAM,UAAkF,CAAC;AAEzF,mBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,0BAAgB,KAAK;AACrB,yBAAe,KAAK;AACpB,yBAAe,KAAK,aAAa;AAAA,YAAO,OACtC,KAAK,iBAAiB,EAAE,GAAG,MAAM,QAAQ,EAAE,YAAY,KAAK;AAAA,UAC9D,EAAE;AACF,oBAAU,KAAK;AACf,kBAAQ,KAAK,EAAE,MAAM,OAAO,KAAK,OAAO,SAAS,KAAK,SAAS,OAAO,KAAK,MAAM,CAAC;AAAA,QACpF;AAEA,eAAO;AAAA,UACL,iBAAiB,YAAY,IAAI,IAAI,KAAK;AAAA,UAC1C;AAAA,UACA;AAAA,UACA,YAAY,eAAe,IAAI,cAAc,eAAe;AAAA,UAC5D;AAAA,UACA;AAAA,UACA,YAAY,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,EAAE;AAAA,UACtE,WAAW,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,EAAE;AAAA,QAC3E;AAAA,MACF;AAAA,MAEA,gBAAgB,QAAQ,IAAkB;AACxC,eAAO,KAAK,aAAa,MAAM,CAAC,KAAK;AAAA,MACvC;AAAA,MAEA,cAAoB;AAClB,cAAM,UAAU,KAAK,WAAW;AAChC,gBAAQ,IAAI,mDAAmD;AAC/D,gBAAQ,IAAI,sBAAsB,QAAQ,kBAAkB,KAAM,QAAQ,CAAC,CAAC,GAAG;AAC/E,gBAAQ,IAAI,kBAAkB,QAAQ,YAAY,EAAE;AACpD,gBAAQ,IAAI,mBAAmB,QAAQ,YAAY,QAAQ,CAAC,CAAC,IAAI;AACjE,gBAAQ,IAAI,mBAAmB,QAAQ,WAAW,QAAQ,CAAC,CAAC,IAAI;AAChE,gBAAQ,IAAI,kBAAkB,KAAK,kBAAkB,QAAQ,QAAQ,WAAW,EAAE;AAClF,gBAAQ,IAAI,WAAW,QAAQ,MAAM,EAAE;AAEvC,gBAAQ,IAAI,wBAAwB;AACpC,mBAAW,SAAS,QAAQ,YAAY;AACtC,kBAAQ,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,WAAW,MAAM,QAAQ,QAAQ,CAAC,CAAC,aAAa,MAAM,MAAM,QAAQ,CAAC,CAAC,QAAQ;AAAA,QAC3H;AAEA,gBAAQ,IAAI,6BAA6B;AACzC,mBAAW,SAAS,QAAQ,WAAW;AACrC,kBAAQ,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,QAAQ,QAAQ,CAAC,CAAC,aAAa,MAAM,KAAK,WAAW,MAAM,MAAM,QAAQ,CAAC,CAAC,QAAQ;AAAA,QAC3H;AAEA,gBAAQ,IAAI,oDAAoD;AAAA,MAClE;AAAA,IACF;AAGA,IAAM,aAAa,IAAI,qBAAqB;AAAA;AAAA;;;AC3N5C;AAAA;AA8BA;AASA,QAAM,QAAQ,oBAAI,IAAyB;AAG3C,QAAM,gBAAgB,oBAAI,IAAoB;AAG9C,QAAI,sBAA6D;AAGjE,QAAM,0BAA0B;AAGhC,QAAM,8BAA8B;AAGpC,QAAI,aAAa;AAGjB,aAAS,iBAAyB;AAChC,aAAO,QAAQ,YAAY,IAAI,KAAK,IAAI,CAAC;AAAA,IAC3C;AAOA,QAAM,wBAAwB,oBAAI,IAAyB;AAG3D,QAAM,gBAAgB,oBAAI,IAAyB;AAQnD,QAAM,kBAAkB,oBAAI,IAAoB;AAGhD,QAAM,sBAAsB,oBAAI,IAAyB;AAKzD,aAAS,oBAAoB,QAAgB,QAAsB;AACjE,UAAI,CAAC,sBAAsB,IAAI,MAAM,GAAG;AACtC,8BAAsB,IAAI,QAAQ,oBAAI,IAAI,CAAC;AAAA,MAC7C;AACA,4BAAsB,IAAI,MAAM,EAAG,IAAI,MAAM;AAC7C,cAAQ,IAAI,wBAAwB,MAAM,2BAA2B,MAAM,EAAE;AAAA,IAC/E;AAKA,aAAS,wBAAwB,QAAgB,QAAsB;AACrE,YAAM,cAAc,sBAAsB,IAAI,MAAM;AACpD,UAAI,aAAa;AACf,oBAAY,OAAO,MAAM;AACzB,YAAI,YAAY,SAAS,GAAG;AAC1B,gCAAsB,OAAO,MAAM;AAAA,QACrC;AACA,gBAAQ,IAAI,wBAAwB,MAAM,+BAA+B,MAAM,EAAE;AAAA,MACnF;AAAA,IACF;AAKA,aAAS,qBAAqB,QAAgB,QAAsB;AAClE,UAAI,CAAC,cAAc,IAAI,MAAM,GAAG;AAC9B,sBAAc,IAAI,QAAQ,oBAAI,IAAI,CAAC;AAAA,MACrC;AACA,oBAAc,IAAI,MAAM,EAAG,IAAI,MAAM;AAAA,IACvC;AAKA,aAAS,uBAAuB,QAAgB,QAAyB;AACvE,YAAM,QAAQ,cAAc,IAAI,MAAM;AACtC,UAAI,OAAO;AACT,cAAM,OAAO,MAAM;AACnB,YAAI,MAAM,SAAS,GAAG;AACpB,wBAAc,OAAO,MAAM;AAC3B,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAgBA,aAAS,mBACP,kBACA,QACA,WACwD;AAExD,UAAI,gBAAgB,IAAI,gBAAgB,GAAG;AACzC,cAAM,iBAAiB,gBAAgB,IAAI,gBAAgB;AAG3D,YAAI,UAAU;AACd,cAAM,WAAW,cAAc,IAAI,cAAc;AACjD,YAAI,YAAY,SAAS,OAAO,GAAG;AAEjC,gBAAM,kBAAmB,KAAa;AACtC,cAAI,OAAO,oBAAoB,YAAY;AACzC,gBAAI;AACF,oBAAM,OAAO,gBAAgB,cAAc;AAC3C,wBAAU,SAAS,QAAQ,SAAS;AAAA,YACtC,QAAQ;AACN,wBAAU;AAAA,YACZ;AAAA,UACF,OAAO;AAEL,sBAAU;AAAA,UACZ;AAAA,QACF;AAGA,YAAI,CAAC,SAAS;AACZ,kBAAQ,KAAK,yCAAyC,gBAAgB,aAAa,cAAc,gBAAgB;AAEjH,gBAAM,aAAa,oBAAoB,IAAI,gBAAgB;AAC3D,cAAI,YAAY;AACd,uBAAW,OAAO,YAAY;AAC5B,sCAAwB,gBAAgB,GAAG;AAC3C,qCAAuB,gBAAgB,GAAG;AAAA,YAC5C;AAAA,UACF;AACA,0BAAgB,OAAO,gBAAgB;AACvC,8BAAoB,OAAO,gBAAgB;AAC3C,gCAAsB,OAAO,cAAc;AAC3C,wBAAc,OAAO,cAAc;AAAA,QAErC,OAAO;AAEL,cAAIC,SAAQ,oBAAoB,IAAI,gBAAgB;AACpD,cAAI,CAACA,QAAO;AACV,YAAAA,SAAQ,oBAAI,IAAI;AAChB,gCAAoB,IAAI,kBAAkBA,MAAK;AAAA,UACjD;AACA,UAAAA,OAAM,IAAI,MAAM;AAGhB,+BAAqB,gBAAgB,MAAM;AAG3C,8BAAoB,gBAAgB,MAAM;AAE1C,kBAAQ,IAAI,wBAAwB,MAAM,2BAA2B,gBAAgB,aAAa,cAAc,MAAMA,OAAM,IAAI,QAAQ;AAExI,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,WAAWA,OAAM;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAGA,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,YAAY,gBAAgB,mCAAmC;AAAA,MACjF;AAGA,YAAM,eAAgB,KAAa;AACnC,UAAI,OAAO,iBAAiB,YAAY;AACtC,cAAM,IAAI,MAAM,qCAAqC;AAAA,MACvD;AAEA,YAAM,SAAS,aAAa,SAAS;AACrC,UAAI,WAAW,GAAG;AAChB,cAAM,IAAI,MAAM,yCAAyC;AAAA,MAC3D;AAGA,sBAAgB,IAAI,kBAAkB,MAAM;AAC5C,YAAM,QAAQ,oBAAI,IAAY,CAAC,MAAM,CAAC;AACtC,0BAAoB,IAAI,kBAAkB,KAAK;AAG/C,2BAAqB,QAAQ,MAAM;AAGnC,0BAAoB,QAAQ,MAAM;AAElC,cAAQ,IAAI,wBAAwB,MAAM,2BAA2B,gBAAgB,aAAa,MAAM,GAAG;AAE3G,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,QACR,WAAW;AAAA,MACb;AAAA,IACF;AAUA,aAAS,sBACP,kBACA,QACiE;AACjE,YAAM,SAAS,gBAAgB,IAAI,gBAAgB;AAEnD,UAAI,WAAW,QAAW;AACxB,eAAO,EAAE,OAAO,OAAO,UAAU,KAAK;AAAA,MACxC;AAGA,YAAM,QAAQ,oBAAoB,IAAI,gBAAgB;AACtD,UAAI,OAAO;AACT,cAAM,OAAO,MAAM;AAGnB,gCAAwB,QAAQ,MAAM;AAGtC,+BAAuB,QAAQ,MAAM;AAGrC,YAAI,MAAM,SAAS,GAAG;AACpB,kBAAQ,IAAI,2CAA2C,gBAAgB,aAAa,MAAM,mBAAmB;AAG7G,cAAI;AACF,kBAAM,eAAgB,KAAa;AACnC,gBAAI,OAAO,iBAAiB,YAAY;AACtC,2BAAa,MAAM;AAAA,YACrB;AAAA,UACF,SAAS,OAAO;AACd,oBAAQ,MAAM,0CAA0C,MAAM,KAAK,KAAK;AAAA,UAC1E;AAGA,0BAAgB,OAAO,gBAAgB;AACvC,8BAAoB,OAAO,gBAAgB;AAC3C,gCAAsB,OAAO,MAAM;AAEnC,iBAAO,EAAE,OAAO,KAAK;AAAA,QACvB;AAEA,gBAAQ,IAAI,wBAAwB,MAAM,6BAA6B,gBAAgB,KAAK,MAAM,IAAI,kBAAkB;AACxH,eAAO,EAAE,OAAO,OAAO,gBAAgB,MAAM,KAAK;AAAA,MACpD;AAEA,aAAO,EAAE,OAAO,OAAO,UAAU,KAAK;AAAA,IACxC;AAQA,aAAS,iBAAiB,kBAAmC;AAC3D,aAAO,gBAAgB,IAAI,gBAAgB;AAAA,IAC7C;AAQA,aAAS,qBAAqB,kBAA8C;AAC1E,aAAO,gBAAgB,IAAI,gBAAgB;AAAA,IAC7C;AAUA,aAAS,yBACP,kBACA,QACA,QACM;AACN,YAAM,SAAS,gBAAgB,IAAI,gBAAgB;AAEnD,UAAI,WAAW,QAAW;AACxB;AAAA,MACF;AAEA,YAAM,QAAQ,oBAAoB,IAAI,gBAAgB;AACtD,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AAGA,iBAAW,cAAc,OAAO;AAC9B,YAAI,eAAe,QAAQ;AACzB,gBAAM,OAAO,MAAM,IAAI,UAAU;AACjC,cAAI,MAAM;AACR,gBAAI;AACF,mBAAK,YAAY;AAAA,gBACf,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACA,iBAAiB;AAAA,cACnB,CAAC;AACD,sBAAQ,IAAI,iCAAiC,UAAU,8BAA8B,gBAAgB,EAAE;AAAA,YACzG,SAAS,OAAO;AACd,sBAAQ,MAAM,wCAAwC,UAAU,KAAK,KAAK;AAAA,YAC5E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAKA,aAAS,YAAY,QAAsB;AACzC,cAAQ,IAAI,oCAAoC,MAAM,EAAE;AAGxD,iBAAW,CAAC,QAAQ,WAAW,KAAK,uBAAuB;AACzD,oBAAY,OAAO,MAAM;AACzB,YAAI,YAAY,SAAS,GAAG;AAC1B,gCAAsB,OAAO,MAAM;AAAA,QACrC;AAAA,MACF;AAGA,iBAAW,CAAC,kBAAkB,KAAK,KAAK,qBAAqB;AAC3D,YAAI,MAAM,IAAI,MAAM,GAAG;AACrB,gBAAM,OAAO,MAAM;AAGnB,cAAI,MAAM,SAAS,GAAG;AACpB,kBAAM,SAAS,gBAAgB,IAAI,gBAAgB;AACnD,gBAAI,WAAW,QAAW;AACxB,sBAAQ,IAAI,2CAA2C,gBAAgB,aAAa,MAAM,YAAY,MAAM,gBAAgB;AAC5H,kBAAI;AACF,sBAAM,eAAgB,KAAa;AACnC,oBAAI,OAAO,iBAAiB,YAAY;AACtC,+BAAa,MAAM;AAAA,gBACrB;AAAA,cACF,SAAS,OAAO;AACd,wBAAQ,MAAM,0CAA0C,MAAM,KAAK,KAAK;AAAA,cAC1E;AACA,8BAAgB,OAAO,gBAAgB;AACvC,4BAAc,OAAO,MAAM;AAAA,YAC7B;AACA,gCAAoB,OAAO,gBAAgB;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAGA,iBAAW,CAAC,QAAQ,KAAK,KAAK,eAAe;AAC3C,cAAM,OAAO,MAAM;AACnB,YAAI,MAAM,SAAS,GAAG;AAEpB,cAAI,WAAW;AACf,qBAAW,CAAC,EAAE,YAAY,KAAK,iBAAiB;AAC9C,gBAAI,iBAAiB,QAAQ;AAC3B,yBAAW;AACX;AAAA,YACF;AAAA,UACF;AAEA,cAAI,CAAC,UAAU;AAEb,oBAAQ,IAAI,+CAA+C,MAAM,kBAAkB;AACnF,gBAAI;AACF,oBAAM,eAAgB,KAAa;AACnC,kBAAI,OAAO,iBAAiB,YAAY;AACtC,6BAAa,MAAM;AAAA,cACrB;AAAA,YACF,SAAS,OAAO;AACd,sBAAQ,MAAM,0CAA0C,MAAM,KAAK,KAAK;AAAA,YAC1E;AAAA,UACF;AACA,wBAAc,OAAO,MAAM;AAAA,QAC7B;AAAA,MACF;AAGA,oBAAc,OAAO,MAAM;AAG3B,YAAM,OAAO,MAAM;AAGnB,UAAI,MAAM,SAAS,KAAK,qBAAqB;AAC3C,sBAAc,mBAAmB;AACjC,8BAAsB;AAAA,MACxB;AAAA,IACF;AAOA,aAAS,qBAA2B;AAClC,YAAM,MAAM,KAAK,IAAI;AAErB,YAAM,aAAuB,CAAC;AAC9B,iBAAW,CAAC,QAAQ,QAAQ,KAAK,eAAe;AAC9C,YAAI,MAAM,YAAY,yBAAyB;AAC7C,qBAAW,KAAK,MAAM;AAAA,QACxB;AAAA,MACF;AACA,iBAAW,UAAU,YAAY;AAC/B,gBAAQ,IAAI,wBAAwB,MAAM,4BAA4B,uBAAuB,kBAAkB;AAC/G,oBAAY,MAAM;AAAA,MACpB;AAAA,IACF;AASA,aAAS,uBAAuB,QAAgB,WAAmB,QAAuB;AACxF,YAAM,cAAc,sBAAsB,IAAI,MAAM;AACpD,cAAQ,IAAI,wDAAwD,MAAM,cAAc,SAAS,oBAAoB,aAAa,QAAQ,CAAC,EAAE;AAC7I,UAAI,CAAC,eAAe,YAAY,SAAS,GAAG;AAC1C,gBAAQ,IAAI,+CAA+C,MAAM,uBAAuB;AACxF;AAAA,MACF;AAEA,YAAM,UAAkC;AAAA,QACtC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,aAAa;AAAA,MACf;AAEA,iBAAW,UAAU,aAAa;AAChC,cAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,YAAI,MAAM;AACR,cAAI;AACF,oBAAQ,IAAI,6CAA6C,MAAM,EAAE;AACjE,iBAAK,YAAY,OAAO;AACxB,oBAAQ,IAAI,4CAA4C,MAAM,eAAe;AAAA,UAC/E,SAAS,OAAO;AACd,oBAAQ,MAAM,yCAAyC,MAAM,KAAK,KAAK;AAAA,UACzE;AAAA,QACF,OAAO;AACL,kBAAQ,KAAK,wBAAwB,MAAM,4CAA4C;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAKA,aAAS,eAAe,SAAwB;AAC9C,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO;AAClC,YAAI;AACF,eAAK,YAAY,OAAO;AAAA,QAC1B,SAAS,OAAO;AACd,kBAAQ,MAAM,yCAAyC,MAAM,KAAK,KAAK;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAMA,QAAI,cAAc;AAClB,QAAI,cAAoC;AACxC,QAAI,SAAuB,CAAC;AAc5B,aAAS,uBAA6B;AAEpC,YAAM,eAAe;AAAA,QACnB,kBAAkB,CAAC,MAAc,YAA2B;AAE1D,kBAAQ,IAAI,kDAAkD,IAAI,6BAA6B;AAAA,QACjG;AAAA,QACA,qBAAqB,CAAC,MAAc,YAA2B;AAAA,QAE/D;AAAA,QACA,eAAe,CAAC,UAAiB;AAE/B,cAAI,EAAE,iBAAiB,cAAc;AACnC,mBAAO;AAAA,UACT;AAEA,gBAAM,YAAY,MAAM;AACxB,gBAAM,YAAY,MAAM;AAGxB,cAAI;AACJ,cAAI;AACF,2BAAe,OAAO,cAAc,WAAW,KAAK,MAAM,SAAS,IAAI;AAAA,UACzE,SAAS,GAAG;AACV,oBAAQ,KAAK,mCAAmC,SAAS,YAAY,CAAC;AACtE,2BAAe;AAAA,UACjB;AAEA,gBAAM,SAAS,cAAc;AAC7B,kBAAQ,IAAI,kCAAkC,SAAS,IAAI,EAAE,QAAQ,WAAW,cAAc,UAAU,CAAC;AAEzG,cAAI,WAAW,QAAW;AAGxB,mCAAuB,QAAQ,WAAW,YAAY;AAAA,UACxD,OAAO;AAEL,2BAAe;AAAA,cACb,MAAM;AAAA,cACN;AAAA,cACA,QAAQ;AAAA,YACV,CAA2B;AAAA,UAC7B;AAEA,iBAAO;AAAA,QACT;AAAA,QACA,eAAe,MAAM;AAAA,QACrB,MAAM;AAAA,QACN,iBAAiB;AAAA,MACnB;AAEA,MAAC,KAAa,WAAW;AAEzB,cAAQ,IAAI,uEAAuE;AAAA,IACrF;AAMA,mBAAe,kBAAiC;AAC9C,YAAM,WAAW;AACjB,YAAM,aAAa;AAEnB,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,QAAQ;AACrC,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,gCAAgC,SAAS,UAAU,EAAE;AAAA,QACvE;AACA,cAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,cAAM,cAAc;AAAA;AAAA,UAEd,IAAI;AAAA;AAAA;AAAA;AAMV,cAAM,gBAAgB,KAAK,WAAW;AACtC,cAAM,aAAa,EAAE,SAAS,CAAC,EAAS;AACxC,cAAM,YAAY,cAAc,YAAY,WAAW,OAAO;AAE9D,YAAI,OAAO,cAAc,YAAY;AACnC,gBAAM,IAAI,MAAM,+CAA+C;AAAA,QACjE;AAEA,cAAM,YAAY;AAAA,UAChB,YAAY,MAAM;AAAA,QACpB;AAEA,cAAM,MAAM,MAAM,UAAU,SAAS;AACrC,uBAAe,GAAG;AAClB,8BAAsB;AAGtB,QAAC,KAAa,eAAe,CAAC,UAA8B;AAC1D,gBAAM,SAAS,aAAa,KAAK;AACjC,cAAI,WAAW,GAAG;AAChB,oBAAQ,MAAM,yCAAyC;AACvD,mBAAO;AAAA,UACT;AACA,iBAAQ,KAAa,yBAAyB,MAAM;AAAA,QACtD;AAEA,gBAAQ,IAAI,sDAAsD;AAAA,MACpE,SAAS,OAAO;AACd,gBAAQ,MAAM,gDAAgD,KAAK;AACnE,cAAM,IAAI,MAAM,gCAAgC,KAAK,EAAE;AAAA,MACzD;AAAA,IACF;AAEA,mBAAe,eAA8B;AAC3C,UAAK,KAAa,IAAI;AACpB;AAAA,MACF;AAEA,YAAM,UAAU,OAAO,eAAe,KAAK,SAAS;AACpD,YAAM,cAAc,GAAG,OAAO;AAE9B,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,WAAW;AACxC,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,iCAAiC,SAAS,UAAU,EAAE;AAAA,QACxE;AACA,cAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,aAAK,IAAI;AACT,gBAAQ,IAAI,qCAAqC;AAAA,MACnD,SAAS,OAAO;AACd,cAAM,IAAI,MAAM,gCAAgC,KAAK,EAAE;AAAA,MACzD;AAAA,IACF;AAEA,mBAAe,aAA4B;AACzC,YAAMC,WAAU,OAAO,eAAe,KAAK,SAAS;AAEpD,YAAM,eAAe,OAAO,cAAc,MAAM,OAAO,WAAW,KAAK;AACvE,YAAM,UAAU,GAAGA,QAAO,eAAe,YAAY;AAErD,YAAMC,YAAW,MAAM,MAAM,OAAO;AACpC,UAAI,CAACA,UAAS,IAAI;AAChB,cAAM,IAAI,MAAM,gCAAgCA,UAAS,UAAU,EAAE;AAAA,MACvE;AACA,YAAM,YAAY,MAAMA,UAAS,YAAY;AAE7C,YAAM,KAAK,IAAK,KAAa,GAAG;AAChC,YAAM,SAAS,MAAM,YAAY,YAAY,WAAW,GAAG,YAAY;AACvE,SAAG,IAAI,OAAO,QAAQ;AAEtB,YAAM,WAAW,OAAO,YAAY;AACpC,UAAK,KAAa,oBAAoB;AACpC,QAAC,KAAa,mBAAmB,QAAQ;AAAA,MAC3C;AAEA,cAAQ,IAAI,gCAAgC;AAAA,IAC9C;AAEA,mBAAe,WAAW,cAA4C;AACpE,UAAI,aAAa;AACf;AAAA,MACF;AAEA,UAAI,aAAa;AACf,eAAO;AAAA,MACT;AAEA,eAAS,gBAAgB,CAAC;AAE1B,qBAAe,YAAY;AACzB,YAAI;AACF,+BAAqB;AACrB,gBAAM,gBAAgB;AACtB,gBAAM,aAAa;AACnB,gBAAM,WAAW;AACjB,wBAAc;AACd,kBAAQ,IAAI,+CAA+C;AAAA,QAC7D,SAAS,OAAO;AACd,kBAAQ,MAAM,0CAA0C,KAAK;AAC7D,gBAAM;AAAA,QACR;AAAA,MACF,GAAG;AAEH,aAAO;AAAA,IACT;AASA,aAAS,WAAW,SAAoD;AACtE,YAAM,EAAE,IAAI,QAAQ,MAAM,OAAO,IAAI;AAErC,UAAI;AACF,cAAM,KAAM,KAAa,MAAM;AAC/B,YAAI,OAAO,OAAO,YAAY;AAC5B,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA,SAAS;AAAA,YACT,OAAO,aAAa,MAAM;AAAA,UAC5B;AAAA,QACF;AAEA,cAAM,SAAS,GAAG,GAAI,QAAQ,CAAC,CAAE;AAGjC,YAAI,WAAW,oBAAoB,WAAW,4BAC1C,WAAW,4BAA4B,WAAW,iCAClD,WAAW,gBAAgB;AAC7B,cAAI,OAAO,WAAW,YAAY,SAAS,GAAG;AAC5C,iCAAqB,QAAQ,MAAM;AAAA,UACrC;AAAA,QACF;AAGA,YAAI,WAAW,kBAAkB,QAAQ,KAAK,SAAS,GAAG;AACxD,gBAAM,SAAS,KAAK,CAAC;AACrB,gBAAM,aAAa,uBAAuB,QAAQ,MAAM;AACxD,cAAI,CAAC,YAAY;AAEf,mBAAO,EAAE,IAAI,QAAQ,SAAS,MAAM,QAAQ,OAAU;AAAA,UACxD;AAAA,QACF;AAEA,eAAO,EAAE,IAAI,QAAQ,SAAS,MAAM,OAAO;AAAA,MAC7C,SAAS,OAAO;AACd,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,SAAS;AAAA,UACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAKA,aAAS,kBAAkB,QAAgB,MAAmB,OAAuD;AACnH,YAAM,OAAO,MAAM;AAGnB,UAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ;AAC1C,SAAC,YAAY;AACX,cAAI;AACF,kBAAM,WAAW,KAAK,MAAM;AAC5B,kBAAM,eAAyC,EAAE,MAAM,SAAS,OAAO;AACvE,iBAAK,YAAY,YAAY;AAAA,UAC/B,SAAS,OAAO;AACd,kBAAM,eAAmC;AAAA,cACvC,MAAM;AAAA,cACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC9D;AACA,iBAAK,YAAY,YAAY;AAAA,UAC/B;AAAA,QACF,GAAG;AACH;AAAA,MACF;AAGA,UAAI,UAAU,QAAQ,KAAK,SAAS,aAAa;AAC/C,4BAAoB,KAAK,QAAQ,MAAM;AACvC;AAAA,MACF;AAEA,UAAI,UAAU,QAAQ,KAAK,SAAS,eAAe;AACjD,gCAAwB,KAAK,QAAQ,MAAM;AAC3C;AAAA,MACF;AAGA,UAAI,UAAU,QAAQ,KAAK,SAAS,sBAAsB;AACxD,cAAM,EAAE,kBAAkB,WAAW,UAAU,IAAI;AACnD,YAAI,CAAC,aAAa;AAChB,eAAK,YAAY;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO;AAAA,YACP,aAAa;AAAA,YACb;AAAA,UACF,CAAC;AACD;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,SAAS,mBAAmB,kBAAkB,QAAQ,SAAS;AACrE,eAAK,YAAY;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa;AAAA,YACb;AAAA,YACA,GAAG;AAAA,UACL,CAAC;AAAA,QACH,SAAS,OAAO;AACd,eAAK,YAAY;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,aAAa;AAAA,YACb;AAAA,UACF,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,UAAU,QAAQ,KAAK,SAAS,yBAAyB;AAC3D,cAAM,EAAE,kBAAkB,UAAU,IAAI;AACxC,YAAI;AACF,gBAAM,SAAS,sBAAsB,kBAAkB,MAAM;AAC7D,eAAK,YAAY;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa;AAAA,YACb;AAAA,YACA,GAAG;AAAA,UACL,CAAC;AAAA,QACH,SAAS,OAAO;AACd,eAAK,YAAY;AAAA,YACf,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,aAAa;AAAA,YACb;AAAA,UACF,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI,UAAU,QAAQ,KAAK,SAAS,oBAAoB;AACtD,cAAM,EAAE,kBAAkB,UAAU,IAAI;AACxC,cAAM,SAAS,iBAAiB,gBAAgB;AAChD,cAAM,SAAS,qBAAqB,gBAAgB;AACpD,aAAK,YAAY;AAAA,UACf,MAAM;AAAA,UACN,SAAS;AAAA,UACT,aAAa;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAEA,UAAI,UAAU,QAAQ,KAAK,SAAS,4BAA4B;AAC9D,cAAM,EAAE,kBAAkB,QAAQ,UAAU,IAAI;AAChD,iCAAyB,kBAAkB,QAAQ,UAAU,QAAQ;AACrE,aAAK,YAAY;AAAA,UACf,MAAM;AAAA,UACN,SAAS;AAAA,UACT,aAAa;AAAA,UACb;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAGA,UAAI,UAAU,QAAQ,KAAK,SAAS,aAAa;AAC/C,sBAAc,IAAI,QAAQ,KAAK,IAAI,CAAC;AACpC;AAAA,MACF;AAGA,UAAI,UAAU,QAAQ,KAAK,SAAS,cAAc;AAChD,gBAAQ,IAAI,wBAAwB,MAAM,uCAAuC;AACjF,oBAAY,MAAM;AAClB;AAAA,MACF;AAGA,UAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ;AAC1C,YAAI,CAAC,aAAa;AAChB,gBAAMA,YAAiC;AAAA,YACrC,IAAK,KAA6B;AAAA,YAClC;AAAA,YACA,SAAS;AAAA,YACT,OAAO;AAAA,UACT;AACA,eAAK,YAAYA,SAAQ;AACzB;AAAA,QACF;AAGA,cAAM,UAAU,EAAE,GAAG,MAAM,OAAO;AAClC,cAAMA,YAAW,WAAW,OAAO;AACnC,aAAK,YAAYA,SAAQ;AAAA,MAC3B;AAAA,IACF;AAMA,SAAK,YAAY,CAAC,UAAwB;AACxC,YAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,YAAM,SAAS,eAAe;AAE9B,cAAQ,IAAI,uCAAuC,MAAM,EAAE;AAC3D,YAAM,IAAI,QAAQ,IAAI;AACtB,oBAAc,IAAI,QAAQ,KAAK,IAAI,CAAC;AAGpC,WAAK,YAAY,CAAC,MAAM,kBAAkB,QAAQ,MAAM,CAAC;AAIzD,WAAK,iBAAiB,MAAM;AAC1B,gBAAQ,IAAI,wBAAwB,MAAM,6BAA6B;AACvE,oBAAY,MAAM;AAAA,MACpB;AAGA,WAAK,MAAM;AAGX,UAAI,CAAC,qBAAqB;AACxB,8BAAsB,YAAY,oBAAoB,2BAA2B;AAAA,MACnF;AAGA,UAAI,aAAa;AACf,cAAM,eAAyC,EAAE,MAAM,SAAS,OAAO;AACvE,aAAK,YAAY,YAAY;AAAA,MAC/B;AAGA,WAAK,YAAY,EAAE,MAAM,aAAa,OAAO,CAAC;AAAA,IAChD;AAGA,YAAQ,IAAI,2DAA2D;AAAA;AAAA;",
|
|
6
6
|
"names": ["binary", "SQL", "users", "baseUrl", "response"]
|
|
7
7
|
}
|
package/dist/kodexa.wasm
CHANGED
|
Binary file
|
package/dist/wasm/types.d.ts
CHANGED
|
@@ -235,7 +235,6 @@ export interface Tag {
|
|
|
235
235
|
confidence?: number;
|
|
236
236
|
groupId?: number;
|
|
237
237
|
parentGroupId?: number;
|
|
238
|
-
cellIndex?: number;
|
|
239
238
|
index?: number;
|
|
240
239
|
note?: string;
|
|
241
240
|
status?: string;
|
|
@@ -248,7 +247,6 @@ export interface TagOptions {
|
|
|
248
247
|
confidence?: number;
|
|
249
248
|
groupId?: number;
|
|
250
249
|
parentGroupId?: number;
|
|
251
|
-
cellIndex?: number;
|
|
252
250
|
[key: string]: any;
|
|
253
251
|
}
|
|
254
252
|
export interface Taxonomy {
|