@capgo/capacitor-fast-sql 8.0.36 → 8.0.38
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 +57 -0
- package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +1 -1
- package/dist/esm/fast-sql.d.ts +15 -0
- package/dist/esm/fast-sql.d.ts.map +1 -1
- package/dist/esm/fast-sql.js +51 -1
- package/dist/esm/helpers.d.ts +2 -0
- package/dist/esm/helpers.d.ts.map +1 -1
- package/dist/esm/helpers.js +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/vector-store.d.ts +128 -0
- package/dist/esm/vector-store.d.ts.map +1 -0
- package/dist/esm/vector-store.js +377 -0
- package/dist/plugin.cjs.js +429 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +429 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +1 -1
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLDatabase.swift +9 -10
- package/package.json +1 -1
package/dist/plugin.cjs.js
CHANGED
|
@@ -401,6 +401,7 @@ class FastSQL {
|
|
|
401
401
|
// Check if already connected
|
|
402
402
|
const existing = this.connections.get(options.database);
|
|
403
403
|
if (existing) {
|
|
404
|
+
this.sharedConnections.add(options.database);
|
|
404
405
|
return existing;
|
|
405
406
|
}
|
|
406
407
|
// Connect via native plugin
|
|
@@ -424,14 +425,22 @@ class FastSQL {
|
|
|
424
425
|
* @param database - Database name to close
|
|
425
426
|
*/
|
|
426
427
|
static async disconnect(database) {
|
|
428
|
+
var _a;
|
|
427
429
|
const connection = this.connections.get(database);
|
|
428
430
|
if (!connection) {
|
|
429
431
|
throw new Error(`Database '${database}' is not connected`);
|
|
430
432
|
}
|
|
433
|
+
if (((_a = this.connectionRetainers.get(database)) !== null && _a !== void 0 ? _a : 0) > 0) {
|
|
434
|
+
this.pendingDisconnects.add(database);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
431
437
|
// Disconnect via native plugin
|
|
432
438
|
await CapgoCapacitorFastSql.disconnect({ database });
|
|
433
439
|
// Remove connection
|
|
434
440
|
this.connections.delete(database);
|
|
441
|
+
this.sharedConnections.delete(database);
|
|
442
|
+
this.connectionRetainers.delete(database);
|
|
443
|
+
this.pendingDisconnects.delete(database);
|
|
435
444
|
}
|
|
436
445
|
/**
|
|
437
446
|
* Get an existing connection
|
|
@@ -442,12 +451,50 @@ class FastSQL {
|
|
|
442
451
|
static getConnection(database) {
|
|
443
452
|
return this.connections.get(database) || null;
|
|
444
453
|
}
|
|
454
|
+
/**
|
|
455
|
+
* Check whether a connection has been handed out more than once.
|
|
456
|
+
*/
|
|
457
|
+
static isConnectionShared(database) {
|
|
458
|
+
return this.sharedConnections.has(database);
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Temporarily retain a connection for helpers that share cached connections.
|
|
462
|
+
*/
|
|
463
|
+
static retainConnection(database) {
|
|
464
|
+
var _a;
|
|
465
|
+
if (!this.connections.has(database)) {
|
|
466
|
+
throw new Error(`Database '${database}' is not connected`);
|
|
467
|
+
}
|
|
468
|
+
this.connectionRetainers.set(database, ((_a = this.connectionRetainers.get(database)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Release a retained connection. Returns true when a pending disconnect closed it.
|
|
472
|
+
*/
|
|
473
|
+
static async releaseConnection(database) {
|
|
474
|
+
var _a;
|
|
475
|
+
const retainers = (_a = this.connectionRetainers.get(database)) !== null && _a !== void 0 ? _a : 0;
|
|
476
|
+
if (retainers > 1) {
|
|
477
|
+
this.connectionRetainers.set(database, retainers - 1);
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
this.connectionRetainers.delete(database);
|
|
481
|
+
if (this.pendingDisconnects.has(database)) {
|
|
482
|
+
this.pendingDisconnects.delete(database);
|
|
483
|
+
await this.disconnect(database);
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
445
488
|
/**
|
|
446
489
|
* Close all open connections
|
|
447
490
|
*/
|
|
448
491
|
static async disconnectAll() {
|
|
449
492
|
const databases = Array.from(this.connections.keys());
|
|
450
|
-
await Promise.all(databases.map((db) =>
|
|
493
|
+
await Promise.all(databases.map((db) => {
|
|
494
|
+
this.connectionRetainers.delete(db);
|
|
495
|
+
this.pendingDisconnects.delete(db);
|
|
496
|
+
return this.disconnect(db);
|
|
497
|
+
}));
|
|
451
498
|
}
|
|
452
499
|
/**
|
|
453
500
|
* Get list of all open database connections
|
|
@@ -459,6 +506,9 @@ class FastSQL {
|
|
|
459
506
|
}
|
|
460
507
|
}
|
|
461
508
|
FastSQL.connections = new Map();
|
|
509
|
+
FastSQL.sharedConnections = new Set();
|
|
510
|
+
FastSQL.connectionRetainers = new Map();
|
|
511
|
+
FastSQL.pendingDisconnects = new Set();
|
|
462
512
|
|
|
463
513
|
/**
|
|
464
514
|
* Key-value storage backed by the FastSQL database connection.
|
|
@@ -643,6 +693,383 @@ class KeyValueStore {
|
|
|
643
693
|
}
|
|
644
694
|
}
|
|
645
695
|
|
|
696
|
+
const DEFAULT_STORE = 'default';
|
|
697
|
+
const VECTOR_TABLE = '__fast_sql_vector_store';
|
|
698
|
+
const VECTOR_META_TABLE = '__fast_sql_vector_store_meta';
|
|
699
|
+
/**
|
|
700
|
+
* SQLite-backed VectorStore for local RAG usage.
|
|
701
|
+
*
|
|
702
|
+
* The helper is optional and dependency-free: pass your own embeddings provider,
|
|
703
|
+
* or use precomputed embeddings with `embeddingDimension`. Multiple stores can
|
|
704
|
+
* share one database by choosing different `store` names.
|
|
705
|
+
*/
|
|
706
|
+
class FastSQLVectorStore {
|
|
707
|
+
constructor(connection, options = {}) {
|
|
708
|
+
var _a;
|
|
709
|
+
this.initialized = false;
|
|
710
|
+
this.ownsConnection = false;
|
|
711
|
+
this.shouldDisconnectConnection = false;
|
|
712
|
+
this.closed = false;
|
|
713
|
+
this.connection = connection;
|
|
714
|
+
this.store = (_a = options.store) !== null && _a !== void 0 ? _a : DEFAULT_STORE;
|
|
715
|
+
this.embeddings = options.embeddings;
|
|
716
|
+
this.configuredEmbeddingDim = options.embeddingDimension;
|
|
717
|
+
this.embeddingDim = options.embeddingDimension;
|
|
718
|
+
}
|
|
719
|
+
static retainConnection(database) {
|
|
720
|
+
var _a;
|
|
721
|
+
this.connectionRefs.set(database, ((_a = this.connectionRefs.get(database)) !== null && _a !== void 0 ? _a : 0) + 1);
|
|
722
|
+
}
|
|
723
|
+
static releaseConnection(database) {
|
|
724
|
+
var _a;
|
|
725
|
+
const refs = (_a = this.connectionRefs.get(database)) !== null && _a !== void 0 ? _a : 0;
|
|
726
|
+
if (refs > 1) {
|
|
727
|
+
this.connectionRefs.set(database, refs - 1);
|
|
728
|
+
return false;
|
|
729
|
+
}
|
|
730
|
+
this.connectionRefs.delete(database);
|
|
731
|
+
this.ownedConnections.delete(database);
|
|
732
|
+
return true;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Open a vector store from database connection options.
|
|
736
|
+
*/
|
|
737
|
+
static async open(options) {
|
|
738
|
+
const existing = FastSQL.getConnection(options.database);
|
|
739
|
+
const ownsExistingVectorConnection = existing && FastSQLVectorStore.connectionRefs.has(options.database);
|
|
740
|
+
const connection = ownsExistingVectorConnection ? existing : await FastSQL.connect(options);
|
|
741
|
+
const vectorStore = new FastSQLVectorStore(connection, options);
|
|
742
|
+
vectorStore.ownsConnection = true;
|
|
743
|
+
vectorStore.shouldDisconnectConnection = !existing || FastSQLVectorStore.ownedConnections.has(options.database);
|
|
744
|
+
FastSQLVectorStore.retainConnection(connection.getDatabaseName());
|
|
745
|
+
FastSQL.retainConnection(connection.getDatabaseName());
|
|
746
|
+
if (vectorStore.shouldDisconnectConnection) {
|
|
747
|
+
FastSQLVectorStore.ownedConnections.add(connection.getDatabaseName());
|
|
748
|
+
}
|
|
749
|
+
try {
|
|
750
|
+
await vectorStore.load();
|
|
751
|
+
return vectorStore;
|
|
752
|
+
}
|
|
753
|
+
catch (error) {
|
|
754
|
+
await vectorStore.unload();
|
|
755
|
+
throw error;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Create a vector store from an existing SQL connection.
|
|
760
|
+
* The caller keeps ownership of the connection.
|
|
761
|
+
*/
|
|
762
|
+
static async fromConnection(connection, options = {}) {
|
|
763
|
+
const vectorStore = new FastSQLVectorStore(connection, options);
|
|
764
|
+
await vectorStore.load();
|
|
765
|
+
return vectorStore;
|
|
766
|
+
}
|
|
767
|
+
getStoreName() {
|
|
768
|
+
return this.store;
|
|
769
|
+
}
|
|
770
|
+
getDatabaseName() {
|
|
771
|
+
return this.connection.getDatabaseName();
|
|
772
|
+
}
|
|
773
|
+
async load() {
|
|
774
|
+
var _a, _b;
|
|
775
|
+
this.assertOpen();
|
|
776
|
+
if (this.initialized) {
|
|
777
|
+
return this;
|
|
778
|
+
}
|
|
779
|
+
await ((_b = (_a = this.embeddings) === null || _a === void 0 ? void 0 : _a.load) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
780
|
+
await this.ensureSchema();
|
|
781
|
+
await this.ensureStoreDimension();
|
|
782
|
+
this.initialized = true;
|
|
783
|
+
return this;
|
|
784
|
+
}
|
|
785
|
+
async unload() {
|
|
786
|
+
var _a, _b;
|
|
787
|
+
if (this.closed) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
await ((_b = (_a = this.embeddings) === null || _a === void 0 ? void 0 : _a.unload) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
791
|
+
if (this.ownsConnection) {
|
|
792
|
+
const database = this.connection.getDatabaseName();
|
|
793
|
+
const releasedLastVectorStore = FastSQLVectorStore.releaseConnection(database);
|
|
794
|
+
const closedFromPendingDisconnect = await FastSQL.releaseConnection(database);
|
|
795
|
+
if (releasedLastVectorStore &&
|
|
796
|
+
this.shouldDisconnectConnection &&
|
|
797
|
+
!FastSQL.isConnectionShared(database) &&
|
|
798
|
+
!closedFromPendingDisconnect) {
|
|
799
|
+
await FastSQL.disconnect(database);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
this.initialized = false;
|
|
803
|
+
this.closed = true;
|
|
804
|
+
}
|
|
805
|
+
async close() {
|
|
806
|
+
await this.unload();
|
|
807
|
+
}
|
|
808
|
+
async add(params) {
|
|
809
|
+
await this.ensureReady();
|
|
810
|
+
const { id = this.createId(), document, embedding, metadata } = params;
|
|
811
|
+
if (document === undefined && embedding === undefined) {
|
|
812
|
+
throw new Error('document and embedding cannot both be undefined');
|
|
813
|
+
}
|
|
814
|
+
const existing = await this.connection.query(`SELECT 1 FROM ${VECTOR_TABLE} WHERE store = ? AND id = ? LIMIT 1`, [
|
|
815
|
+
this.store,
|
|
816
|
+
id,
|
|
817
|
+
]);
|
|
818
|
+
if (existing.length > 0) {
|
|
819
|
+
throw new Error(`id already exists: ${id}`);
|
|
820
|
+
}
|
|
821
|
+
const resolvedEmbedding = embedding !== null && embedding !== void 0 ? embedding : (await this.embedDocument(document));
|
|
822
|
+
await this.ensureEmbeddingDimension(resolvedEmbedding);
|
|
823
|
+
const now = Date.now();
|
|
824
|
+
await this.connection.run(`INSERT INTO ${VECTOR_TABLE} (store, id, document, embedding, metadata, created_at, updated_at)
|
|
825
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
|
826
|
+
this.store,
|
|
827
|
+
id,
|
|
828
|
+
document !== null && document !== void 0 ? document : '',
|
|
829
|
+
this.encodeEmbedding(resolvedEmbedding),
|
|
830
|
+
this.encodeMetadata(metadata),
|
|
831
|
+
now,
|
|
832
|
+
now,
|
|
833
|
+
]);
|
|
834
|
+
return id;
|
|
835
|
+
}
|
|
836
|
+
async update(params) {
|
|
837
|
+
var _a, _b;
|
|
838
|
+
await this.ensureReady();
|
|
839
|
+
const rows = await this.connection.query(`SELECT id, document, embedding, metadata FROM ${VECTOR_TABLE} WHERE store = ? AND id = ? LIMIT 1`, [this.store, params.id]);
|
|
840
|
+
if (rows.length === 0) {
|
|
841
|
+
throw new Error(`id not found: ${params.id}`);
|
|
842
|
+
}
|
|
843
|
+
const current = this.rowToGetResult(rows[0]);
|
|
844
|
+
const document = (_a = params.document) !== null && _a !== void 0 ? _a : current.document;
|
|
845
|
+
const embedding = (_b = params.embedding) !== null && _b !== void 0 ? _b : (params.document !== undefined ? await this.embedDocument(params.document) : current.embedding);
|
|
846
|
+
const metadata = params.metadata === undefined ? current.metadata : params.metadata;
|
|
847
|
+
await this.ensureEmbeddingDimension(embedding);
|
|
848
|
+
await this.connection.run(`UPDATE ${VECTOR_TABLE}
|
|
849
|
+
SET document = ?, embedding = ?, metadata = ?, updated_at = ?
|
|
850
|
+
WHERE store = ? AND id = ?`, [document, this.encodeEmbedding(embedding), this.encodeMetadata(metadata), Date.now(), this.store, params.id]);
|
|
851
|
+
}
|
|
852
|
+
async delete(params) {
|
|
853
|
+
await this.ensureReady();
|
|
854
|
+
const rows = await this.getStoreRows();
|
|
855
|
+
const ids = rows
|
|
856
|
+
.map((row) => this.rowToGetResult(row))
|
|
857
|
+
.filter(params.predicate)
|
|
858
|
+
.map((row) => row.id);
|
|
859
|
+
for (const id of ids) {
|
|
860
|
+
await this.connection.run(`DELETE FROM ${VECTOR_TABLE} WHERE store = ? AND id = ?`, [this.store, id]);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
async query(params) {
|
|
864
|
+
await this.ensureReady();
|
|
865
|
+
const { queryText, queryEmbedding, nResults, predicate } = params;
|
|
866
|
+
if (queryText === undefined && queryEmbedding === undefined) {
|
|
867
|
+
throw new Error('queryText and queryEmbedding cannot both be undefined');
|
|
868
|
+
}
|
|
869
|
+
if (nResults !== undefined && nResults < 0) {
|
|
870
|
+
throw new Error('nResults cannot be negative');
|
|
871
|
+
}
|
|
872
|
+
const searchEmbedding = queryEmbedding !== null && queryEmbedding !== void 0 ? queryEmbedding : (await this.embedDocument(queryText));
|
|
873
|
+
await this.ensureEmbeddingDimension(searchEmbedding);
|
|
874
|
+
const results = (await this.getStoreRows())
|
|
875
|
+
.map((row) => {
|
|
876
|
+
const item = this.rowToGetResult(row);
|
|
877
|
+
return Object.assign(Object.assign({}, item), { similarity: this.cosineSimilarity(item.embedding, searchEmbedding) });
|
|
878
|
+
})
|
|
879
|
+
.filter(predicate !== null && predicate !== void 0 ? predicate : (() => true))
|
|
880
|
+
.sort((a, b) => b.similarity - a.similarity);
|
|
881
|
+
return nResults === undefined ? results : results.slice(0, nResults);
|
|
882
|
+
}
|
|
883
|
+
/**
|
|
884
|
+
* Delete only this logical vector store. Other stores in the same database stay intact.
|
|
885
|
+
*/
|
|
886
|
+
async deleteVectorStore() {
|
|
887
|
+
await this.ensureReady();
|
|
888
|
+
await this.connection.run(`DELETE FROM ${VECTOR_TABLE} WHERE store = ?`, [this.store]);
|
|
889
|
+
await this.connection.run(`DELETE FROM ${VECTOR_META_TABLE} WHERE store = ?`, [this.store]);
|
|
890
|
+
this.embeddingDim = this.configuredEmbeddingDim;
|
|
891
|
+
if (this.embeddingDim !== undefined) {
|
|
892
|
+
await this.saveEmbeddingDimension();
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
async ensureReady() {
|
|
896
|
+
this.assertOpen();
|
|
897
|
+
if (!this.initialized) {
|
|
898
|
+
await this.load();
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
assertOpen() {
|
|
902
|
+
if (this.closed) {
|
|
903
|
+
throw new Error('Vector store is closed');
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
async ensureSchema() {
|
|
907
|
+
await this.connection.run(`CREATE TABLE IF NOT EXISTS ${VECTOR_TABLE} (
|
|
908
|
+
store TEXT NOT NULL,
|
|
909
|
+
id TEXT NOT NULL,
|
|
910
|
+
document TEXT NOT NULL,
|
|
911
|
+
embedding BLOB NOT NULL,
|
|
912
|
+
metadata TEXT DEFAULT NULL,
|
|
913
|
+
created_at INTEGER NOT NULL,
|
|
914
|
+
updated_at INTEGER NOT NULL,
|
|
915
|
+
PRIMARY KEY (store, id)
|
|
916
|
+
)`);
|
|
917
|
+
await this.connection.run(`CREATE INDEX IF NOT EXISTS ${VECTOR_TABLE}_store_idx ON ${VECTOR_TABLE} (store)`);
|
|
918
|
+
await this.connection.run(`CREATE TABLE IF NOT EXISTS ${VECTOR_META_TABLE} (
|
|
919
|
+
store TEXT PRIMARY KEY,
|
|
920
|
+
embedding_dim INTEGER NOT NULL
|
|
921
|
+
)`);
|
|
922
|
+
}
|
|
923
|
+
async ensureStoreDimension() {
|
|
924
|
+
const rows = await this.connection.query(`SELECT embedding_dim FROM ${VECTOR_META_TABLE} WHERE store = ? LIMIT 1`, [
|
|
925
|
+
this.store,
|
|
926
|
+
]);
|
|
927
|
+
const storedDim = this.parseStoredDimension(rows[0]);
|
|
928
|
+
if (storedDim !== undefined && this.embeddingDim !== undefined && storedDim !== this.embeddingDim) {
|
|
929
|
+
throw new Error(`embedding dimension ${this.embeddingDim} does not match existing store dimension ${storedDim}`);
|
|
930
|
+
}
|
|
931
|
+
if (this.embeddingDim === undefined) {
|
|
932
|
+
this.embeddingDim = storedDim !== null && storedDim !== void 0 ? storedDim : (this.embeddings ? (await this.embedDocument('dummy')).length : undefined);
|
|
933
|
+
}
|
|
934
|
+
if (this.embeddingDim !== undefined) {
|
|
935
|
+
await this.saveEmbeddingDimension();
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
parseStoredDimension(row) {
|
|
939
|
+
if (!row) {
|
|
940
|
+
return undefined;
|
|
941
|
+
}
|
|
942
|
+
const value = row.embedding_dim;
|
|
943
|
+
if (typeof value === 'number') {
|
|
944
|
+
return value;
|
|
945
|
+
}
|
|
946
|
+
if (typeof value === 'string') {
|
|
947
|
+
const parsed = Number(value);
|
|
948
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
949
|
+
}
|
|
950
|
+
return undefined;
|
|
951
|
+
}
|
|
952
|
+
async saveEmbeddingDimension() {
|
|
953
|
+
if (this.embeddingDim === undefined) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
await this.connection.run(`INSERT OR REPLACE INTO ${VECTOR_META_TABLE} (store, embedding_dim) VALUES (?, ?)`, [
|
|
957
|
+
this.store,
|
|
958
|
+
this.embeddingDim,
|
|
959
|
+
]);
|
|
960
|
+
}
|
|
961
|
+
async ensureEmbeddingDimension(embedding) {
|
|
962
|
+
this.validateEmbedding(embedding);
|
|
963
|
+
if (this.embeddingDim === undefined) {
|
|
964
|
+
this.embeddingDim = embedding.length;
|
|
965
|
+
await this.saveEmbeddingDimension();
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
if (embedding.length !== this.embeddingDim) {
|
|
969
|
+
throw new Error(`embedding dimension ${embedding.length} does not match vector store dimension ${this.embeddingDim}`);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
async embedDocument(document) {
|
|
973
|
+
if (document === undefined) {
|
|
974
|
+
throw new Error('document is required when embedding is not provided');
|
|
975
|
+
}
|
|
976
|
+
if (!this.embeddings) {
|
|
977
|
+
throw new Error('embeddings provider is required for text operations');
|
|
978
|
+
}
|
|
979
|
+
return this.embeddings.embed(document);
|
|
980
|
+
}
|
|
981
|
+
validateEmbedding(embedding) {
|
|
982
|
+
if (!Array.isArray(embedding) || embedding.length === 0) {
|
|
983
|
+
throw new Error('embedding must be a non-empty number array');
|
|
984
|
+
}
|
|
985
|
+
for (const value of embedding) {
|
|
986
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
987
|
+
throw new Error('embedding values must be finite numbers');
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
async getStoreRows() {
|
|
992
|
+
return this.connection.query(`SELECT id, document, embedding, metadata FROM ${VECTOR_TABLE} WHERE store = ? ORDER BY updated_at DESC`, [this.store]);
|
|
993
|
+
}
|
|
994
|
+
rowToGetResult(row) {
|
|
995
|
+
const result = {
|
|
996
|
+
id: String(row.id),
|
|
997
|
+
document: row.document === null || row.document === undefined ? '' : String(row.document),
|
|
998
|
+
embedding: this.decodeEmbedding(row.embedding),
|
|
999
|
+
};
|
|
1000
|
+
const metadata = this.decodeMetadata(row.metadata);
|
|
1001
|
+
if (metadata !== undefined) {
|
|
1002
|
+
result.metadata = metadata;
|
|
1003
|
+
}
|
|
1004
|
+
return result;
|
|
1005
|
+
}
|
|
1006
|
+
encodeEmbedding(embedding) {
|
|
1007
|
+
const bytes = new Uint8Array(embedding.length * Float32Array.BYTES_PER_ELEMENT);
|
|
1008
|
+
const view = new DataView(bytes.buffer);
|
|
1009
|
+
embedding.forEach((value, index) => view.setFloat32(index * Float32Array.BYTES_PER_ELEMENT, value, true));
|
|
1010
|
+
return bytes;
|
|
1011
|
+
}
|
|
1012
|
+
decodeEmbedding(value) {
|
|
1013
|
+
if (!(value instanceof Uint8Array)) {
|
|
1014
|
+
throw new Error('stored embedding is not binary data');
|
|
1015
|
+
}
|
|
1016
|
+
if (value.byteLength % Float32Array.BYTES_PER_ELEMENT !== 0) {
|
|
1017
|
+
throw new Error('stored embedding has invalid byte length');
|
|
1018
|
+
}
|
|
1019
|
+
const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
|
|
1020
|
+
const embedding = [];
|
|
1021
|
+
for (let offset = 0; offset < value.byteLength; offset += Float32Array.BYTES_PER_ELEMENT) {
|
|
1022
|
+
embedding.push(view.getFloat32(offset, true));
|
|
1023
|
+
}
|
|
1024
|
+
return embedding;
|
|
1025
|
+
}
|
|
1026
|
+
encodeMetadata(metadata) {
|
|
1027
|
+
return metadata ? JSON.stringify(metadata) : null;
|
|
1028
|
+
}
|
|
1029
|
+
decodeMetadata(value) {
|
|
1030
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
1031
|
+
return undefined;
|
|
1032
|
+
}
|
|
1033
|
+
try {
|
|
1034
|
+
const parsed = JSON.parse(value);
|
|
1035
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : undefined;
|
|
1036
|
+
}
|
|
1037
|
+
catch (_a) {
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
cosineSimilarity(a, b) {
|
|
1042
|
+
if (a.length !== b.length) {
|
|
1043
|
+
throw new Error(`embedding dimension ${b.length} does not match stored embedding dimension ${a.length}`);
|
|
1044
|
+
}
|
|
1045
|
+
let dot = 0;
|
|
1046
|
+
let normA = 0;
|
|
1047
|
+
let normB = 0;
|
|
1048
|
+
for (let i = 0; i < a.length; i++) {
|
|
1049
|
+
dot += a[i] * b[i];
|
|
1050
|
+
normA += a[i] * a[i];
|
|
1051
|
+
normB += b[i] * b[i];
|
|
1052
|
+
}
|
|
1053
|
+
if (normA === 0 || normB === 0) {
|
|
1054
|
+
return 0;
|
|
1055
|
+
}
|
|
1056
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
1057
|
+
}
|
|
1058
|
+
createId() {
|
|
1059
|
+
const cryptoApi = globalThis.crypto;
|
|
1060
|
+
if (typeof (cryptoApi === null || cryptoApi === void 0 ? void 0 : cryptoApi.randomUUID) === 'function') {
|
|
1061
|
+
return cryptoApi.randomUUID();
|
|
1062
|
+
}
|
|
1063
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
1064
|
+
const value = Math.floor(Math.random() * 16);
|
|
1065
|
+
const nibble = char === 'x' ? value : (value & 0x3) | 0x8;
|
|
1066
|
+
return nibble.toString(16);
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
FastSQLVectorStore.connectionRefs = new Map();
|
|
1071
|
+
FastSQLVectorStore.ownedConnections = new Set();
|
|
1072
|
+
|
|
646
1073
|
const DEFAULT_SQLJS_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js';
|
|
647
1074
|
const DEFAULT_WASM_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.wasm';
|
|
648
1075
|
/**
|
|
@@ -880,6 +1307,7 @@ var web = /*#__PURE__*/Object.freeze({
|
|
|
880
1307
|
|
|
881
1308
|
exports.CapgoCapacitorFastSql = CapgoCapacitorFastSql;
|
|
882
1309
|
exports.FastSQL = FastSQL;
|
|
1310
|
+
exports.FastSQLVectorStore = FastSQLVectorStore;
|
|
883
1311
|
exports.KeyValueStore = KeyValueStore;
|
|
884
1312
|
exports.NativeSQLConnection = NativeSQLConnection;
|
|
885
1313
|
exports.WebSQLConnection = WebSQLConnection;
|