@wiscale/velesdb-sdk 1.3.0 → 1.4.1
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/README.md +145 -1
- package/dist/index.d.mts +259 -11
- package/dist/index.d.ts +259 -11
- package/dist/index.js +394 -19
- package/dist/index.mjs +391 -18
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -36,7 +36,9 @@ __export(index_exports, {
|
|
|
36
36
|
ValidationError: () => ValidationError,
|
|
37
37
|
VelesDB: () => VelesDB,
|
|
38
38
|
VelesDBError: () => VelesDBError,
|
|
39
|
-
|
|
39
|
+
VelesQLBuilder: () => VelesQLBuilder,
|
|
40
|
+
WasmBackend: () => WasmBackend,
|
|
41
|
+
velesql: () => velesql
|
|
40
42
|
});
|
|
41
43
|
module.exports = __toCommonJS(index_exports);
|
|
42
44
|
|
|
@@ -175,7 +177,7 @@ var WasmBackend = class {
|
|
|
175
177
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
176
178
|
}
|
|
177
179
|
for (const doc of docs) {
|
|
178
|
-
const vectorLen =
|
|
180
|
+
const vectorLen = doc.vector.length;
|
|
179
181
|
if (vectorLen !== collection.config.dimension) {
|
|
180
182
|
throw new VelesDBError(
|
|
181
183
|
`Vector dimension mismatch for doc ${doc.id}: expected ${collection.config.dimension}, got ${vectorLen}`,
|
|
@@ -281,7 +283,7 @@ var WasmBackend = class {
|
|
|
281
283
|
"NOT_SUPPORTED"
|
|
282
284
|
);
|
|
283
285
|
}
|
|
284
|
-
async query(_queryString, _params) {
|
|
286
|
+
async query(_collection, _queryString, _params, _options) {
|
|
285
287
|
throw new VelesDBError(
|
|
286
288
|
"VelesQL queries are not supported in WASM backend. Use REST backend for query support.",
|
|
287
289
|
"NOT_SUPPORTED"
|
|
@@ -452,6 +454,32 @@ var RestBackend = class {
|
|
|
452
454
|
const message = typeof messageField === "string" ? messageField : void 0;
|
|
453
455
|
return { code, message };
|
|
454
456
|
}
|
|
457
|
+
/**
|
|
458
|
+
* Parse node ID safely to handle u64 values above Number.MAX_SAFE_INTEGER.
|
|
459
|
+
* Returns bigint for large values, number for safe values.
|
|
460
|
+
*/
|
|
461
|
+
parseNodeId(value) {
|
|
462
|
+
if (value === null || value === void 0) {
|
|
463
|
+
return 0;
|
|
464
|
+
}
|
|
465
|
+
if (typeof value === "bigint") {
|
|
466
|
+
return value;
|
|
467
|
+
}
|
|
468
|
+
if (typeof value === "string") {
|
|
469
|
+
const num = Number(value);
|
|
470
|
+
if (num > Number.MAX_SAFE_INTEGER) {
|
|
471
|
+
return BigInt(value);
|
|
472
|
+
}
|
|
473
|
+
return num;
|
|
474
|
+
}
|
|
475
|
+
if (typeof value === "number") {
|
|
476
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
479
|
+
return value;
|
|
480
|
+
}
|
|
481
|
+
return 0;
|
|
482
|
+
}
|
|
455
483
|
async request(method, path, body) {
|
|
456
484
|
const url = `${this.baseUrl}${path}`;
|
|
457
485
|
const headers = {
|
|
@@ -543,11 +571,13 @@ var RestBackend = class {
|
|
|
543
571
|
const vector = doc.vector instanceof Float32Array ? Array.from(doc.vector) : doc.vector;
|
|
544
572
|
const response = await this.request(
|
|
545
573
|
"POST",
|
|
546
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
574
|
+
`/collections/${encodeURIComponent(collection)}/points`,
|
|
547
575
|
{
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
576
|
+
points: [{
|
|
577
|
+
id: doc.id,
|
|
578
|
+
vector,
|
|
579
|
+
payload: doc.payload
|
|
580
|
+
}]
|
|
551
581
|
}
|
|
552
582
|
);
|
|
553
583
|
if (response.error) {
|
|
@@ -566,8 +596,8 @@ var RestBackend = class {
|
|
|
566
596
|
}));
|
|
567
597
|
const response = await this.request(
|
|
568
598
|
"POST",
|
|
569
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
570
|
-
{ vectors }
|
|
599
|
+
`/collections/${encodeURIComponent(collection)}/points`,
|
|
600
|
+
{ points: vectors }
|
|
571
601
|
);
|
|
572
602
|
if (response.error) {
|
|
573
603
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -621,7 +651,7 @@ var RestBackend = class {
|
|
|
621
651
|
this.ensureInitialized();
|
|
622
652
|
const response = await this.request(
|
|
623
653
|
"DELETE",
|
|
624
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
654
|
+
`/collections/${encodeURIComponent(collection)}/points/${encodeURIComponent(String(id))}`
|
|
625
655
|
);
|
|
626
656
|
if (response.error) {
|
|
627
657
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -635,7 +665,7 @@ var RestBackend = class {
|
|
|
635
665
|
this.ensureInitialized();
|
|
636
666
|
const response = await this.request(
|
|
637
667
|
"GET",
|
|
638
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
668
|
+
`/collections/${encodeURIComponent(collection)}/points/${encodeURIComponent(String(id))}`
|
|
639
669
|
);
|
|
640
670
|
if (response.error) {
|
|
641
671
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -686,7 +716,7 @@ var RestBackend = class {
|
|
|
686
716
|
}
|
|
687
717
|
return response.data?.results ?? [];
|
|
688
718
|
}
|
|
689
|
-
async query(queryString, params) {
|
|
719
|
+
async query(collection, queryString, params, _options) {
|
|
690
720
|
this.ensureInitialized();
|
|
691
721
|
const response = await this.request(
|
|
692
722
|
"POST",
|
|
@@ -697,9 +727,32 @@ var RestBackend = class {
|
|
|
697
727
|
}
|
|
698
728
|
);
|
|
699
729
|
if (response.error) {
|
|
730
|
+
if (response.error.code === "NOT_FOUND") {
|
|
731
|
+
throw new NotFoundError(`Collection '${collection}'`);
|
|
732
|
+
}
|
|
700
733
|
throw new VelesDBError(response.error.message, response.error.code);
|
|
701
734
|
}
|
|
702
|
-
|
|
735
|
+
const rawData = response.data;
|
|
736
|
+
return {
|
|
737
|
+
results: (rawData?.results ?? []).map((r) => ({
|
|
738
|
+
// Server returns `id` (u64), map to nodeId with precision handling
|
|
739
|
+
nodeId: this.parseNodeId(r.id ?? r.node_id ?? r.nodeId),
|
|
740
|
+
// Server returns `score`, map to vectorScore (primary score for SELECT queries)
|
|
741
|
+
vectorScore: r.score ?? r.vector_score ?? r.vectorScore,
|
|
742
|
+
// graph_score not returned by SELECT queries, only by future MATCH queries
|
|
743
|
+
graphScore: r.graph_score ?? r.graphScore,
|
|
744
|
+
// Use score as fusedScore for compatibility
|
|
745
|
+
fusedScore: r.score ?? r.fused_score ?? r.fusedScore ?? 0,
|
|
746
|
+
// payload maps to bindings for compatibility
|
|
747
|
+
bindings: r.payload ?? r.bindings ?? {},
|
|
748
|
+
columnData: r.column_data ?? r.columnData
|
|
749
|
+
})),
|
|
750
|
+
stats: {
|
|
751
|
+
executionTimeMs: rawData?.timing_ms ?? 0,
|
|
752
|
+
strategy: "select",
|
|
753
|
+
scannedNodes: rawData?.rows_returned ?? 0
|
|
754
|
+
}
|
|
755
|
+
};
|
|
703
756
|
}
|
|
704
757
|
async multiQuerySearch(collection, vectors, options) {
|
|
705
758
|
this.ensureInitialized();
|
|
@@ -1160,18 +1213,36 @@ var VelesDB = class {
|
|
|
1160
1213
|
return this.backend.hybridSearch(collection, vector, textQuery, options);
|
|
1161
1214
|
}
|
|
1162
1215
|
/**
|
|
1163
|
-
* Execute a VelesQL query
|
|
1216
|
+
* Execute a VelesQL multi-model query (EPIC-031 US-011)
|
|
1164
1217
|
*
|
|
1218
|
+
* Supports hybrid vector + graph queries with VelesQL syntax.
|
|
1219
|
+
*
|
|
1220
|
+
* @param collection - Collection name
|
|
1165
1221
|
* @param queryString - VelesQL query string
|
|
1166
|
-
* @param params -
|
|
1167
|
-
* @
|
|
1222
|
+
* @param params - Query parameters (vectors, scalars)
|
|
1223
|
+
* @param options - Query options (timeout, streaming)
|
|
1224
|
+
* @returns Query response with results and execution stats
|
|
1225
|
+
*
|
|
1226
|
+
* @example
|
|
1227
|
+
* ```typescript
|
|
1228
|
+
* const response = await db.query('docs', `
|
|
1229
|
+
* MATCH (d:Doc) WHERE vector NEAR $q LIMIT 20
|
|
1230
|
+
* `, { q: queryVector });
|
|
1231
|
+
*
|
|
1232
|
+
* for (const r of response.results) {
|
|
1233
|
+
* console.log(`Node ${r.nodeId}: ${r.fusedScore}`);
|
|
1234
|
+
* }
|
|
1235
|
+
* ```
|
|
1168
1236
|
*/
|
|
1169
|
-
async query(queryString, params) {
|
|
1237
|
+
async query(collection, queryString, params, options) {
|
|
1170
1238
|
this.ensureInitialized();
|
|
1239
|
+
if (!collection || typeof collection !== "string") {
|
|
1240
|
+
throw new ValidationError("Collection name must be a non-empty string");
|
|
1241
|
+
}
|
|
1171
1242
|
if (!queryString || typeof queryString !== "string") {
|
|
1172
1243
|
throw new ValidationError("Query string must be a non-empty string");
|
|
1173
1244
|
}
|
|
1174
|
-
return this.backend.query(queryString, params);
|
|
1245
|
+
return this.backend.query(collection, queryString, params, options);
|
|
1175
1246
|
}
|
|
1176
1247
|
/**
|
|
1177
1248
|
* Multi-query fusion search combining results from multiple query vectors
|
|
@@ -1409,6 +1480,308 @@ var VelesDB = class {
|
|
|
1409
1480
|
return this.backend.getNodeDegree(collection, nodeId);
|
|
1410
1481
|
}
|
|
1411
1482
|
};
|
|
1483
|
+
|
|
1484
|
+
// src/query-builder.ts
|
|
1485
|
+
var VelesQLBuilder = class _VelesQLBuilder {
|
|
1486
|
+
constructor(state) {
|
|
1487
|
+
this.state = {
|
|
1488
|
+
matchClauses: state?.matchClauses ?? [],
|
|
1489
|
+
whereClauses: state?.whereClauses ?? [],
|
|
1490
|
+
whereOperators: state?.whereOperators ?? [],
|
|
1491
|
+
params: state?.params ?? {},
|
|
1492
|
+
limitValue: state?.limitValue,
|
|
1493
|
+
offsetValue: state?.offsetValue,
|
|
1494
|
+
orderByClause: state?.orderByClause,
|
|
1495
|
+
returnClause: state?.returnClause,
|
|
1496
|
+
fusionOptions: state?.fusionOptions,
|
|
1497
|
+
currentNode: state?.currentNode,
|
|
1498
|
+
pendingRel: state?.pendingRel
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1501
|
+
clone(updates) {
|
|
1502
|
+
return new _VelesQLBuilder({
|
|
1503
|
+
...this.state,
|
|
1504
|
+
matchClauses: [...this.state.matchClauses],
|
|
1505
|
+
whereClauses: [...this.state.whereClauses],
|
|
1506
|
+
whereOperators: [...this.state.whereOperators],
|
|
1507
|
+
params: { ...this.state.params },
|
|
1508
|
+
...updates
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Start a MATCH clause with a node pattern
|
|
1513
|
+
*
|
|
1514
|
+
* @param alias - Node alias (e.g., 'n', 'person')
|
|
1515
|
+
* @param label - Optional node label(s)
|
|
1516
|
+
*/
|
|
1517
|
+
match(alias, label) {
|
|
1518
|
+
const labelStr = this.formatLabel(label);
|
|
1519
|
+
const nodePattern = `(${alias}${labelStr})`;
|
|
1520
|
+
return this.clone({
|
|
1521
|
+
matchClauses: [...this.state.matchClauses, nodePattern],
|
|
1522
|
+
currentNode: alias
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Add a relationship pattern
|
|
1527
|
+
*
|
|
1528
|
+
* @param type - Relationship type (e.g., 'KNOWS', 'FOLLOWS')
|
|
1529
|
+
* @param alias - Optional relationship alias
|
|
1530
|
+
* @param options - Relationship options (direction, hops)
|
|
1531
|
+
*/
|
|
1532
|
+
rel(type, alias, options) {
|
|
1533
|
+
return this.clone({
|
|
1534
|
+
pendingRel: { type, alias, options }
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Complete a relationship pattern with target node
|
|
1539
|
+
*
|
|
1540
|
+
* @param alias - Target node alias
|
|
1541
|
+
* @param label - Optional target node label(s)
|
|
1542
|
+
*/
|
|
1543
|
+
to(alias, label) {
|
|
1544
|
+
if (!this.state.pendingRel) {
|
|
1545
|
+
throw new Error("to() must be called after rel()");
|
|
1546
|
+
}
|
|
1547
|
+
const { type, alias: relAlias, options } = this.state.pendingRel;
|
|
1548
|
+
const direction = options?.direction ?? "outgoing";
|
|
1549
|
+
const labelStr = this.formatLabel(label);
|
|
1550
|
+
const relPattern = this.formatRelationship(type, relAlias, options);
|
|
1551
|
+
const targetNode = `(${alias}${labelStr})`;
|
|
1552
|
+
let fullPattern;
|
|
1553
|
+
switch (direction) {
|
|
1554
|
+
case "incoming":
|
|
1555
|
+
fullPattern = `<-${relPattern}-${targetNode}`;
|
|
1556
|
+
break;
|
|
1557
|
+
case "both":
|
|
1558
|
+
fullPattern = `-${relPattern}-${targetNode}`;
|
|
1559
|
+
break;
|
|
1560
|
+
default:
|
|
1561
|
+
fullPattern = `-${relPattern}->${targetNode}`;
|
|
1562
|
+
}
|
|
1563
|
+
const lastMatch = this.state.matchClauses[this.state.matchClauses.length - 1];
|
|
1564
|
+
const updatedMatch = lastMatch + fullPattern;
|
|
1565
|
+
const newMatchClauses = [...this.state.matchClauses.slice(0, -1), updatedMatch];
|
|
1566
|
+
return this.clone({
|
|
1567
|
+
matchClauses: newMatchClauses,
|
|
1568
|
+
currentNode: alias,
|
|
1569
|
+
pendingRel: void 0
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
/**
|
|
1573
|
+
* Add a WHERE clause
|
|
1574
|
+
*
|
|
1575
|
+
* @param condition - WHERE condition
|
|
1576
|
+
* @param params - Optional parameters
|
|
1577
|
+
*/
|
|
1578
|
+
where(condition, params) {
|
|
1579
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1580
|
+
return this.clone({
|
|
1581
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1582
|
+
whereOperators: [...this.state.whereOperators],
|
|
1583
|
+
params: newParams
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* Add an AND WHERE clause
|
|
1588
|
+
*
|
|
1589
|
+
* @param condition - WHERE condition
|
|
1590
|
+
* @param params - Optional parameters
|
|
1591
|
+
*/
|
|
1592
|
+
andWhere(condition, params) {
|
|
1593
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1594
|
+
return this.clone({
|
|
1595
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1596
|
+
whereOperators: [...this.state.whereOperators, "AND"],
|
|
1597
|
+
params: newParams
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* Add an OR WHERE clause
|
|
1602
|
+
*
|
|
1603
|
+
* @param condition - WHERE condition
|
|
1604
|
+
* @param params - Optional parameters
|
|
1605
|
+
*/
|
|
1606
|
+
orWhere(condition, params) {
|
|
1607
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1608
|
+
return this.clone({
|
|
1609
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1610
|
+
whereOperators: [...this.state.whereOperators, "OR"],
|
|
1611
|
+
params: newParams
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
/**
|
|
1615
|
+
* Add a vector NEAR clause for similarity search
|
|
1616
|
+
*
|
|
1617
|
+
* @param paramName - Parameter name (e.g., '$query', '$embedding')
|
|
1618
|
+
* @param vector - Vector data
|
|
1619
|
+
* @param options - NEAR options (topK)
|
|
1620
|
+
*/
|
|
1621
|
+
nearVector(paramName, vector, options) {
|
|
1622
|
+
const cleanParamName = paramName.startsWith("$") ? paramName.slice(1) : paramName;
|
|
1623
|
+
const topKSuffix = options?.topK ? ` TOP ${options.topK}` : "";
|
|
1624
|
+
const condition = `vector NEAR $${cleanParamName}${topKSuffix}`;
|
|
1625
|
+
const newParams = { ...this.state.params, [cleanParamName]: vector };
|
|
1626
|
+
if (this.state.whereClauses.length === 0) {
|
|
1627
|
+
return this.clone({
|
|
1628
|
+
whereClauses: [condition],
|
|
1629
|
+
params: newParams
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
return this.clone({
|
|
1633
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1634
|
+
whereOperators: [...this.state.whereOperators, "AND"],
|
|
1635
|
+
params: newParams
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Add LIMIT clause
|
|
1640
|
+
*
|
|
1641
|
+
* @param value - Maximum number of results
|
|
1642
|
+
*/
|
|
1643
|
+
limit(value) {
|
|
1644
|
+
if (value < 0) {
|
|
1645
|
+
throw new Error("LIMIT must be non-negative");
|
|
1646
|
+
}
|
|
1647
|
+
return this.clone({ limitValue: value });
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* Add OFFSET clause
|
|
1651
|
+
*
|
|
1652
|
+
* @param value - Number of results to skip
|
|
1653
|
+
*/
|
|
1654
|
+
offset(value) {
|
|
1655
|
+
if (value < 0) {
|
|
1656
|
+
throw new Error("OFFSET must be non-negative");
|
|
1657
|
+
}
|
|
1658
|
+
return this.clone({ offsetValue: value });
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Add ORDER BY clause
|
|
1662
|
+
*
|
|
1663
|
+
* @param field - Field to order by
|
|
1664
|
+
* @param direction - Sort direction (ASC or DESC)
|
|
1665
|
+
*/
|
|
1666
|
+
orderBy(field, direction) {
|
|
1667
|
+
const orderClause = direction ? `${field} ${direction}` : field;
|
|
1668
|
+
return this.clone({ orderByClause: orderClause });
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* Add RETURN clause with specific fields
|
|
1672
|
+
*
|
|
1673
|
+
* @param fields - Fields to return (array or object with aliases)
|
|
1674
|
+
*/
|
|
1675
|
+
return(fields) {
|
|
1676
|
+
let returnClause;
|
|
1677
|
+
if (Array.isArray(fields)) {
|
|
1678
|
+
returnClause = fields.join(", ");
|
|
1679
|
+
} else {
|
|
1680
|
+
returnClause = Object.entries(fields).map(([field, alias]) => `${field} AS ${alias}`).join(", ");
|
|
1681
|
+
}
|
|
1682
|
+
return this.clone({ returnClause });
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Add RETURN * clause
|
|
1686
|
+
*/
|
|
1687
|
+
returnAll() {
|
|
1688
|
+
return this.clone({ returnClause: "*" });
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Set fusion strategy for hybrid queries
|
|
1692
|
+
*
|
|
1693
|
+
* @param strategy - Fusion strategy
|
|
1694
|
+
* @param options - Fusion parameters
|
|
1695
|
+
*/
|
|
1696
|
+
fusion(strategy, options) {
|
|
1697
|
+
return this.clone({
|
|
1698
|
+
fusionOptions: {
|
|
1699
|
+
strategy,
|
|
1700
|
+
...options
|
|
1701
|
+
}
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Get the fusion options
|
|
1706
|
+
*/
|
|
1707
|
+
getFusionOptions() {
|
|
1708
|
+
return this.state.fusionOptions;
|
|
1709
|
+
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Get all parameters
|
|
1712
|
+
*/
|
|
1713
|
+
getParams() {
|
|
1714
|
+
return { ...this.state.params };
|
|
1715
|
+
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Build the VelesQL query string
|
|
1718
|
+
*/
|
|
1719
|
+
toVelesQL() {
|
|
1720
|
+
if (this.state.matchClauses.length === 0) {
|
|
1721
|
+
throw new Error("Query must have at least one MATCH clause");
|
|
1722
|
+
}
|
|
1723
|
+
const parts = [];
|
|
1724
|
+
parts.push(`MATCH ${this.state.matchClauses.join(", ")}`);
|
|
1725
|
+
if (this.state.whereClauses.length > 0) {
|
|
1726
|
+
const whereStr = this.buildWhereClause();
|
|
1727
|
+
parts.push(`WHERE ${whereStr}`);
|
|
1728
|
+
}
|
|
1729
|
+
if (this.state.orderByClause) {
|
|
1730
|
+
parts.push(`ORDER BY ${this.state.orderByClause}`);
|
|
1731
|
+
}
|
|
1732
|
+
if (this.state.limitValue !== void 0) {
|
|
1733
|
+
parts.push(`LIMIT ${this.state.limitValue}`);
|
|
1734
|
+
}
|
|
1735
|
+
if (this.state.offsetValue !== void 0) {
|
|
1736
|
+
parts.push(`OFFSET ${this.state.offsetValue}`);
|
|
1737
|
+
}
|
|
1738
|
+
if (this.state.returnClause) {
|
|
1739
|
+
parts.push(`RETURN ${this.state.returnClause}`);
|
|
1740
|
+
}
|
|
1741
|
+
if (this.state.fusionOptions) {
|
|
1742
|
+
parts.push(`/* FUSION ${this.state.fusionOptions.strategy} */`);
|
|
1743
|
+
}
|
|
1744
|
+
return parts.join(" ");
|
|
1745
|
+
}
|
|
1746
|
+
formatLabel(label) {
|
|
1747
|
+
if (!label) return "";
|
|
1748
|
+
if (Array.isArray(label)) {
|
|
1749
|
+
return label.map((l) => `:${l}`).join("");
|
|
1750
|
+
}
|
|
1751
|
+
return `:${label}`;
|
|
1752
|
+
}
|
|
1753
|
+
formatRelationship(type, alias, options) {
|
|
1754
|
+
const aliasStr = alias ? alias : "";
|
|
1755
|
+
const hopsStr = this.formatHops(options);
|
|
1756
|
+
if (alias) {
|
|
1757
|
+
return `[${aliasStr}:${type}${hopsStr}]`;
|
|
1758
|
+
}
|
|
1759
|
+
return `[:${type}${hopsStr}]`;
|
|
1760
|
+
}
|
|
1761
|
+
formatHops(options) {
|
|
1762
|
+
if (!options?.minHops && !options?.maxHops) return "";
|
|
1763
|
+
const min = options.minHops ?? 1;
|
|
1764
|
+
const max = options.maxHops ?? "";
|
|
1765
|
+
return `*${min}..${max}`;
|
|
1766
|
+
}
|
|
1767
|
+
buildWhereClause() {
|
|
1768
|
+
if (this.state.whereClauses.length === 0) return "";
|
|
1769
|
+
const first = this.state.whereClauses[0];
|
|
1770
|
+
if (!first) return "";
|
|
1771
|
+
let result = first;
|
|
1772
|
+
for (let i = 1; i < this.state.whereClauses.length; i++) {
|
|
1773
|
+
const operator = this.state.whereOperators[i - 1] ?? "AND";
|
|
1774
|
+
const clause = this.state.whereClauses[i];
|
|
1775
|
+
if (clause) {
|
|
1776
|
+
result += ` ${operator} ${clause}`;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
return result;
|
|
1780
|
+
}
|
|
1781
|
+
};
|
|
1782
|
+
function velesql() {
|
|
1783
|
+
return new VelesQLBuilder();
|
|
1784
|
+
}
|
|
1412
1785
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1413
1786
|
0 && (module.exports = {
|
|
1414
1787
|
ConnectionError,
|
|
@@ -1417,5 +1790,7 @@ var VelesDB = class {
|
|
|
1417
1790
|
ValidationError,
|
|
1418
1791
|
VelesDB,
|
|
1419
1792
|
VelesDBError,
|
|
1420
|
-
|
|
1793
|
+
VelesQLBuilder,
|
|
1794
|
+
WasmBackend,
|
|
1795
|
+
velesql
|
|
1421
1796
|
});
|