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