@utaba/deep-memory-storage-sqlserver 0.1.0 → 0.3.0
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/dist/index.cjs +68 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -5
- package/dist/index.d.ts +18 -5
- package/dist/index.js +68 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { StorageProvider, SearchProvider, SearchableEntity } from '@utaba/deep-memory/providers';
|
|
1
|
+
import * as _utaba_deep_memory_types from '@utaba/deep-memory/types';
|
|
3
2
|
import { StorageRepositoryConfig, StoredRepository, RepositoryFilter, PaginatedResult, StoredRepositorySummary, RepositoryUpdate, RepositoryStats, MemoryVocabulary, PaginationOptions, VocabularyChangeRecord, StoredEntity, StoredEntityUpdate, StorageFindQuery, StoredRelationship, RelationshipQueryOptions, StorageExploreOptions, StorageNeighbourhood, StoragePathOptions, StoragePathResult, StorageTimelineOptions, StorageTimelineResult, ExportChunk, ImportChunk, BulkImportResult, SearchOptions, SearchHit } from '@utaba/deep-memory/types';
|
|
3
|
+
import sql from 'mssql';
|
|
4
|
+
import { StorageProvider, EnsureSchemaResult, SearchProvider, SearchableEntity } from '@utaba/deep-memory/providers';
|
|
4
5
|
|
|
5
6
|
/** Configuration for SqlServerStorageProvider */
|
|
6
7
|
interface SqlServerStorageProviderConfig {
|
|
@@ -19,12 +20,24 @@ declare class SqlServerStorageProvider implements StorageProvider {
|
|
|
19
20
|
private getPool;
|
|
20
21
|
initialise(): Promise<void>;
|
|
21
22
|
dispose(): Promise<void>;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Ensure the target database exists. If constructed with a sql.config and the
|
|
25
|
+
* database does not yet exist, creates it via a temporary connection to master,
|
|
26
|
+
* then (re)connects the main pool to the newly created database.
|
|
27
|
+
*
|
|
28
|
+
* @returns true if the database was created, false if it already existed.
|
|
29
|
+
*/
|
|
30
|
+
private ensureDatabase;
|
|
31
|
+
ensureSchema(): Promise<EnsureSchemaResult>;
|
|
23
32
|
createRepository(config: StorageRepositoryConfig): Promise<StoredRepository>;
|
|
24
33
|
getRepository(repositoryId: string): Promise<StoredRepository | null>;
|
|
25
34
|
listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>>;
|
|
26
35
|
updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository>;
|
|
27
|
-
deleteRepository(repositoryId: string): Promise<void>;
|
|
36
|
+
deleteRepository(repositoryId: string, _onProgress?: _utaba_deep_memory_types.DeleteProgressCallback): Promise<void>;
|
|
37
|
+
deleteAllContents(repositoryId: string, _onProgress?: _utaba_deep_memory_types.DeleteProgressCallback): Promise<{
|
|
38
|
+
deletedEntities: number;
|
|
39
|
+
deletedRelationships: number;
|
|
40
|
+
}>;
|
|
28
41
|
getRepositoryStats(repositoryId: string): Promise<RepositoryStats>;
|
|
29
42
|
getVocabulary(repositoryId: string): Promise<MemoryVocabulary>;
|
|
30
43
|
saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void>;
|
|
@@ -56,7 +69,7 @@ declare class SqlServerStorageProvider implements StorageProvider {
|
|
|
56
69
|
findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult>;
|
|
57
70
|
getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult>;
|
|
58
71
|
exportAll(repositoryId: string): AsyncIterable<ExportChunk>;
|
|
59
|
-
importBulk(repositoryId: string, data: ImportChunk[]): Promise<BulkImportResult>;
|
|
72
|
+
importBulk(repositoryId: string, data: ImportChunk[], _options?: _utaba_deep_memory_types.BulkImportOptions): Promise<BulkImportResult>;
|
|
60
73
|
/** Creates a TVP table from an array of string IDs (eliminates plan cache bloat from IN clauses). */
|
|
61
74
|
private createIdListTvp;
|
|
62
75
|
/** Returns a StoredEntity without the embedding column (lighter I/O). */
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { StorageProvider, SearchProvider, SearchableEntity } from '@utaba/deep-memory/providers';
|
|
1
|
+
import * as _utaba_deep_memory_types from '@utaba/deep-memory/types';
|
|
3
2
|
import { StorageRepositoryConfig, StoredRepository, RepositoryFilter, PaginatedResult, StoredRepositorySummary, RepositoryUpdate, RepositoryStats, MemoryVocabulary, PaginationOptions, VocabularyChangeRecord, StoredEntity, StoredEntityUpdate, StorageFindQuery, StoredRelationship, RelationshipQueryOptions, StorageExploreOptions, StorageNeighbourhood, StoragePathOptions, StoragePathResult, StorageTimelineOptions, StorageTimelineResult, ExportChunk, ImportChunk, BulkImportResult, SearchOptions, SearchHit } from '@utaba/deep-memory/types';
|
|
3
|
+
import sql from 'mssql';
|
|
4
|
+
import { StorageProvider, EnsureSchemaResult, SearchProvider, SearchableEntity } from '@utaba/deep-memory/providers';
|
|
4
5
|
|
|
5
6
|
/** Configuration for SqlServerStorageProvider */
|
|
6
7
|
interface SqlServerStorageProviderConfig {
|
|
@@ -19,12 +20,24 @@ declare class SqlServerStorageProvider implements StorageProvider {
|
|
|
19
20
|
private getPool;
|
|
20
21
|
initialise(): Promise<void>;
|
|
21
22
|
dispose(): Promise<void>;
|
|
22
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Ensure the target database exists. If constructed with a sql.config and the
|
|
25
|
+
* database does not yet exist, creates it via a temporary connection to master,
|
|
26
|
+
* then (re)connects the main pool to the newly created database.
|
|
27
|
+
*
|
|
28
|
+
* @returns true if the database was created, false if it already existed.
|
|
29
|
+
*/
|
|
30
|
+
private ensureDatabase;
|
|
31
|
+
ensureSchema(): Promise<EnsureSchemaResult>;
|
|
23
32
|
createRepository(config: StorageRepositoryConfig): Promise<StoredRepository>;
|
|
24
33
|
getRepository(repositoryId: string): Promise<StoredRepository | null>;
|
|
25
34
|
listRepositories(filter?: RepositoryFilter): Promise<PaginatedResult<StoredRepositorySummary>>;
|
|
26
35
|
updateRepository(repositoryId: string, updates: RepositoryUpdate): Promise<StoredRepository>;
|
|
27
|
-
deleteRepository(repositoryId: string): Promise<void>;
|
|
36
|
+
deleteRepository(repositoryId: string, _onProgress?: _utaba_deep_memory_types.DeleteProgressCallback): Promise<void>;
|
|
37
|
+
deleteAllContents(repositoryId: string, _onProgress?: _utaba_deep_memory_types.DeleteProgressCallback): Promise<{
|
|
38
|
+
deletedEntities: number;
|
|
39
|
+
deletedRelationships: number;
|
|
40
|
+
}>;
|
|
28
41
|
getRepositoryStats(repositoryId: string): Promise<RepositoryStats>;
|
|
29
42
|
getVocabulary(repositoryId: string): Promise<MemoryVocabulary>;
|
|
30
43
|
saveVocabulary(repositoryId: string, vocabulary: MemoryVocabulary): Promise<void>;
|
|
@@ -56,7 +69,7 @@ declare class SqlServerStorageProvider implements StorageProvider {
|
|
|
56
69
|
findPaths(repositoryId: string, sourceId: string, targetId: string, options: StoragePathOptions): Promise<StoragePathResult>;
|
|
57
70
|
getTimeline(repositoryId: string, entityId: string, options: StorageTimelineOptions): Promise<StorageTimelineResult>;
|
|
58
71
|
exportAll(repositoryId: string): AsyncIterable<ExportChunk>;
|
|
59
|
-
importBulk(repositoryId: string, data: ImportChunk[]): Promise<BulkImportResult>;
|
|
72
|
+
importBulk(repositoryId: string, data: ImportChunk[], _options?: _utaba_deep_memory_types.BulkImportOptions): Promise<BulkImportResult>;
|
|
60
73
|
/** Creates a TVP table from an array of string IDs (eliminates plan cache bloat from IN clauses). */
|
|
61
74
|
private createIdListTvp;
|
|
62
75
|
/** Returns a StoredEntity without the embedding column (lighter I/O). */
|
package/dist/index.js
CHANGED
|
@@ -431,7 +431,51 @@ var SqlServerStorageProvider = class {
|
|
|
431
431
|
}
|
|
432
432
|
this.pool = null;
|
|
433
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Ensure the target database exists. If constructed with a sql.config and the
|
|
436
|
+
* database does not yet exist, creates it via a temporary connection to master,
|
|
437
|
+
* then (re)connects the main pool to the newly created database.
|
|
438
|
+
*
|
|
439
|
+
* @returns true if the database was created, false if it already existed.
|
|
440
|
+
*/
|
|
441
|
+
async ensureDatabase() {
|
|
442
|
+
if (this.config.connection instanceof sql.ConnectionPool) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
const cfg = this.config.connection;
|
|
446
|
+
const dbName = cfg.database;
|
|
447
|
+
if (!dbName) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
let created = false;
|
|
451
|
+
const masterPool = new sql.ConnectionPool({ ...cfg, database: "master" });
|
|
452
|
+
try {
|
|
453
|
+
await masterPool.connect();
|
|
454
|
+
const result = await masterPool.request().input("dbName", sql.NVarChar, dbName).query(
|
|
455
|
+
`SELECT COUNT(*) AS cnt FROM sys.databases WHERE name = @dbName`
|
|
456
|
+
);
|
|
457
|
+
const exists = (result.recordset[0]?.cnt ?? 0) > 0;
|
|
458
|
+
if (!exists) {
|
|
459
|
+
if (!/^[A-Za-z0-9_-]+$/.test(dbName)) {
|
|
460
|
+
throw new ProviderError(
|
|
461
|
+
`Invalid database name '${dbName}'. Only alphanumeric characters, hyphens, and underscores are allowed.`
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
await masterPool.request().query(`CREATE DATABASE [${dbName}]`);
|
|
465
|
+
created = true;
|
|
466
|
+
}
|
|
467
|
+
} finally {
|
|
468
|
+
await masterPool.close();
|
|
469
|
+
}
|
|
470
|
+
if (!this.pool || !this.pool.connected) {
|
|
471
|
+
this.pool = new sql.ConnectionPool(cfg);
|
|
472
|
+
this.ownsPool = true;
|
|
473
|
+
await this.pool.connect();
|
|
474
|
+
}
|
|
475
|
+
return created;
|
|
476
|
+
}
|
|
434
477
|
async ensureSchema() {
|
|
478
|
+
const databaseCreated = await this.ensureDatabase();
|
|
435
479
|
const pool = this.getPool();
|
|
436
480
|
const metaCheck = await pool.request().query(
|
|
437
481
|
`SELECT COUNT(*) AS cnt FROM sys.tables WHERE name = 'dm_meta' AND schema_id = SCHEMA_ID('${this.schema}')`
|
|
@@ -448,7 +492,12 @@ var SqlServerStorageProvider = class {
|
|
|
448
492
|
);
|
|
449
493
|
}
|
|
450
494
|
if (currentVersion === SCHEMA_VERSION) {
|
|
451
|
-
return
|
|
495
|
+
return {
|
|
496
|
+
databaseCreated,
|
|
497
|
+
schemaCreated: false,
|
|
498
|
+
alreadyUpToDate: !databaseCreated,
|
|
499
|
+
schemaVersion: SCHEMA_VERSION
|
|
500
|
+
};
|
|
452
501
|
}
|
|
453
502
|
}
|
|
454
503
|
const ddl = getSchemaSQL(this.schema);
|
|
@@ -463,6 +512,12 @@ var SqlServerStorageProvider = class {
|
|
|
463
512
|
}
|
|
464
513
|
}
|
|
465
514
|
}
|
|
515
|
+
return {
|
|
516
|
+
databaseCreated,
|
|
517
|
+
schemaCreated: true,
|
|
518
|
+
alreadyUpToDate: false,
|
|
519
|
+
schemaVersion: SCHEMA_VERSION
|
|
520
|
+
};
|
|
466
521
|
}
|
|
467
522
|
// ─── Repository ──────────────────────────────────────────────────
|
|
468
523
|
async createRepository(config) {
|
|
@@ -612,13 +667,23 @@ var SqlServerStorageProvider = class {
|
|
|
612
667
|
if (!updated) throw new RepositoryNotFoundError(repositoryId);
|
|
613
668
|
return updated;
|
|
614
669
|
}
|
|
615
|
-
async deleteRepository(repositoryId) {
|
|
670
|
+
async deleteRepository(repositoryId, _onProgress) {
|
|
616
671
|
const pool = this.getPool();
|
|
617
672
|
const result = await pool.request().input("id", sql.UniqueIdentifier, repositoryId).query(`DELETE FROM ${this.t("dm_repositories")} WHERE [repository_id] = @id`);
|
|
618
673
|
if (result.rowsAffected[0] === 0) {
|
|
619
674
|
throw new RepositoryNotFoundError(repositoryId);
|
|
620
675
|
}
|
|
621
676
|
}
|
|
677
|
+
async deleteAllContents(repositoryId, _onProgress) {
|
|
678
|
+
await this.assertRepository(repositoryId);
|
|
679
|
+
const pool = this.getPool();
|
|
680
|
+
const relResult = await pool.request().input("id", sql.UniqueIdentifier, repositoryId).query(`DELETE FROM ${this.t("dm_relationships")} WHERE [repository_id] = @id`);
|
|
681
|
+
const entityResult = await pool.request().input("id", sql.UniqueIdentifier, repositoryId).query(`DELETE FROM ${this.t("dm_entities")} WHERE [repository_id] = @id`);
|
|
682
|
+
return {
|
|
683
|
+
deletedEntities: entityResult.rowsAffected[0] ?? 0,
|
|
684
|
+
deletedRelationships: relResult.rowsAffected[0] ?? 0
|
|
685
|
+
};
|
|
686
|
+
}
|
|
622
687
|
async getRepositoryStats(repositoryId) {
|
|
623
688
|
await this.assertRepository(repositoryId);
|
|
624
689
|
const pool = this.getPool();
|
|
@@ -1308,7 +1373,7 @@ var SqlServerStorageProvider = class {
|
|
|
1308
1373
|
}
|
|
1309
1374
|
}
|
|
1310
1375
|
}
|
|
1311
|
-
async importBulk(repositoryId, data) {
|
|
1376
|
+
async importBulk(repositoryId, data, _options) {
|
|
1312
1377
|
await this.assertRepository(repositoryId);
|
|
1313
1378
|
const pool = this.getPool();
|
|
1314
1379
|
let entitiesImported = 0;
|