@ladybugdb/core-linux-arm64 0.15.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022-2025 Kùzu Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,69 @@
1
+ <div align="center">
2
+ <picture>
3
+ <!-- <source srcset="https://ladybugdb.com/img/lbug-logo-dark.png" media="(prefers-color-scheme: dark)"> -->
4
+ <img src="https://ladybugdb.com/logo.png" height="100" alt="Ladybug Logo">
5
+ </picture>
6
+ </div>
7
+
8
+ <br>
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/LadybugDB/ladybug/actions">
12
+ <img src="https://github.com/LadybugDB/ladybug/actions/workflows/ci-workflow.yml/badge.svg?branch=master" alt="Github Actions Badge"></a>
13
+ <a href="https://discord.com/invite/hXyHmvW3Vy">
14
+ <img src="https://img.shields.io/discord/1162999022819225631?logo=discord" alt="discord" /></a>
15
+ <a href="https://twitter.com/lbugdb">
16
+ <img src="https://img.shields.io/badge/follow-@lbugdb-1DA1F2?logo=twitter" alt="twitter"></a>
17
+ </p>
18
+
19
+ # Ladybug
20
+ Ladybug is an embedded graph database built for query speed and scalability. Ladybug is optimized for handling complex analytical workloads
21
+ on very large databases and provides a set of retrieval features, such as a full text search and vector indices. Our core feature set includes:
22
+
23
+ - Flexible Property Graph Data Model and Cypher query language
24
+ - Embeddable, serverless integration into applications
25
+ - Native full text search and vector index
26
+ - Columnar disk-based storage
27
+ - Columnar sparse row-based (CSR) adjacency list/join indices
28
+ - Vectorized and factorized query processor
29
+ - Novel and very fast join algorithms
30
+ - Multi-core query parallelism
31
+ - Serializable ACID transactions
32
+ - Wasm (WebAssembly) bindings for fast, secure execution in the browser
33
+
34
+ Ladybug is being developed by [LadybugDB Developers](https://github.com/LadybugDB) and
35
+ is available under a permissive license. So try it out and help us make it better! We welcome your feedback and feature requests.
36
+
37
+ The database was formerly known as [Kuzu](https://github.com/kuzudb/kuzu).
38
+
39
+ ## Installation
40
+
41
+ | Language | Installation |
42
+ | -------- |------------------------------------------------------------------------|
43
+ | Python | `pip install real_ladybug` |
44
+ | NodeJS | `npm install @ladybug/core` |
45
+ | Rust | `cargo add lbug` |
46
+ | Go | `go get github.com/lbugdb/go-ladybug` |
47
+ | Swift | [lbug-swift](https://github.com/lbugdb/swift-ladybug) |
48
+ | Java | [Maven Central](https://central.sonatype.com/artifact/com.ladybugdb/lbug) |
49
+ | C/C++ | [precompiled binaries](https://github.com/LadybugDB/ladybug/releases/latest) |
50
+ | CLI | [precompiled binaries](https://github.com/LadybugDB/ladybug/releases/latest) |
51
+
52
+ To learn more about installation, see our [Installation](https://docs.ladybugdb.com/installation) page.
53
+
54
+ ## Getting Started
55
+
56
+ Refer to our [Getting Started](https://docs.ladybugdb.com/get-started/) page for your first example.
57
+
58
+ ## Build from Source
59
+
60
+ You can build from source using the instructions provided in the [developer guide](https://docs.ladybugdb.com/developer-guide/).
61
+
62
+ ## Contributing
63
+ We welcome contributions to Ladybug. If you are interested in contributing to Ladybug, please read our [Contributing Guide](CONTRIBUTING.md).
64
+
65
+ ## License
66
+ By contributing to Ladybug, you agree that your contributions will be licensed under the [MIT License](LICENSE).
67
+
68
+ ## Contact
69
+ You can contact us at [social@ladybugdb.com](mailto:social@ladybugdb.com) or [join our Discord community](https://discord.com/invite/hXyHmvW3Vy).
package/connection.js ADDED
@@ -0,0 +1,471 @@
1
+ "use strict";
2
+
3
+ const LbugNative = require("./lbug_native.js");
4
+ const QueryResult = require("./query_result.js");
5
+ const PreparedStatement = require("./prepared_statement.js");
6
+
7
+ class Connection {
8
+ /**
9
+ * Initialize a new Connection object. Note that the initialization is done
10
+ * lazily, so the connection is not initialized until the first query is
11
+ * executed. To initialize the connection immediately, call the `init()`
12
+ * function on the returned object.
13
+ *
14
+ * @param {lbug.Database} database the database object to connect to.
15
+ * @param {Number} numThreads the maximum number of threads to use for query execution.
16
+ */
17
+ constructor(database, numThreads = null) {
18
+ if (
19
+ typeof database !== "object" ||
20
+ database.constructor.name !== "Database"
21
+ ) {
22
+ throw new Error("database must be a valid Database object.");
23
+ }
24
+ this._database = database;
25
+ this._connection = null;
26
+ this._isInitialized = false;
27
+ this._initPromise = null;
28
+ this._isClosed = false;
29
+ numThreads = parseInt(numThreads);
30
+ if (numThreads && numThreads > 0) {
31
+ this._numThreads = numThreads;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Initialize the connection. Calling this function is optional, as the
37
+ * connection is initialized automatically when the first query is executed.
38
+ */
39
+ async init() {
40
+ if (this._isClosed) {
41
+ throw new Error("Connection is closed.");
42
+ }
43
+ if (!this._isInitialized) {
44
+ if (!this._initPromise) {
45
+ if (!this._connection) {
46
+ const database = await this._database._getDatabase();
47
+ this._connection = new LbugNative.NodeConnection(database);
48
+ }
49
+ this._initPromise = new Promise((resolve, reject) => {
50
+ this._connection.initAsync((err) => {
51
+ if (err) {
52
+ reject(err);
53
+ } else {
54
+ this._isInitialized = true;
55
+ if (this._numThreads) {
56
+ this._connection.setMaxNumThreadForExec(this._numThreads);
57
+ }
58
+ if (this._queryTimeout) {
59
+ this._connection.setQueryTimeout(this._queryTimeout);
60
+ }
61
+ resolve();
62
+ }
63
+ });
64
+ });
65
+ }
66
+ await this._initPromise;
67
+ this._initPromise = null;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Initialize the connection synchronously. Calling this function is optional, as the
73
+ * connection is initialized automatically when the first query is executed. This function
74
+ * may block the main thread, so use it with caution.
75
+ */
76
+ initSync() {
77
+ if (this._isClosed) {
78
+ throw new Error("Connection is closed.");
79
+ }
80
+ if (this._isInitialized) {
81
+ return;
82
+ }
83
+ if (this._initPromise) {
84
+ throw new Error("There is an ongoing asynchronous initialization. Please wait for it to finish.");
85
+ }
86
+ if (!this._connection) {
87
+ const database = this._database._getDatabaseSync();
88
+ this._connection = new LbugNative.NodeConnection(database);
89
+ }
90
+ this._connection.initSync();
91
+ this._isInitialized = true;
92
+ }
93
+
94
+ /**
95
+ * Internal function to get the underlying native connection object.
96
+ * @returns {LbugNative.NodeConnection} the underlying native connection.
97
+ * @throws {Error} if the connection is closed.
98
+ */
99
+ async _getConnection() {
100
+ if (this._isClosed) {
101
+ throw new Error("Connection is closed.");
102
+ }
103
+ await this.init();
104
+ return this._connection;
105
+ }
106
+
107
+ /**
108
+ * Internal function to get the underlying native connection object synchronously.
109
+ * @returns {LbugNative.NodeConnection} the underlying native connection.
110
+ * @throws {Error} if the connection is closed.
111
+ */
112
+ _getConnectionSync() {
113
+ if (this._isClosed) {
114
+ throw new Error("Connection is closed.");
115
+ }
116
+ this.initSync();
117
+ return this._connection;
118
+ }
119
+
120
+ /**
121
+ * Execute a prepared statement with the given parameters.
122
+ * @param {lbug.PreparedStatement} preparedStatement the prepared statement to execute.
123
+ * @param {Object} params a plain object mapping parameter names to values.
124
+ * @param {Function} [progressCallback] - Optional callback function that is invoked with the progress of the query execution. The callback receives three arguments: pipelineProgress, numPipelinesFinished, and numPipelines.
125
+ * @returns {Promise<lbug.QueryResult>} a promise that resolves to the query result. The promise is rejected if there is an error.
126
+ */
127
+ execute(preparedStatement, params = {}, progressCallback) {
128
+ return new Promise((resolve, reject) => {
129
+ if (
130
+ !typeof preparedStatement === "object" ||
131
+ preparedStatement.constructor.name !== "PreparedStatement"
132
+ ) {
133
+ return reject(
134
+ new Error(
135
+ "preparedStatement must be a valid PreparedStatement object."
136
+ )
137
+ );
138
+ }
139
+ if (!preparedStatement.isSuccess()) {
140
+ return reject(new Error(preparedStatement.getErrorMessage()));
141
+ }
142
+ if (params.constructor !== Object) {
143
+ return reject(new Error("params must be a plain object."));
144
+ }
145
+ const paramArray = [];
146
+ for (const key in params) {
147
+ const value = params[key];
148
+ paramArray.push([key, value]);
149
+ }
150
+ if (progressCallback && typeof progressCallback !== "function") {
151
+ return reject(new Error("progressCallback must be a function."));
152
+ }
153
+ this._getConnection()
154
+ .then((connection) => {
155
+ const nodeQueryResult = new LbugNative.NodeQueryResult();
156
+ try {
157
+ connection.executeAsync(
158
+ preparedStatement._preparedStatement,
159
+ nodeQueryResult,
160
+ paramArray,
161
+ (err) => {
162
+ if (err) {
163
+ return reject(err);
164
+ }
165
+ this._unwrapMultipleQueryResults(nodeQueryResult)
166
+ .then((queryResults) => {
167
+ return resolve(queryResults);
168
+ })
169
+ .catch((err) => {
170
+ return reject(err);
171
+ });
172
+ },
173
+ progressCallback
174
+ );
175
+ } catch (e) {
176
+ return reject(e);
177
+ }
178
+ })
179
+ .catch((err) => {
180
+ return reject(err);
181
+ });
182
+ });
183
+ }
184
+
185
+ /**
186
+ * Execute a prepared statement with the given parameters synchronously. This function blocks the main thread for the duration of the query, so use it with caution.
187
+ * @param {lbug.PreparedStatement} preparedStatement the prepared statement
188
+ * @param {Object} params a plain object mapping parameter names to values.
189
+ * @returns {Array<lbug.QueryResult> | lbug.QueryResult} an array of query results. If there is only one query result, the function returns the query result directly.
190
+ * @throws {Error} if there is an error.
191
+ */
192
+ executeSync(preparedStatement, params = {}) {
193
+ if (
194
+ !typeof preparedStatement === "object" ||
195
+ preparedStatement.constructor.name !== "PreparedStatement"
196
+ ) {
197
+ throw new Error("preparedStatement must be a valid PreparedStatement object.");
198
+ }
199
+ if (!preparedStatement.isSuccess()) {
200
+ throw new Error(preparedStatement.getErrorMessage());
201
+ }
202
+ if (params.constructor !== Object) {
203
+ throw new Error("params must be a plain object.");
204
+ }
205
+ const paramArray = [];
206
+ for (const key in params) {
207
+ const value = params[key];
208
+ paramArray.push([key, value]);
209
+ }
210
+ const connection = this._getConnectionSync();
211
+ const nodeQueryResult = new LbugNative.NodeQueryResult();
212
+ connection.executeSync(preparedStatement._preparedStatement, nodeQueryResult, paramArray);
213
+ return this._unwrapMultipleQueryResultsSync(nodeQueryResult);
214
+ }
215
+
216
+ /**
217
+ * Prepare a statement for execution.
218
+ * @param {String} statement the statement to prepare.
219
+ * @returns {Promise<lbug.PreparedStatement>} a promise that resolves to the prepared statement. The promise is rejected if there is an error.
220
+ */
221
+ prepare(statement) {
222
+ return new Promise((resolve, reject) => {
223
+ if (typeof statement !== "string") {
224
+ return reject(new Error("statement must be a string."));
225
+ }
226
+ this._getConnection()
227
+ .then((connection) => {
228
+ const preparedStatement = new LbugNative.NodePreparedStatement(
229
+ connection,
230
+ statement
231
+ );
232
+ preparedStatement.initAsync((err) => {
233
+ if (err) {
234
+ return reject(err);
235
+ }
236
+ return resolve(new PreparedStatement(this, preparedStatement));
237
+ });
238
+ })
239
+ .catch((err) => {
240
+ return reject(err);
241
+ });
242
+ });
243
+ }
244
+
245
+ /**
246
+ * Prepare a statement for execution synchronously. This function blocks the main thread so use it with caution.
247
+ * @param {String} statement the statement to prepare.
248
+ * @returns {lbug.PreparedStatement} the prepared statement.
249
+ * @throws {Error} if there is an error.
250
+ */
251
+ prepareSync(statement) {
252
+ if (typeof statement !== "string") {
253
+ throw new Error("statement must be a string.");
254
+ }
255
+ const connection = this._getConnectionSync();
256
+ const preparedStatement = new LbugNative.NodePreparedStatement(
257
+ connection,
258
+ statement
259
+ );
260
+ preparedStatement.initSync();
261
+ return new PreparedStatement(this, preparedStatement);
262
+ }
263
+
264
+ /**
265
+ * Execute a query.
266
+ * @param {String} statement the statement to execute.
267
+ * @param {Function} [progressCallback] - Optional callback function that is invoked with the progress of the query execution. The callback receives three arguments: pipelineProgress, numPipelinesFinished, and numPipelines.
268
+ * @returns {Promise<lbug.QueryResult>} a promise that resolves to the query result. The promise is rejected if there is an error.
269
+ */
270
+ query(statement, progressCallback) {
271
+ return new Promise((resolve, reject) => {
272
+ if (typeof statement !== "string") {
273
+ return reject(new Error("statement must be a string."));
274
+ }
275
+ if (progressCallback && typeof progressCallback !== "function") {
276
+ return reject(new Error("progressCallback must be a function."));
277
+ }
278
+ this._getConnection()
279
+ .then((connection) => {
280
+ const nodeQueryResult = new LbugNative.NodeQueryResult();
281
+ try {
282
+ connection.queryAsync(statement, nodeQueryResult, (err) => {
283
+ if (err) {
284
+ return reject(err);
285
+ }
286
+ this._unwrapMultipleQueryResults(nodeQueryResult)
287
+ .then((queryResults) => {
288
+ return resolve(queryResults);
289
+ })
290
+ .catch((err) => {
291
+ return reject(err);
292
+ });
293
+ },
294
+ progressCallback);
295
+ } catch (e) {
296
+ return reject(e);
297
+ }
298
+ })
299
+ .catch((err) => {
300
+ return reject(err);
301
+ });
302
+ });
303
+ }
304
+
305
+ /**
306
+ * Execute a query synchronously.
307
+ * @param {String} statement the statement to execute. This function blocks the main thread for the duration of the query, so use it with caution.
308
+ * @returns {Array<lbug.QueryResult> | lbug.QueryResult} an array of query results. If there is only one query result, the function returns the query result directly.
309
+ * @throws {Error} if there is an error.
310
+ * @throws {Error} if the statement is not a string.
311
+ * @throws {Error} if the connection is closed.
312
+ */
313
+ querySync(statement) {
314
+ if (typeof statement !== "string") {
315
+ throw new Error("statement must be a string.");
316
+ }
317
+ const connection = this._getConnectionSync();
318
+ const nodeQueryResult = new LbugNative.NodeQueryResult();
319
+ connection.querySync(statement, nodeQueryResult);
320
+ return this._unwrapMultipleQueryResultsSync(nodeQueryResult);
321
+ }
322
+
323
+ /**
324
+ * Internal function to get the next query result for multiple query results.
325
+ * @param {LbugNative.NodeQueryResult} nodeQueryResult the current node query result.
326
+ * @returns {Promise<lbug.QueryResult>} a promise that resolves to the next query result. The promise is rejected if there is an error.
327
+ */
328
+ _getNextQueryResult(nodeQueryResult) {
329
+ return new Promise((resolve, reject) => {
330
+ nodeQueryResult.getNextQueryResultAsync((err, nextNodeQueryResult) => {
331
+ if (err) {
332
+ return reject(err);
333
+ }
334
+ if (!nextNodeQueryResult) {
335
+ return resolve(undefined);
336
+ }
337
+ return resolve(new QueryResult(this, nextNodeQueryResult));
338
+ });
339
+ });
340
+ }
341
+
342
+ /**
343
+ * Internal function to unwrap multiple query results into an array of query results.
344
+ * @param {LbugNative.NodeQueryResult} nodeQueryResult the node query result.
345
+ * @returns {Promise<Array<lbug.QueryResult>> | lbug.QueryResult} a promise that resolves to an array of query results. The promise is rejected if there is an error.
346
+ */
347
+ async _unwrapMultipleQueryResults(nodeQueryResult) {
348
+ const wrappedQueryResult = new QueryResult(this, nodeQueryResult);
349
+ if (!nodeQueryResult.hasNextQueryResult()) {
350
+ return wrappedQueryResult;
351
+ }
352
+ const queryResults = [wrappedQueryResult];
353
+ let currentQueryResult = nodeQueryResult;
354
+ while (currentQueryResult.hasNextQueryResult()) {
355
+ queryResults.push(await this._getNextQueryResult(currentQueryResult));
356
+ currentQueryResult = queryResults[queryResults.length - 1]._queryResult;
357
+ }
358
+ return queryResults;
359
+ }
360
+
361
+ /**
362
+ * Internal function to unwrap multiple query results into an array of query results synchronously.
363
+ * @param {LbugNative.NodeQueryResult} nodeQueryResult the node query result.
364
+ * @returns {Array<lbug.QueryResult> | lbug.QueryResult} an array of query results.
365
+ * @throws {Error} if there is an error.
366
+ */
367
+ _unwrapMultipleQueryResultsSync(nodeQueryResult) {
368
+ const wrappedQueryResult = new QueryResult(this, nodeQueryResult);
369
+ if (!nodeQueryResult.hasNextQueryResult()) {
370
+ return wrappedQueryResult;
371
+ }
372
+ const queryResults = [wrappedQueryResult];
373
+ let currentQueryResult = nodeQueryResult;
374
+ while (currentQueryResult.hasNextQueryResult()) {
375
+ const nextNodeQueryResult = currentQueryResult.getNextQueryResultSync();
376
+ const nextQueryResult = new QueryResult(this, nextNodeQueryResult);
377
+ queryResults.push(nextQueryResult);
378
+ currentQueryResult = nextNodeQueryResult;
379
+ }
380
+ return queryResults;
381
+ }
382
+
383
+ /**
384
+ * Set the maximum number of threads to use for query execution.
385
+ * @param {Number} numThreads the maximum number of threads to use for query execution.
386
+ */
387
+ setMaxNumThreadForExec(numThreads) {
388
+ // If the connection is not initialized yet, store the logging level
389
+ // and defer setting it until the connection is initialized.
390
+ if (typeof numThreads !== "number" || !numThreads || numThreads < 0) {
391
+ throw new Error("numThreads must be a positive number.");
392
+ }
393
+ if (this._isInitialized) {
394
+ this._connection.setMaxNumThreadForExec(numThreads);
395
+ } else {
396
+ this._numThreads = numThreads;
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Set the timeout for queries. Queries that take longer than the timeout
402
+ * will be aborted.
403
+ * @param {Number} timeoutInMs the timeout in milliseconds.
404
+ */
405
+ setQueryTimeout(timeoutInMs) {
406
+ if (
407
+ typeof timeoutInMs !== "number" ||
408
+ isNaN(timeoutInMs) ||
409
+ timeoutInMs <= 0
410
+ ) {
411
+ throw new Error("timeoutInMs must be a positive number.");
412
+ }
413
+ if (this._isInitialized) {
414
+ this._connection.setQueryTimeout(timeoutInMs);
415
+ } else {
416
+ this._queryTimeout = timeoutInMs;
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Close the connection.
422
+ *
423
+ * Note: Call to this method is optional. The connection will be closed
424
+ * automatically when the object goes out of scope.
425
+ */
426
+ async close() {
427
+ if (this._isClosed) {
428
+ return;
429
+ }
430
+ if (!this._isInitialized) {
431
+ if (this._initPromise) {
432
+ // Connection is initializing, wait for it to finish first.
433
+ await this._initPromise;
434
+ } else {
435
+ // Connection is not initialized, simply mark it as closed and initialized.
436
+ this._isInitialized = true;
437
+ this._isClosed = true;
438
+ delete this._connection;
439
+ return;
440
+ }
441
+ }
442
+ // Connection is initialized, close it.
443
+ this._connection.close();
444
+ delete this._connection;
445
+ this._isClosed = true;
446
+ }
447
+
448
+ /**
449
+ * Close the connection synchronously.
450
+ * @throws {Error} if there is an undergoing asynchronous initialization.
451
+ */
452
+ closeSync() {
453
+ if (this._isClosed) {
454
+ return;
455
+ }
456
+ if (!this._isInitialized) {
457
+ if (this._initPromise) {
458
+ throw new Error("There is an ongoing asynchronous initialization. Please wait for it to finish.");
459
+ }
460
+ this._isInitialized = true;
461
+ this._isClosed = true;
462
+ delete this._connection;
463
+ return;
464
+ }
465
+ this._connection.close();
466
+ delete this._connection;
467
+ this._isClosed = true;
468
+ }
469
+ }
470
+
471
+ module.exports = Connection;