-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnative.js
More file actions
162 lines (137 loc) · 5.52 KB
/
native.js
File metadata and controls
162 lines (137 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
const koffi = require('koffi');
const path = require('path');
const fs = require('fs');
// Determine library filename based on platform
function getLibraryName() {
switch (process.platform) {
case 'win32':
return 'cqlai.dll';
case 'darwin':
return 'libcqlai.dylib';
default:
return 'libcqlai.so';
}
}
// Determine library path, handling Electron ASAR unpacking
function getLibraryPath() {
const libName = getLibraryName();
let libPath = path.join(__dirname, 'lib', libName);
// Handle Electron ASAR: unpacked files are at .asar.unpacked instead of .asar
if (libPath.includes('.asar') && !libPath.includes('.asar.unpacked')) {
const unpackedPath = libPath.replace('.asar', '.asar.unpacked');
if (fs.existsSync(unpackedPath)) {
return unpackedPath;
}
}
return libPath;
}
const libPath = getLibraryPath();
// Load the native library
const lib = koffi.load(libPath);
// Define function signatures
const native = {
// Session management
CreateSession: lib.func('char* CreateSession(const char* optionsJSON)'),
CloseSession: lib.func('char* CloseSession(int handle)'),
// Connection test
TestConnection: lib.func('char* TestConnection(const char* optionsJSON)'),
TestConnectionWithID: lib.func('char* TestConnectionWithID(const char* optionsJSON)'),
CancelTestConnection: lib.func('char* CancelTestConnection(const char* requestID)'),
// Query execution
ExecuteQuery: lib.func('char* ExecuteQuery(int handle, const char* query)'),
ExecuteMultiQuery: lib.func('char* ExecuteMultiQuery(int handle, const char* query, const char* optionsJSON)'),
// CQL parsing
SplitCQL: lib.func('char* SplitCQL(const char* cql)'),
// Paged query execution (iterator-based pagination)
ExecuteQueryPaged: lib.func('char* ExecuteQueryPaged(int handle, const char* query)'),
FetchNextPage: lib.func('char* FetchNextPage(int handle, const char* queryID)'),
CancelPagedQuery: lib.func('char* CancelPagedQuery(int handle, const char* queryID)'),
CancelQuery: lib.func('char* CancelQuery(int handle)'),
// Session configuration
SetConsistency: lib.func('char* SetConsistency(int handle, const char* level)'),
SetKeyspace: lib.func('char* SetKeyspace(int handle, const char* keyspace)'),
SetPaging: lib.func('char* SetPaging(int handle, const char* value)'),
SetTracing: lib.func('char* SetTracing(int handle, int enabled)'),
SetExpand: lib.func('char* SetExpand(int handle, int enabled)'),
GetSessionInfo: lib.func('char* GetSessionInfo(int handle)'),
// Metadata
GetClusterMetadata: lib.func('char* GetClusterMetadata(int handle)'),
// DDL Generation
GetDDL: lib.func('char* GetDDL(int handle, const char* scope)'),
// TLS Security
CheckTLS: lib.func('char* CheckTLS(const char* optionsJSON)'),
// RSA Decryption (for standalone use - normally handled automatically in connect)
DecryptCredential: lib.func('char* DecryptCredential(const char* optionsJSON)'),
// Astra Secure Bundle
ParseAstraSecureBundle: lib.func('char* ParseAstraSecureBundle(const char* optionsJSON)'),
ValidateAstraSecureBundle: lib.func('char* ValidateAstraSecureBundle(const char* bundlePath)'),
CreateAstraSession: lib.func('char* CreateAstraSession(const char* optionsJSON)'),
TestAstraConnectionWithID: lib.func('char* TestAstraConnectionWithID(const char* optionsJSON)'),
CleanupAstraExtracted: lib.func('char* CleanupAstraExtracted(const char* extractedDir)'),
// COPY TO/FROM (CSV export/import)
CopyTo: lib.func('char* CopyTo(int handle, const char* paramsJSON)'),
CopyFrom: lib.func('char* CopyFrom(int handle, const char* paramsJSON)'),
// Source file execution (CQL files)
ExecuteSourceFiles: lib.func('char* ExecuteSourceFiles(int handle, const char* optionsJSON)'),
GetSourceProgress: lib.func('char* GetSourceProgress(int handle)'),
StopSourceExecution: lib.func('char* StopSourceExecution(int handle)'),
// Query tracing
GetQueryTrace: lib.func('char* GetQueryTrace(int handle, const char* sessionID)'),
// Memory management
FreeString: lib.func('void FreeString(char* str)'),
};
/**
* Call a native function synchronously and parse the JSON response
*/
function callNative(fn) {
const resultStr = fn();
const result = JSON.parse(resultStr);
return result;
}
/**
* Call a native function asynchronously using koffi's worker thread
* This is truly non-blocking - runs in a separate thread
*/
function callNativeAsync(fn) {
return new Promise((resolve, reject) => {
// Get the function reference and arguments from the closure
// We need to call the function's .async method with a callback
try {
const resultStr = fn();
const result = JSON.parse(resultStr);
resolve(result);
} catch (err) {
reject(err);
}
});
}
/**
* Call a native function truly asynchronously using koffi's async mode
* This runs in a worker thread and doesn't block the event loop
* @param {Function} nativeFunc - The native function to call
* @param {...any} args - Arguments to pass to the function
* @returns {Promise<Object>} Parsed JSON result
*/
function callNativeTrueAsync(nativeFunc, ...args) {
return new Promise((resolve, reject) => {
// koffi's .async() method runs the call in a worker thread
nativeFunc.async(...args, (err, resultStr) => {
if (err) {
reject(err);
return;
}
try {
const result = JSON.parse(resultStr);
resolve(result);
} catch (parseErr) {
reject(parseErr);
}
});
});
}
module.exports = {
native,
callNative,
callNativeAsync,
callNativeTrueAsync,
};