@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.mjs
CHANGED
|
@@ -133,7 +133,7 @@ var WasmBackend = class {
|
|
|
133
133
|
throw new NotFoundError(`Collection '${collectionName}'`);
|
|
134
134
|
}
|
|
135
135
|
for (const doc of docs) {
|
|
136
|
-
const vectorLen =
|
|
136
|
+
const vectorLen = doc.vector.length;
|
|
137
137
|
if (vectorLen !== collection.config.dimension) {
|
|
138
138
|
throw new VelesDBError(
|
|
139
139
|
`Vector dimension mismatch for doc ${doc.id}: expected ${collection.config.dimension}, got ${vectorLen}`,
|
|
@@ -239,7 +239,7 @@ var WasmBackend = class {
|
|
|
239
239
|
"NOT_SUPPORTED"
|
|
240
240
|
);
|
|
241
241
|
}
|
|
242
|
-
async query(_queryString, _params) {
|
|
242
|
+
async query(_collection, _queryString, _params, _options) {
|
|
243
243
|
throw new VelesDBError(
|
|
244
244
|
"VelesQL queries are not supported in WASM backend. Use REST backend for query support.",
|
|
245
245
|
"NOT_SUPPORTED"
|
|
@@ -410,6 +410,32 @@ var RestBackend = class {
|
|
|
410
410
|
const message = typeof messageField === "string" ? messageField : void 0;
|
|
411
411
|
return { code, message };
|
|
412
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* Parse node ID safely to handle u64 values above Number.MAX_SAFE_INTEGER.
|
|
415
|
+
* Returns bigint for large values, number for safe values.
|
|
416
|
+
*/
|
|
417
|
+
parseNodeId(value) {
|
|
418
|
+
if (value === null || value === void 0) {
|
|
419
|
+
return 0;
|
|
420
|
+
}
|
|
421
|
+
if (typeof value === "bigint") {
|
|
422
|
+
return value;
|
|
423
|
+
}
|
|
424
|
+
if (typeof value === "string") {
|
|
425
|
+
const num = Number(value);
|
|
426
|
+
if (num > Number.MAX_SAFE_INTEGER) {
|
|
427
|
+
return BigInt(value);
|
|
428
|
+
}
|
|
429
|
+
return num;
|
|
430
|
+
}
|
|
431
|
+
if (typeof value === "number") {
|
|
432
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
433
|
+
return value;
|
|
434
|
+
}
|
|
435
|
+
return value;
|
|
436
|
+
}
|
|
437
|
+
return 0;
|
|
438
|
+
}
|
|
413
439
|
async request(method, path, body) {
|
|
414
440
|
const url = `${this.baseUrl}${path}`;
|
|
415
441
|
const headers = {
|
|
@@ -501,11 +527,13 @@ var RestBackend = class {
|
|
|
501
527
|
const vector = doc.vector instanceof Float32Array ? Array.from(doc.vector) : doc.vector;
|
|
502
528
|
const response = await this.request(
|
|
503
529
|
"POST",
|
|
504
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
530
|
+
`/collections/${encodeURIComponent(collection)}/points`,
|
|
505
531
|
{
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
532
|
+
points: [{
|
|
533
|
+
id: doc.id,
|
|
534
|
+
vector,
|
|
535
|
+
payload: doc.payload
|
|
536
|
+
}]
|
|
509
537
|
}
|
|
510
538
|
);
|
|
511
539
|
if (response.error) {
|
|
@@ -524,8 +552,8 @@ var RestBackend = class {
|
|
|
524
552
|
}));
|
|
525
553
|
const response = await this.request(
|
|
526
554
|
"POST",
|
|
527
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
528
|
-
{ vectors }
|
|
555
|
+
`/collections/${encodeURIComponent(collection)}/points`,
|
|
556
|
+
{ points: vectors }
|
|
529
557
|
);
|
|
530
558
|
if (response.error) {
|
|
531
559
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -579,7 +607,7 @@ var RestBackend = class {
|
|
|
579
607
|
this.ensureInitialized();
|
|
580
608
|
const response = await this.request(
|
|
581
609
|
"DELETE",
|
|
582
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
610
|
+
`/collections/${encodeURIComponent(collection)}/points/${encodeURIComponent(String(id))}`
|
|
583
611
|
);
|
|
584
612
|
if (response.error) {
|
|
585
613
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -593,7 +621,7 @@ var RestBackend = class {
|
|
|
593
621
|
this.ensureInitialized();
|
|
594
622
|
const response = await this.request(
|
|
595
623
|
"GET",
|
|
596
|
-
`/collections/${encodeURIComponent(collection)}/
|
|
624
|
+
`/collections/${encodeURIComponent(collection)}/points/${encodeURIComponent(String(id))}`
|
|
597
625
|
);
|
|
598
626
|
if (response.error) {
|
|
599
627
|
if (response.error.code === "NOT_FOUND") {
|
|
@@ -644,7 +672,7 @@ var RestBackend = class {
|
|
|
644
672
|
}
|
|
645
673
|
return response.data?.results ?? [];
|
|
646
674
|
}
|
|
647
|
-
async query(queryString, params) {
|
|
675
|
+
async query(collection, queryString, params, _options) {
|
|
648
676
|
this.ensureInitialized();
|
|
649
677
|
const response = await this.request(
|
|
650
678
|
"POST",
|
|
@@ -655,9 +683,32 @@ var RestBackend = class {
|
|
|
655
683
|
}
|
|
656
684
|
);
|
|
657
685
|
if (response.error) {
|
|
686
|
+
if (response.error.code === "NOT_FOUND") {
|
|
687
|
+
throw new NotFoundError(`Collection '${collection}'`);
|
|
688
|
+
}
|
|
658
689
|
throw new VelesDBError(response.error.message, response.error.code);
|
|
659
690
|
}
|
|
660
|
-
|
|
691
|
+
const rawData = response.data;
|
|
692
|
+
return {
|
|
693
|
+
results: (rawData?.results ?? []).map((r) => ({
|
|
694
|
+
// Server returns `id` (u64), map to nodeId with precision handling
|
|
695
|
+
nodeId: this.parseNodeId(r.id ?? r.node_id ?? r.nodeId),
|
|
696
|
+
// Server returns `score`, map to vectorScore (primary score for SELECT queries)
|
|
697
|
+
vectorScore: r.score ?? r.vector_score ?? r.vectorScore,
|
|
698
|
+
// graph_score not returned by SELECT queries, only by future MATCH queries
|
|
699
|
+
graphScore: r.graph_score ?? r.graphScore,
|
|
700
|
+
// Use score as fusedScore for compatibility
|
|
701
|
+
fusedScore: r.score ?? r.fused_score ?? r.fusedScore ?? 0,
|
|
702
|
+
// payload maps to bindings for compatibility
|
|
703
|
+
bindings: r.payload ?? r.bindings ?? {},
|
|
704
|
+
columnData: r.column_data ?? r.columnData
|
|
705
|
+
})),
|
|
706
|
+
stats: {
|
|
707
|
+
executionTimeMs: rawData?.timing_ms ?? 0,
|
|
708
|
+
strategy: "select",
|
|
709
|
+
scannedNodes: rawData?.rows_returned ?? 0
|
|
710
|
+
}
|
|
711
|
+
};
|
|
661
712
|
}
|
|
662
713
|
async multiQuerySearch(collection, vectors, options) {
|
|
663
714
|
this.ensureInitialized();
|
|
@@ -1118,18 +1169,36 @@ var VelesDB = class {
|
|
|
1118
1169
|
return this.backend.hybridSearch(collection, vector, textQuery, options);
|
|
1119
1170
|
}
|
|
1120
1171
|
/**
|
|
1121
|
-
* Execute a VelesQL query
|
|
1172
|
+
* Execute a VelesQL multi-model query (EPIC-031 US-011)
|
|
1122
1173
|
*
|
|
1174
|
+
* Supports hybrid vector + graph queries with VelesQL syntax.
|
|
1175
|
+
*
|
|
1176
|
+
* @param collection - Collection name
|
|
1123
1177
|
* @param queryString - VelesQL query string
|
|
1124
|
-
* @param params -
|
|
1125
|
-
* @
|
|
1178
|
+
* @param params - Query parameters (vectors, scalars)
|
|
1179
|
+
* @param options - Query options (timeout, streaming)
|
|
1180
|
+
* @returns Query response with results and execution stats
|
|
1181
|
+
*
|
|
1182
|
+
* @example
|
|
1183
|
+
* ```typescript
|
|
1184
|
+
* const response = await db.query('docs', `
|
|
1185
|
+
* MATCH (d:Doc) WHERE vector NEAR $q LIMIT 20
|
|
1186
|
+
* `, { q: queryVector });
|
|
1187
|
+
*
|
|
1188
|
+
* for (const r of response.results) {
|
|
1189
|
+
* console.log(`Node ${r.nodeId}: ${r.fusedScore}`);
|
|
1190
|
+
* }
|
|
1191
|
+
* ```
|
|
1126
1192
|
*/
|
|
1127
|
-
async query(queryString, params) {
|
|
1193
|
+
async query(collection, queryString, params, options) {
|
|
1128
1194
|
this.ensureInitialized();
|
|
1195
|
+
if (!collection || typeof collection !== "string") {
|
|
1196
|
+
throw new ValidationError("Collection name must be a non-empty string");
|
|
1197
|
+
}
|
|
1129
1198
|
if (!queryString || typeof queryString !== "string") {
|
|
1130
1199
|
throw new ValidationError("Query string must be a non-empty string");
|
|
1131
1200
|
}
|
|
1132
|
-
return this.backend.query(queryString, params);
|
|
1201
|
+
return this.backend.query(collection, queryString, params, options);
|
|
1133
1202
|
}
|
|
1134
1203
|
/**
|
|
1135
1204
|
* Multi-query fusion search combining results from multiple query vectors
|
|
@@ -1367,6 +1436,308 @@ var VelesDB = class {
|
|
|
1367
1436
|
return this.backend.getNodeDegree(collection, nodeId);
|
|
1368
1437
|
}
|
|
1369
1438
|
};
|
|
1439
|
+
|
|
1440
|
+
// src/query-builder.ts
|
|
1441
|
+
var VelesQLBuilder = class _VelesQLBuilder {
|
|
1442
|
+
constructor(state) {
|
|
1443
|
+
this.state = {
|
|
1444
|
+
matchClauses: state?.matchClauses ?? [],
|
|
1445
|
+
whereClauses: state?.whereClauses ?? [],
|
|
1446
|
+
whereOperators: state?.whereOperators ?? [],
|
|
1447
|
+
params: state?.params ?? {},
|
|
1448
|
+
limitValue: state?.limitValue,
|
|
1449
|
+
offsetValue: state?.offsetValue,
|
|
1450
|
+
orderByClause: state?.orderByClause,
|
|
1451
|
+
returnClause: state?.returnClause,
|
|
1452
|
+
fusionOptions: state?.fusionOptions,
|
|
1453
|
+
currentNode: state?.currentNode,
|
|
1454
|
+
pendingRel: state?.pendingRel
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
clone(updates) {
|
|
1458
|
+
return new _VelesQLBuilder({
|
|
1459
|
+
...this.state,
|
|
1460
|
+
matchClauses: [...this.state.matchClauses],
|
|
1461
|
+
whereClauses: [...this.state.whereClauses],
|
|
1462
|
+
whereOperators: [...this.state.whereOperators],
|
|
1463
|
+
params: { ...this.state.params },
|
|
1464
|
+
...updates
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Start a MATCH clause with a node pattern
|
|
1469
|
+
*
|
|
1470
|
+
* @param alias - Node alias (e.g., 'n', 'person')
|
|
1471
|
+
* @param label - Optional node label(s)
|
|
1472
|
+
*/
|
|
1473
|
+
match(alias, label) {
|
|
1474
|
+
const labelStr = this.formatLabel(label);
|
|
1475
|
+
const nodePattern = `(${alias}${labelStr})`;
|
|
1476
|
+
return this.clone({
|
|
1477
|
+
matchClauses: [...this.state.matchClauses, nodePattern],
|
|
1478
|
+
currentNode: alias
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Add a relationship pattern
|
|
1483
|
+
*
|
|
1484
|
+
* @param type - Relationship type (e.g., 'KNOWS', 'FOLLOWS')
|
|
1485
|
+
* @param alias - Optional relationship alias
|
|
1486
|
+
* @param options - Relationship options (direction, hops)
|
|
1487
|
+
*/
|
|
1488
|
+
rel(type, alias, options) {
|
|
1489
|
+
return this.clone({
|
|
1490
|
+
pendingRel: { type, alias, options }
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Complete a relationship pattern with target node
|
|
1495
|
+
*
|
|
1496
|
+
* @param alias - Target node alias
|
|
1497
|
+
* @param label - Optional target node label(s)
|
|
1498
|
+
*/
|
|
1499
|
+
to(alias, label) {
|
|
1500
|
+
if (!this.state.pendingRel) {
|
|
1501
|
+
throw new Error("to() must be called after rel()");
|
|
1502
|
+
}
|
|
1503
|
+
const { type, alias: relAlias, options } = this.state.pendingRel;
|
|
1504
|
+
const direction = options?.direction ?? "outgoing";
|
|
1505
|
+
const labelStr = this.formatLabel(label);
|
|
1506
|
+
const relPattern = this.formatRelationship(type, relAlias, options);
|
|
1507
|
+
const targetNode = `(${alias}${labelStr})`;
|
|
1508
|
+
let fullPattern;
|
|
1509
|
+
switch (direction) {
|
|
1510
|
+
case "incoming":
|
|
1511
|
+
fullPattern = `<-${relPattern}-${targetNode}`;
|
|
1512
|
+
break;
|
|
1513
|
+
case "both":
|
|
1514
|
+
fullPattern = `-${relPattern}-${targetNode}`;
|
|
1515
|
+
break;
|
|
1516
|
+
default:
|
|
1517
|
+
fullPattern = `-${relPattern}->${targetNode}`;
|
|
1518
|
+
}
|
|
1519
|
+
const lastMatch = this.state.matchClauses[this.state.matchClauses.length - 1];
|
|
1520
|
+
const updatedMatch = lastMatch + fullPattern;
|
|
1521
|
+
const newMatchClauses = [...this.state.matchClauses.slice(0, -1), updatedMatch];
|
|
1522
|
+
return this.clone({
|
|
1523
|
+
matchClauses: newMatchClauses,
|
|
1524
|
+
currentNode: alias,
|
|
1525
|
+
pendingRel: void 0
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Add a WHERE clause
|
|
1530
|
+
*
|
|
1531
|
+
* @param condition - WHERE condition
|
|
1532
|
+
* @param params - Optional parameters
|
|
1533
|
+
*/
|
|
1534
|
+
where(condition, params) {
|
|
1535
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1536
|
+
return this.clone({
|
|
1537
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1538
|
+
whereOperators: [...this.state.whereOperators],
|
|
1539
|
+
params: newParams
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Add an AND WHERE clause
|
|
1544
|
+
*
|
|
1545
|
+
* @param condition - WHERE condition
|
|
1546
|
+
* @param params - Optional parameters
|
|
1547
|
+
*/
|
|
1548
|
+
andWhere(condition, params) {
|
|
1549
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1550
|
+
return this.clone({
|
|
1551
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1552
|
+
whereOperators: [...this.state.whereOperators, "AND"],
|
|
1553
|
+
params: newParams
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Add an OR WHERE clause
|
|
1558
|
+
*
|
|
1559
|
+
* @param condition - WHERE condition
|
|
1560
|
+
* @param params - Optional parameters
|
|
1561
|
+
*/
|
|
1562
|
+
orWhere(condition, params) {
|
|
1563
|
+
const newParams = params ? { ...this.state.params, ...params } : this.state.params;
|
|
1564
|
+
return this.clone({
|
|
1565
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1566
|
+
whereOperators: [...this.state.whereOperators, "OR"],
|
|
1567
|
+
params: newParams
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
/**
|
|
1571
|
+
* Add a vector NEAR clause for similarity search
|
|
1572
|
+
*
|
|
1573
|
+
* @param paramName - Parameter name (e.g., '$query', '$embedding')
|
|
1574
|
+
* @param vector - Vector data
|
|
1575
|
+
* @param options - NEAR options (topK)
|
|
1576
|
+
*/
|
|
1577
|
+
nearVector(paramName, vector, options) {
|
|
1578
|
+
const cleanParamName = paramName.startsWith("$") ? paramName.slice(1) : paramName;
|
|
1579
|
+
const topKSuffix = options?.topK ? ` TOP ${options.topK}` : "";
|
|
1580
|
+
const condition = `vector NEAR $${cleanParamName}${topKSuffix}`;
|
|
1581
|
+
const newParams = { ...this.state.params, [cleanParamName]: vector };
|
|
1582
|
+
if (this.state.whereClauses.length === 0) {
|
|
1583
|
+
return this.clone({
|
|
1584
|
+
whereClauses: [condition],
|
|
1585
|
+
params: newParams
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
return this.clone({
|
|
1589
|
+
whereClauses: [...this.state.whereClauses, condition],
|
|
1590
|
+
whereOperators: [...this.state.whereOperators, "AND"],
|
|
1591
|
+
params: newParams
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Add LIMIT clause
|
|
1596
|
+
*
|
|
1597
|
+
* @param value - Maximum number of results
|
|
1598
|
+
*/
|
|
1599
|
+
limit(value) {
|
|
1600
|
+
if (value < 0) {
|
|
1601
|
+
throw new Error("LIMIT must be non-negative");
|
|
1602
|
+
}
|
|
1603
|
+
return this.clone({ limitValue: value });
|
|
1604
|
+
}
|
|
1605
|
+
/**
|
|
1606
|
+
* Add OFFSET clause
|
|
1607
|
+
*
|
|
1608
|
+
* @param value - Number of results to skip
|
|
1609
|
+
*/
|
|
1610
|
+
offset(value) {
|
|
1611
|
+
if (value < 0) {
|
|
1612
|
+
throw new Error("OFFSET must be non-negative");
|
|
1613
|
+
}
|
|
1614
|
+
return this.clone({ offsetValue: value });
|
|
1615
|
+
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Add ORDER BY clause
|
|
1618
|
+
*
|
|
1619
|
+
* @param field - Field to order by
|
|
1620
|
+
* @param direction - Sort direction (ASC or DESC)
|
|
1621
|
+
*/
|
|
1622
|
+
orderBy(field, direction) {
|
|
1623
|
+
const orderClause = direction ? `${field} ${direction}` : field;
|
|
1624
|
+
return this.clone({ orderByClause: orderClause });
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Add RETURN clause with specific fields
|
|
1628
|
+
*
|
|
1629
|
+
* @param fields - Fields to return (array or object with aliases)
|
|
1630
|
+
*/
|
|
1631
|
+
return(fields) {
|
|
1632
|
+
let returnClause;
|
|
1633
|
+
if (Array.isArray(fields)) {
|
|
1634
|
+
returnClause = fields.join(", ");
|
|
1635
|
+
} else {
|
|
1636
|
+
returnClause = Object.entries(fields).map(([field, alias]) => `${field} AS ${alias}`).join(", ");
|
|
1637
|
+
}
|
|
1638
|
+
return this.clone({ returnClause });
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* Add RETURN * clause
|
|
1642
|
+
*/
|
|
1643
|
+
returnAll() {
|
|
1644
|
+
return this.clone({ returnClause: "*" });
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Set fusion strategy for hybrid queries
|
|
1648
|
+
*
|
|
1649
|
+
* @param strategy - Fusion strategy
|
|
1650
|
+
* @param options - Fusion parameters
|
|
1651
|
+
*/
|
|
1652
|
+
fusion(strategy, options) {
|
|
1653
|
+
return this.clone({
|
|
1654
|
+
fusionOptions: {
|
|
1655
|
+
strategy,
|
|
1656
|
+
...options
|
|
1657
|
+
}
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Get the fusion options
|
|
1662
|
+
*/
|
|
1663
|
+
getFusionOptions() {
|
|
1664
|
+
return this.state.fusionOptions;
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Get all parameters
|
|
1668
|
+
*/
|
|
1669
|
+
getParams() {
|
|
1670
|
+
return { ...this.state.params };
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* Build the VelesQL query string
|
|
1674
|
+
*/
|
|
1675
|
+
toVelesQL() {
|
|
1676
|
+
if (this.state.matchClauses.length === 0) {
|
|
1677
|
+
throw new Error("Query must have at least one MATCH clause");
|
|
1678
|
+
}
|
|
1679
|
+
const parts = [];
|
|
1680
|
+
parts.push(`MATCH ${this.state.matchClauses.join(", ")}`);
|
|
1681
|
+
if (this.state.whereClauses.length > 0) {
|
|
1682
|
+
const whereStr = this.buildWhereClause();
|
|
1683
|
+
parts.push(`WHERE ${whereStr}`);
|
|
1684
|
+
}
|
|
1685
|
+
if (this.state.orderByClause) {
|
|
1686
|
+
parts.push(`ORDER BY ${this.state.orderByClause}`);
|
|
1687
|
+
}
|
|
1688
|
+
if (this.state.limitValue !== void 0) {
|
|
1689
|
+
parts.push(`LIMIT ${this.state.limitValue}`);
|
|
1690
|
+
}
|
|
1691
|
+
if (this.state.offsetValue !== void 0) {
|
|
1692
|
+
parts.push(`OFFSET ${this.state.offsetValue}`);
|
|
1693
|
+
}
|
|
1694
|
+
if (this.state.returnClause) {
|
|
1695
|
+
parts.push(`RETURN ${this.state.returnClause}`);
|
|
1696
|
+
}
|
|
1697
|
+
if (this.state.fusionOptions) {
|
|
1698
|
+
parts.push(`/* FUSION ${this.state.fusionOptions.strategy} */`);
|
|
1699
|
+
}
|
|
1700
|
+
return parts.join(" ");
|
|
1701
|
+
}
|
|
1702
|
+
formatLabel(label) {
|
|
1703
|
+
if (!label) return "";
|
|
1704
|
+
if (Array.isArray(label)) {
|
|
1705
|
+
return label.map((l) => `:${l}`).join("");
|
|
1706
|
+
}
|
|
1707
|
+
return `:${label}`;
|
|
1708
|
+
}
|
|
1709
|
+
formatRelationship(type, alias, options) {
|
|
1710
|
+
const aliasStr = alias ? alias : "";
|
|
1711
|
+
const hopsStr = this.formatHops(options);
|
|
1712
|
+
if (alias) {
|
|
1713
|
+
return `[${aliasStr}:${type}${hopsStr}]`;
|
|
1714
|
+
}
|
|
1715
|
+
return `[:${type}${hopsStr}]`;
|
|
1716
|
+
}
|
|
1717
|
+
formatHops(options) {
|
|
1718
|
+
if (!options?.minHops && !options?.maxHops) return "";
|
|
1719
|
+
const min = options.minHops ?? 1;
|
|
1720
|
+
const max = options.maxHops ?? "";
|
|
1721
|
+
return `*${min}..${max}`;
|
|
1722
|
+
}
|
|
1723
|
+
buildWhereClause() {
|
|
1724
|
+
if (this.state.whereClauses.length === 0) return "";
|
|
1725
|
+
const first = this.state.whereClauses[0];
|
|
1726
|
+
if (!first) return "";
|
|
1727
|
+
let result = first;
|
|
1728
|
+
for (let i = 1; i < this.state.whereClauses.length; i++) {
|
|
1729
|
+
const operator = this.state.whereOperators[i - 1] ?? "AND";
|
|
1730
|
+
const clause = this.state.whereClauses[i];
|
|
1731
|
+
if (clause) {
|
|
1732
|
+
result += ` ${operator} ${clause}`;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
return result;
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
function velesql() {
|
|
1739
|
+
return new VelesQLBuilder();
|
|
1740
|
+
}
|
|
1370
1741
|
export {
|
|
1371
1742
|
ConnectionError,
|
|
1372
1743
|
NotFoundError,
|
|
@@ -1374,5 +1745,7 @@ export {
|
|
|
1374
1745
|
ValidationError,
|
|
1375
1746
|
VelesDB,
|
|
1376
1747
|
VelesDBError,
|
|
1377
|
-
|
|
1748
|
+
VelesQLBuilder,
|
|
1749
|
+
WasmBackend,
|
|
1750
|
+
velesql
|
|
1378
1751
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wiscale/velesdb-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "VelesDB TypeScript SDK: The Local Vector Database for AI & RAG. Microsecond semantic search in Browser & Node.js.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"vitest": "^4.0.16"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@wiscale/velesdb-wasm": "^1.
|
|
69
|
+
"@wiscale/velesdb-wasm": "^1.4.0"
|
|
70
70
|
},
|
|
71
71
|
"engines": {
|
|
72
72
|
"node": ">=18.0.0"
|