@utaba/deep-memory 0.17.0 → 0.18.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/{StorageProvider-DDTLUcuj.d.ts → StorageProvider-B2p_XThQ.d.ts} +1 -1
- package/dist/{StorageProvider-DGH7bVuK.d.cts → StorageProvider-CadKZ85j.d.cts} +1 -1
- package/dist/index.cjs +51 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +51 -37
- package/dist/index.js.map +1 -1
- package/dist/{portability-Dbm6vCdD.d.cts → portability-CAeyzSCx.d.cts} +15 -5
- package/dist/{portability-Dbm6vCdD.d.ts → portability-CAeyzSCx.d.ts} +15 -5
- package/dist/providers/index.d.cts +4 -4
- package/dist/providers/index.d.ts +4 -4
- package/dist/testing/conformance.cjs +2 -2
- package/dist/testing/conformance.cjs.map +1 -1
- package/dist/testing/conformance.d.cts +2 -2
- package/dist/testing/conformance.d.ts +2 -2
- package/dist/testing/conformance.js +2 -2
- package/dist/testing/conformance.js.map +1 -1
- package/dist/{traversal-1f35drOx.d.cts → traversal-Dql81Wh4.d.ts} +12 -7
- package/dist/{traversal-OkXViSTI.d.ts → traversal-WLcdLN-Z.d.cts} +12 -7
- package/dist/types/index.d.cts +3 -3
- package/dist/types/index.d.ts +3 -3
- package/package.json +2 -2
|
@@ -473,8 +473,13 @@ interface SearchOptions extends PaginationOptions {
|
|
|
473
473
|
entityTypes?: string[];
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
/**
|
|
477
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Direction filter for relationship queries, relative to the queried entity.
|
|
478
|
+
* - `'out'` — edges where the entity is the source
|
|
479
|
+
* - `'in'` — edges where the entity is the target
|
|
480
|
+
* - `'both'` — edges in either direction
|
|
481
|
+
*/
|
|
482
|
+
type RelationshipDirection = 'out' | 'in' | 'both';
|
|
478
483
|
/** Public relationship representation */
|
|
479
484
|
interface Relationship {
|
|
480
485
|
id: string;
|
|
@@ -522,10 +527,15 @@ interface EnrichedRelationship {
|
|
|
522
527
|
bidirectional: boolean;
|
|
523
528
|
provenance: Provenance;
|
|
524
529
|
}
|
|
525
|
-
/**
|
|
530
|
+
/**
|
|
531
|
+
* Aggregated relationship counts by type, keyed by direction relative to the
|
|
532
|
+
* entity the summary belongs to.
|
|
533
|
+
* - `out` — edges where the entity is the source
|
|
534
|
+
* - `in` — edges where the entity is the target
|
|
535
|
+
*/
|
|
526
536
|
interface RelationshipSummary {
|
|
527
|
-
|
|
528
|
-
|
|
537
|
+
out: Record<string, number>;
|
|
538
|
+
in: Record<string, number>;
|
|
529
539
|
}
|
|
530
540
|
/** Result of a bulk relationship removal */
|
|
531
541
|
interface RemoveRelationshipsResult {
|
|
@@ -473,8 +473,13 @@ interface SearchOptions extends PaginationOptions {
|
|
|
473
473
|
entityTypes?: string[];
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
/**
|
|
477
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Direction filter for relationship queries, relative to the queried entity.
|
|
478
|
+
* - `'out'` — edges where the entity is the source
|
|
479
|
+
* - `'in'` — edges where the entity is the target
|
|
480
|
+
* - `'both'` — edges in either direction
|
|
481
|
+
*/
|
|
482
|
+
type RelationshipDirection = 'out' | 'in' | 'both';
|
|
478
483
|
/** Public relationship representation */
|
|
479
484
|
interface Relationship {
|
|
480
485
|
id: string;
|
|
@@ -522,10 +527,15 @@ interface EnrichedRelationship {
|
|
|
522
527
|
bidirectional: boolean;
|
|
523
528
|
provenance: Provenance;
|
|
524
529
|
}
|
|
525
|
-
/**
|
|
530
|
+
/**
|
|
531
|
+
* Aggregated relationship counts by type, keyed by direction relative to the
|
|
532
|
+
* entity the summary belongs to.
|
|
533
|
+
* - `out` — edges where the entity is the source
|
|
534
|
+
* - `in` — edges where the entity is the target
|
|
535
|
+
*/
|
|
526
536
|
interface RelationshipSummary {
|
|
527
|
-
|
|
528
|
-
|
|
537
|
+
out: Record<string, number>;
|
|
538
|
+
in: Record<string, number>;
|
|
529
539
|
}
|
|
530
540
|
/** Result of a bulk relationship removal */
|
|
531
541
|
interface RemoveRelationshipsResult {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { E as EnsureSchemaResult, a as EntityReadOptions, S as StorageProvider } from '../StorageProvider-
|
|
2
|
-
import { al as SearchOptions, T as PaginatedResult, ak as SearchHit } from '../portability-
|
|
3
|
-
import { f as TraversalSpec, d as TraversalResult } from '../traversal-
|
|
1
|
+
export { E as EnsureSchemaResult, a as EntityReadOptions, S as StorageProvider } from '../StorageProvider-CadKZ85j.cjs';
|
|
2
|
+
import { al as SearchOptions, T as PaginatedResult, ak as SearchHit } from '../portability-CAeyzSCx.cjs';
|
|
3
|
+
import { f as TraversalSpec, d as TraversalResult } from '../traversal-WLcdLN-Z.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* EmbeddingProvider — enables semantic search and vocabulary deduplication.
|
|
@@ -145,7 +145,7 @@ interface GraphTraversalCapabilities {
|
|
|
145
145
|
/** Whether the provider supports dedup across traversal results. */
|
|
146
146
|
supportsDedup: boolean;
|
|
147
147
|
/**
|
|
148
|
-
* Whether the provider can return relationship summaries (
|
|
148
|
+
* Whether the provider can return relationship summaries (out/in
|
|
149
149
|
* counts by type) natively in a single traversal query.
|
|
150
150
|
* When false, the library falls back to a batch fetch + local computation.
|
|
151
151
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { E as EnsureSchemaResult, a as EntityReadOptions, S as StorageProvider } from '../StorageProvider-
|
|
2
|
-
import { al as SearchOptions, T as PaginatedResult, ak as SearchHit } from '../portability-
|
|
3
|
-
import { f as TraversalSpec, d as TraversalResult } from '../traversal-
|
|
1
|
+
export { E as EnsureSchemaResult, a as EntityReadOptions, S as StorageProvider } from '../StorageProvider-B2p_XThQ.js';
|
|
2
|
+
import { al as SearchOptions, T as PaginatedResult, ak as SearchHit } from '../portability-CAeyzSCx.js';
|
|
3
|
+
import { f as TraversalSpec, d as TraversalResult } from '../traversal-Dql81Wh4.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* EmbeddingProvider — enables semantic search and vocabulary deduplication.
|
|
@@ -145,7 +145,7 @@ interface GraphTraversalCapabilities {
|
|
|
145
145
|
/** Whether the provider supports dedup across traversal results. */
|
|
146
146
|
supportsDedup: boolean;
|
|
147
147
|
/**
|
|
148
|
-
* Whether the provider can return relationship summaries (
|
|
148
|
+
* Whether the provider can return relationship summaries (out/in
|
|
149
149
|
* counts by type) natively in a single traversal query.
|
|
150
150
|
* When false, the library falls back to a batch fetch + local computation.
|
|
151
151
|
*/
|
|
@@ -285,10 +285,10 @@ function runStorageProviderConformanceTests(factory) {
|
|
|
285
285
|
(0, import_vitest.it)("filters relationships by direction", async () => {
|
|
286
286
|
await provider.createRelationship(repoId, makeRelationship("r1", "connects", "a", "b"));
|
|
287
287
|
await provider.createRelationship(repoId, makeRelationship("r2", "connects", "c", "a"));
|
|
288
|
-
const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "
|
|
288
|
+
const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "out" });
|
|
289
289
|
(0, import_vitest.expect)(outbound.items).toHaveLength(1);
|
|
290
290
|
(0, import_vitest.expect)(outbound.items[0].targetEntityId).toBe("b");
|
|
291
|
-
const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "
|
|
291
|
+
const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "in" });
|
|
292
292
|
(0, import_vitest.expect)(inbound.items).toHaveLength(1);
|
|
293
293
|
(0, import_vitest.expect)(inbound.items[0].sourceEntityId).toBe("c");
|
|
294
294
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers-builtin/conformance.ts"],"sourcesContent":["// Provider Conformance Test Suite\n// Any StorageProvider implementer can import and run these tests to verify conformance.\n//\n// Usage:\n// import { runStorageProviderConformanceTests } from '@utaba/deep-memory';\n// runStorageProviderConformanceTests(() => new MyStorageProvider());\n\nimport { describe, it, expect, beforeEach } from 'vitest';\nimport type { StorageProvider } from '../providers/StorageProvider.js';\nimport type { StoredEntity } from '../types/entities.js';\nimport type { StoredRelationship } from '../types/relationships.js';\nimport type { Provenance } from '../types/provenance.js';\n\nfunction makeProvenance(): Provenance {\n const now = new Date().toISOString();\n return {\n createdBy: 'conformance-test',\n createdByType: 'agent',\n createdAt: now,\n modifiedBy: 'conformance-test',\n modifiedByType: 'agent',\n modifiedAt: now,\n };\n}\n\nfunction makeEntity(id: string, type = 'test-type', label?: string): StoredEntity {\n return {\n id,\n slug: `${type}:${(label ?? id).toLowerCase().replace(/[^a-z0-9]+/g, '-')}`,\n entityType: type,\n label: label ?? id,\n summary: `Summary for ${id}`,\n properties: { key: 'value' },\n provenance: makeProvenance(),\n };\n}\n\nfunction makeRelationship(\n id: string,\n type: string,\n sourceId: string,\n targetId: string,\n bidirectional = false,\n): StoredRelationship {\n return {\n id,\n relationshipType: type,\n sourceEntityId: sourceId,\n targetEntityId: targetId,\n properties: {},\n bidirectional,\n provenance: makeProvenance(),\n };\n}\n\n/**\n * Run the full StorageProvider conformance test suite.\n *\n * @param factory - A function that creates a fresh, empty StorageProvider instance.\n * Called before each test to ensure isolation.\n */\nexport function runStorageProviderConformanceTests(\n factory: () => StorageProvider | Promise<StorageProvider>,\n): void {\n // Use a stable GUID so external cleanup scripts can target it\n const repoId = '40000000-0000-4000-a000-000000000001';\n\n let provider: StorageProvider;\n\n async function setup(): Promise<void> {\n provider = await factory();\n if (provider.initialize) await provider.initialize();\n\n await provider.createRepository({\n repositoryId: repoId,\n label: 'Conformance Test',\n governanceConfig: { mode: 'open' },\n createdAt: new Date().toISOString(),\n createdBy: 'conformance-test',\n });\n }\n\n describe('StorageProvider Conformance Tests', () => {\n beforeEach(async () => {\n await setup();\n });\n\n // ─── Repository ─────────────────────────────────────────\n\n describe('repository operations', () => {\n it('creates a repository', async () => {\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n expect(repo!.repositoryId).toBe(repoId);\n expect(repo!.label).toBe('Conformance Test');\n });\n\n it('returns null for non-existent repository', async () => {\n const repo = await provider.getRepository('ffffffff-ffff-4fff-afff-ffffffffffff');\n expect(repo).toBeNull();\n });\n\n it('lists repositories', async () => {\n const list = await provider.listRepositories();\n expect(list.items.length).toBeGreaterThanOrEqual(1);\n expect(list.items.some((r) => r.repositoryId === repoId)).toBe(true);\n });\n\n it('updates a repository', async () => {\n const updated = await provider.updateRepository(repoId, {\n label: 'Updated Label',\n description: 'Updated description',\n governanceConfig: { mode: 'open', defaultSimilarityThreshold: 0.4 },\n });\n expect(updated.label).toBe('Updated Label');\n expect(updated.description).toBe('Updated description');\n expect(updated.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n\n // Verify persistence\n const fetched = await provider.getRepository(repoId);\n expect(fetched!.label).toBe('Updated Label');\n expect(fetched!.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n });\n\n it('deletes a repository', async () => {\n await provider.deleteRepository(repoId);\n expect(await provider.getRepository(repoId)).toBeNull();\n });\n\n it('returns repository stats', async () => {\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n expect(typeof stats.vocabularyVersion).toBe('string');\n });\n });\n\n // ─── Vocabulary ─────────────────────────────────────────\n\n describe('vocabulary operations', () => {\n it('gets and saves vocabulary', async () => {\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n expect(typeof vocab.version).toBe('string');\n\n const updated = { ...vocab, version: '1.0.0' };\n await provider.saveVocabulary(repoId, updated);\n\n const fetched = await provider.getVocabulary(repoId);\n expect(fetched.version).toBe('1.0.0');\n });\n\n it('returns vocabulary change log', async () => {\n const log = await provider.getVocabularyChangeLog(repoId);\n expect(Array.isArray(log.items)).toBe(true);\n });\n });\n\n // ─── Entities ───────────────────────────────────────────\n\n describe('entity operations', () => {\n it('creates and retrieves an entity', async () => {\n const entity = makeEntity('e1');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntity(repoId, 'e1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.label).toBe('e1');\n });\n\n it('retrieves an entity by slug', async () => {\n const entity = makeEntity('e1', 'test-type', 'Alpha');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntityBySlug(repoId, entity.slug);\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.slug).toBe(entity.slug);\n });\n\n it('returns null for non-existent entity', async () => {\n const result = await provider.getEntity(repoId, 'nonexistent');\n expect(result).toBeNull();\n });\n\n it('returns null for non-existent slug', async () => {\n const result = await provider.getEntityBySlug(repoId, 'nonexistent:slug');\n expect(result).toBeNull();\n });\n\n it('batch retrieves entities', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n\n const map = await provider.getEntities(repoId, ['e1', 'e2', 'missing']);\n expect(map.size).toBe(2);\n expect(map.has('e1')).toBe(true);\n expect(map.has('e2')).toBe(true);\n expect(map.has('missing')).toBe(false);\n });\n\n it('updates an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const updated = await provider.updateEntity(repoId, 'e1', {\n label: 'Updated Label',\n provenance: makeProvenance(),\n });\n expect(updated.label).toBe('Updated Label');\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.label).toBe('Updated Label');\n });\n\n it('clears summary/data/dataFormat when null is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'starting summary',\n data: 'raw content',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n summary: null,\n data: null,\n dataFormat: null,\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBeUndefined();\n expect(fetched!.data).toBeUndefined();\n expect(fetched!.dataFormat).toBeUndefined();\n });\n\n it('preserves summary/data/dataFormat when undefined is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'keep me',\n data: 'keep me too',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n label: 'Renamed',\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBe('keep me');\n expect(fetched!.data).toBe('keep me too');\n expect(fetched!.dataFormat).toBe('text/plain');\n });\n\n it('deletes an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.deleteEntity(repoId, 'e1');\n expect(await provider.getEntity(repoId, 'e1')).toBeNull();\n });\n\n it('finds entities by search term', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'test-type', 'Beta'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'alpha',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by search term case-insensitively', async () => {\n // Locks the invariant that searchTerm matching is case-insensitive on\n // every provider. In-memory lowercases both sides; SQL Server's LIKE\n // is case-insensitive under the default *_CI_AS collation; Cosmos\n // routes through CONTAINS(..., @term, true) on the Document endpoint.\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'ALPHA',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by type filter', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'type-a', 'A'));\n await provider.createEntity(repoId, makeEntity('e2', 'type-b', 'B'));\n\n const result = await provider.findEntities(repoId, {\n entityTypes: ['type-a'],\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.entityType).toBe('type-a');\n });\n\n it('paginates find results', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n await provider.createEntity(repoId, makeEntity('e3'));\n\n const page1 = await provider.findEntities(repoId, { limit: 2, offset: 0 });\n expect(page1.items).toHaveLength(2);\n expect(page1.hasMore).toBe(true);\n\n const page2 = await provider.findEntities(repoId, { limit: 2, offset: 2 });\n expect(page2.items).toHaveLength(1);\n expect(page2.hasMore).toBe(false);\n });\n });\n\n // ─── Relationships ──────────────────────────────────────\n\n describe('relationship operations', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a'));\n await provider.createEntity(repoId, makeEntity('b'));\n await provider.createEntity(repoId, makeEntity('c'));\n });\n\n it('creates and retrieves a relationship', async () => {\n const rel = makeRelationship('r1', 'connects', 'a', 'b');\n await provider.createRelationship(repoId, rel);\n\n const retrieved = await provider.getRelationship(repoId, 'r1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.sourceEntityId).toBe('a');\n expect(retrieved!.targetEntityId).toBe('b');\n });\n\n it('returns null for non-existent relationship', async () => {\n expect(await provider.getRelationship(repoId, 'nonexistent')).toBeNull();\n });\n\n it('gets entity relationships', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const result = await provider.getEntityRelationships(repoId, 'a');\n expect(result.items).toHaveLength(2);\n });\n\n it('filters relationships by direction', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const outbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'outbound' });\n expect(outbound.items).toHaveLength(1);\n expect(outbound.items[0]!.targetEntityId).toBe('b');\n\n const inbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'inbound' });\n expect(inbound.items).toHaveLength(1);\n expect(inbound.items[0]!.sourceEntityId).toBe('c');\n });\n\n it('deletes a relationship', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.deleteRelationship(repoId, 'r1');\n expect(await provider.getRelationship(repoId, 'r1')).toBeNull();\n });\n });\n\n // ─── Graph Traversal ────────────────────────────────────\n\n describe('graph traversal', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a', 'node', 'A'));\n await provider.createEntity(repoId, makeEntity('b', 'node', 'B'));\n await provider.createEntity(repoId, makeEntity('c', 'node', 'C'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'links', 'b', 'c'));\n });\n\n it('explores neighborhood at depth 1', async () => {\n const result = await provider.exploreNeighborhood(repoId, 'a', {\n depth: 1,\n direction: 'both',\n limitPerType: 10,\n offsetPerType: 0,\n });\n expect(result.centerId).toBe('a');\n expect(result.layers).toHaveLength(1);\n });\n\n it('finds paths between connected entities', async () => {\n const result = await provider.findPaths(repoId, 'a', 'c', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('c');\n });\n\n it('returns empty paths when no connection', async () => {\n await provider.createEntity(repoId, makeEntity('isolated', 'node', 'Isolated'));\n const result = await provider.findPaths(repoId, 'a', 'isolated', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths).toHaveLength(0);\n });\n\n it('finds paths through non-bidirectional inbound edges', async () => {\n // Graph: a → b ← d (both edges are non-bidirectional)\n // Path from a to d should traverse: a →(outbound) b ←(inbound) d\n await provider.createEntity(repoId, makeEntity('d', 'node', 'D'));\n await provider.createRelationship(repoId, makeRelationship('r3', 'links', 'd', 'b'));\n const result = await provider.findPaths(repoId, 'a', 'd', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('d');\n });\n });\n\n // ─── Timeline ───────────────────────────────────────────\n\n describe('timeline', () => {\n it('returns timeline events', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const result = await provider.getTimeline(repoId, 'e1', {\n limit: 10,\n offset: 0,\n });\n expect(result.events.length).toBeGreaterThanOrEqual(1);\n });\n });\n\n // ─── Bulk Operations ────────────────────────────────────\n\n describe('bulk operations', () => {\n it('exports data', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n\n const chunks = [];\n for await (const chunk of provider.exportAll(repoId)) {\n chunks.push(chunk);\n }\n expect(chunks.length).toBeGreaterThanOrEqual(1);\n });\n\n it('imports data', async () => {\n const result = await provider.importBulk(repoId, [\n { entities: [makeEntity('imported-1'), makeEntity('imported-2')] },\n { relationships: [makeRelationship('ir1', 'links', 'imported-1', 'imported-2')] },\n ]);\n expect(result.entitiesImported).toBe(2);\n expect(result.relationshipsImported).toBe(1);\n\n // Verify imported data is accessible\n const e = await provider.getEntity(repoId, 'imported-1');\n expect(e).not.toBeNull();\n });\n });\n\n // ─── Delete All Contents ───────────────────────────────\n\n describe('deleteAllContents', () => {\n it('deletes all entities and relationships but preserves the repository', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(2);\n expect(result.deletedRelationships).toBe(1);\n\n // Repository still exists\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n\n // Vocabulary still exists\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n\n // Contents are gone\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n });\n\n it('returns zero counts on an empty repository', async () => {\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(0);\n expect(result.deletedRelationships).toBe(0);\n });\n });\n\n // ─── Stats after data ───────────────────────────────────\n\n describe('stats reflect data', () => {\n it('counts entities and relationships', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e3', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(3);\n expect(stats.relationshipCount).toBe(1);\n expect(stats.entityTypeBreakdown['alpha']).toBe(2);\n expect(stats.entityTypeBreakdown['beta']).toBe(1);\n expect(stats.relationshipTypeBreakdown['links']).toBe(1);\n });\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,oBAAiD;AAMjD,SAAS,iBAA6B;AACpC,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAO;AAAA,IACL,WAAW;AAAA,IACX,eAAe;AAAA,IACf,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,YAAY;AAAA,EACd;AACF;AAEA,SAAS,WAAW,IAAY,OAAO,aAAa,OAA8B;AAChF,SAAO;AAAA,IACL;AAAA,IACA,MAAM,GAAG,IAAI,KAAK,SAAS,IAAI,YAAY,EAAE,QAAQ,eAAe,GAAG,CAAC;AAAA,IACxE,YAAY;AAAA,IACZ,OAAO,SAAS;AAAA,IAChB,SAAS,eAAe,EAAE;AAAA,IAC1B,YAAY,EAAE,KAAK,QAAQ;AAAA,IAC3B,YAAY,eAAe;AAAA,EAC7B;AACF;AAEA,SAAS,iBACP,IACA,MACA,UACA,UACA,gBAAgB,OACI;AACpB,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,YAAY,CAAC;AAAA,IACb;AAAA,IACA,YAAY,eAAe;AAAA,EAC7B;AACF;AAQO,SAAS,mCACd,SACM;AAEN,QAAM,SAAS;AAEf,MAAI;AAEJ,iBAAe,QAAuB;AACpC,eAAW,MAAM,QAAQ;AACzB,QAAI,SAAS,WAAY,OAAM,SAAS,WAAW;AAEnD,UAAM,SAAS,iBAAiB;AAAA,MAC9B,cAAc;AAAA,MACd,OAAO;AAAA,MACP,kBAAkB,EAAE,MAAM,OAAO;AAAA,MACjC,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,8BAAS,qCAAqC,MAAM;AAClD,kCAAW,YAAY;AACrB,YAAM,MAAM;AAAA,IACd,CAAC;AAID,gCAAS,yBAAyB,MAAM;AACtC,4BAAG,wBAAwB,YAAY;AACrC,cAAM,OAAO,MAAM,SAAS,cAAc,MAAM;AAChD,kCAAO,IAAI,EAAE,IAAI,SAAS;AAC1B,kCAAO,KAAM,YAAY,EAAE,KAAK,MAAM;AACtC,kCAAO,KAAM,KAAK,EAAE,KAAK,kBAAkB;AAAA,MAC7C,CAAC;AAED,4BAAG,4CAA4C,YAAY;AACzD,cAAM,OAAO,MAAM,SAAS,cAAc,sCAAsC;AAChF,kCAAO,IAAI,EAAE,SAAS;AAAA,MACxB,CAAC;AAED,4BAAG,sBAAsB,YAAY;AACnC,cAAM,OAAO,MAAM,SAAS,iBAAiB;AAC7C,kCAAO,KAAK,MAAM,MAAM,EAAE,uBAAuB,CAAC;AAClD,kCAAO,KAAK,MAAM,KAAK,CAAC,MAAM,EAAE,iBAAiB,MAAM,CAAC,EAAE,KAAK,IAAI;AAAA,MACrE,CAAC;AAED,4BAAG,wBAAwB,YAAY;AACrC,cAAM,UAAU,MAAM,SAAS,iBAAiB,QAAQ;AAAA,UACtD,OAAO;AAAA,UACP,aAAa;AAAA,UACb,kBAAkB,EAAE,MAAM,QAAQ,4BAA4B,IAAI;AAAA,QACpE,CAAC;AACD,kCAAO,QAAQ,KAAK,EAAE,KAAK,eAAe;AAC1C,kCAAO,QAAQ,WAAW,EAAE,KAAK,qBAAqB;AACtD,kCAAO,QAAQ,iBAAiB,0BAA0B,EAAE,KAAK,GAAG;AAGpE,cAAM,UAAU,MAAM,SAAS,cAAc,MAAM;AACnD,kCAAO,QAAS,KAAK,EAAE,KAAK,eAAe;AAC3C,kCAAO,QAAS,iBAAiB,0BAA0B,EAAE,KAAK,GAAG;AAAA,MACvE,CAAC;AAED,4BAAG,wBAAwB,YAAY;AACrC,cAAM,SAAS,iBAAiB,MAAM;AACtC,kCAAO,MAAM,SAAS,cAAc,MAAM,CAAC,EAAE,SAAS;AAAA,MACxD,CAAC;AAED,4BAAG,4BAA4B,YAAY;AACzC,cAAM,QAAQ,MAAM,SAAS,mBAAmB,MAAM;AACtD,kCAAO,MAAM,WAAW,EAAE,KAAK,CAAC;AAChC,kCAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC;AACtC,kCAAO,OAAO,MAAM,iBAAiB,EAAE,KAAK,QAAQ;AAAA,MACtD,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,yBAAyB,MAAM;AACtC,4BAAG,6BAA6B,YAAY;AAC1C,cAAM,QAAQ,MAAM,SAAS,cAAc,MAAM;AACjD,kCAAO,KAAK,EAAE,YAAY;AAC1B,kCAAO,OAAO,MAAM,OAAO,EAAE,KAAK,QAAQ;AAE1C,cAAM,UAAU,EAAE,GAAG,OAAO,SAAS,QAAQ;AAC7C,cAAM,SAAS,eAAe,QAAQ,OAAO;AAE7C,cAAM,UAAU,MAAM,SAAS,cAAc,MAAM;AACnD,kCAAO,QAAQ,OAAO,EAAE,KAAK,OAAO;AAAA,MACtC,CAAC;AAED,4BAAG,iCAAiC,YAAY;AAC9C,cAAM,MAAM,MAAM,SAAS,uBAAuB,MAAM;AACxD,kCAAO,MAAM,QAAQ,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI;AAAA,MAC5C,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,qBAAqB,MAAM;AAClC,4BAAG,mCAAmC,YAAY;AAChD,cAAM,SAAS,WAAW,IAAI;AAC9B,cAAM,SAAS,aAAa,QAAQ,MAAM;AAE1C,cAAM,YAAY,MAAM,SAAS,UAAU,QAAQ,IAAI;AACvD,kCAAO,SAAS,EAAE,IAAI,SAAS;AAC/B,kCAAO,UAAW,EAAE,EAAE,KAAK,IAAI;AAC/B,kCAAO,UAAW,KAAK,EAAE,KAAK,IAAI;AAAA,MACpC,CAAC;AAED,4BAAG,+BAA+B,YAAY;AAC5C,cAAM,SAAS,WAAW,MAAM,aAAa,OAAO;AACpD,cAAM,SAAS,aAAa,QAAQ,MAAM;AAE1C,cAAM,YAAY,MAAM,SAAS,gBAAgB,QAAQ,OAAO,IAAI;AACpE,kCAAO,SAAS,EAAE,IAAI,SAAS;AAC/B,kCAAO,UAAW,EAAE,EAAE,KAAK,IAAI;AAC/B,kCAAO,UAAW,IAAI,EAAE,KAAK,OAAO,IAAI;AAAA,MAC1C,CAAC;AAED,4BAAG,wCAAwC,YAAY;AACrD,cAAM,SAAS,MAAM,SAAS,UAAU,QAAQ,aAAa;AAC7D,kCAAO,MAAM,EAAE,SAAS;AAAA,MAC1B,CAAC;AAED,4BAAG,sCAAsC,YAAY;AACnD,cAAM,SAAS,MAAM,SAAS,gBAAgB,QAAQ,kBAAkB;AACxE,kCAAO,MAAM,EAAE,SAAS;AAAA,MAC1B,CAAC;AAED,4BAAG,4BAA4B,YAAY;AACzC,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AAEpD,cAAM,MAAM,MAAM,SAAS,YAAY,QAAQ,CAAC,MAAM,MAAM,SAAS,CAAC;AACtE,kCAAO,IAAI,IAAI,EAAE,KAAK,CAAC;AACvB,kCAAO,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;AAC/B,kCAAO,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;AAC/B,kCAAO,IAAI,IAAI,SAAS,CAAC,EAAE,KAAK,KAAK;AAAA,MACvC,CAAC;AAED,4BAAG,qBAAqB,YAAY;AAClC,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,UAAU,MAAM,SAAS,aAAa,QAAQ,MAAM;AAAA,UACxD,OAAO;AAAA,UACP,YAAY,eAAe;AAAA,QAC7B,CAAC;AACD,kCAAO,QAAQ,KAAK,EAAE,KAAK,eAAe;AAE1C,cAAM,UAAU,MAAM,SAAS,UAAU,QAAQ,IAAI;AACrD,kCAAO,QAAS,KAAK,EAAE,KAAK,eAAe;AAAA,MAC7C,CAAC;AAED,4BAAG,sDAAsD,YAAY;AACnE,cAAM,SAAuB;AAAA,UAC3B,GAAG,WAAW,IAAI;AAAA,UAClB,SAAS;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,QACd;AACA,cAAM,SAAS,aAAa,QAAQ,MAAM;AAE1C,cAAM,SAAS,aAAa,QAAQ,MAAM;AAAA,UACxC,SAAS;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,YAAY,eAAe;AAAA,QAC7B,CAAC;AAED,cAAM,UAAU,MAAM,SAAS,UAAU,QAAQ,IAAI;AACrD,kCAAO,QAAS,OAAO,EAAE,cAAc;AACvC,kCAAO,QAAS,IAAI,EAAE,cAAc;AACpC,kCAAO,QAAS,UAAU,EAAE,cAAc;AAAA,MAC5C,CAAC;AAED,4BAAG,8DAA8D,YAAY;AAC3E,cAAM,SAAuB;AAAA,UAC3B,GAAG,WAAW,IAAI;AAAA,UAClB,SAAS;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,QACd;AACA,cAAM,SAAS,aAAa,QAAQ,MAAM;AAE1C,cAAM,SAAS,aAAa,QAAQ,MAAM;AAAA,UACxC,OAAO;AAAA,UACP,YAAY,eAAe;AAAA,QAC7B,CAAC;AAED,cAAM,UAAU,MAAM,SAAS,UAAU,QAAQ,IAAI;AACrD,kCAAO,QAAS,OAAO,EAAE,KAAK,SAAS;AACvC,kCAAO,QAAS,IAAI,EAAE,KAAK,aAAa;AACxC,kCAAO,QAAS,UAAU,EAAE,KAAK,YAAY;AAAA,MAC/C,CAAC;AAED,4BAAG,qBAAqB,YAAY;AAClC,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,SAAS,aAAa,QAAQ,IAAI;AACxC,kCAAO,MAAM,SAAS,UAAU,QAAQ,IAAI,CAAC,EAAE,SAAS;AAAA,MAC1D,CAAC;AAED,4BAAG,iCAAiC,YAAY;AAC9C,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,aAAa,OAAO,CAAC;AAC1E,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,aAAa,MAAM,CAAC;AAEzE,cAAM,SAAS,MAAM,SAAS,aAAa,QAAQ;AAAA,UACjD,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,KAAK,EAAE,aAAa,CAAC;AACnC,kCAAO,OAAO,MAAM,CAAC,EAAG,KAAK,EAAE,KAAK,OAAO;AAAA,MAC7C,CAAC;AAED,4BAAG,oDAAoD,YAAY;AAKjE,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,aAAa,OAAO,CAAC;AAE1E,cAAM,SAAS,MAAM,SAAS,aAAa,QAAQ;AAAA,UACjD,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,KAAK,EAAE,aAAa,CAAC;AACnC,kCAAO,OAAO,MAAM,CAAC,EAAG,KAAK,EAAE,KAAK,OAAO;AAAA,MAC7C,CAAC;AAED,4BAAG,iCAAiC,YAAY;AAC9C,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,UAAU,GAAG,CAAC;AACnE,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,UAAU,GAAG,CAAC;AAEnE,cAAM,SAAS,MAAM,SAAS,aAAa,QAAQ;AAAA,UACjD,aAAa,CAAC,QAAQ;AAAA,UACtB,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,KAAK,EAAE,aAAa,CAAC;AACnC,kCAAO,OAAO,MAAM,CAAC,EAAG,UAAU,EAAE,KAAK,QAAQ;AAAA,MACnD,CAAC;AAED,4BAAG,0BAA0B,YAAY;AACvC,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AAEpD,cAAM,QAAQ,MAAM,SAAS,aAAa,QAAQ,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AACzE,kCAAO,MAAM,KAAK,EAAE,aAAa,CAAC;AAClC,kCAAO,MAAM,OAAO,EAAE,KAAK,IAAI;AAE/B,cAAM,QAAQ,MAAM,SAAS,aAAa,QAAQ,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AACzE,kCAAO,MAAM,KAAK,EAAE,aAAa,CAAC;AAClC,kCAAO,MAAM,OAAO,EAAE,KAAK,KAAK;AAAA,MAClC,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,2BAA2B,MAAM;AACxC,oCAAW,YAAY;AACrB,cAAM,SAAS,aAAa,QAAQ,WAAW,GAAG,CAAC;AACnD,cAAM,SAAS,aAAa,QAAQ,WAAW,GAAG,CAAC;AACnD,cAAM,SAAS,aAAa,QAAQ,WAAW,GAAG,CAAC;AAAA,MACrD,CAAC;AAED,4BAAG,wCAAwC,YAAY;AACrD,cAAM,MAAM,iBAAiB,MAAM,YAAY,KAAK,GAAG;AACvD,cAAM,SAAS,mBAAmB,QAAQ,GAAG;AAE7C,cAAM,YAAY,MAAM,SAAS,gBAAgB,QAAQ,IAAI;AAC7D,kCAAO,SAAS,EAAE,IAAI,SAAS;AAC/B,kCAAO,UAAW,cAAc,EAAE,KAAK,GAAG;AAC1C,kCAAO,UAAW,cAAc,EAAE,KAAK,GAAG;AAAA,MAC5C,CAAC;AAED,4BAAG,8CAA8C,YAAY;AAC3D,kCAAO,MAAM,SAAS,gBAAgB,QAAQ,aAAa,CAAC,EAAE,SAAS;AAAA,MACzE,CAAC;AAED,4BAAG,6BAA6B,YAAY;AAC1C,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,YAAY,KAAK,GAAG,CAAC;AACtF,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,YAAY,KAAK,GAAG,CAAC;AAEtF,cAAM,SAAS,MAAM,SAAS,uBAAuB,QAAQ,GAAG;AAChE,kCAAO,OAAO,KAAK,EAAE,aAAa,CAAC;AAAA,MACrC,CAAC;AAED,4BAAG,sCAAsC,YAAY;AACnD,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,YAAY,KAAK,GAAG,CAAC;AACtF,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,YAAY,KAAK,GAAG,CAAC;AAEtF,cAAM,WAAW,MAAM,SAAS,uBAAuB,QAAQ,KAAK,EAAE,WAAW,WAAW,CAAC;AAC7F,kCAAO,SAAS,KAAK,EAAE,aAAa,CAAC;AACrC,kCAAO,SAAS,MAAM,CAAC,EAAG,cAAc,EAAE,KAAK,GAAG;AAElD,cAAM,UAAU,MAAM,SAAS,uBAAuB,QAAQ,KAAK,EAAE,WAAW,UAAU,CAAC;AAC3F,kCAAO,QAAQ,KAAK,EAAE,aAAa,CAAC;AACpC,kCAAO,QAAQ,MAAM,CAAC,EAAG,cAAc,EAAE,KAAK,GAAG;AAAA,MACnD,CAAC;AAED,4BAAG,0BAA0B,YAAY;AACvC,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,YAAY,KAAK,GAAG,CAAC;AACtF,cAAM,SAAS,mBAAmB,QAAQ,IAAI;AAC9C,kCAAO,MAAM,SAAS,gBAAgB,QAAQ,IAAI,CAAC,EAAE,SAAS;AAAA,MAChE,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,mBAAmB,MAAM;AAChC,oCAAW,YAAY;AACrB,cAAM,SAAS,aAAa,QAAQ,WAAW,KAAK,QAAQ,GAAG,CAAC;AAChE,cAAM,SAAS,aAAa,QAAQ,WAAW,KAAK,QAAQ,GAAG,CAAC;AAChE,cAAM,SAAS,aAAa,QAAQ,WAAW,KAAK,QAAQ,GAAG,CAAC;AAChE,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,SAAS,KAAK,GAAG,CAAC;AACnF,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,SAAS,KAAK,GAAG,CAAC;AAAA,MACrF,CAAC;AAED,4BAAG,oCAAoC,YAAY;AACjD,cAAM,SAAS,MAAM,SAAS,oBAAoB,QAAQ,KAAK;AAAA,UAC7D,OAAO;AAAA,UACP,WAAW;AAAA,UACX,cAAc;AAAA,UACd,eAAe;AAAA,QACjB,CAAC;AACD,kCAAO,OAAO,QAAQ,EAAE,KAAK,GAAG;AAChC,kCAAO,OAAO,MAAM,EAAE,aAAa,CAAC;AAAA,MACtC,CAAC;AAED,4BAAG,0CAA0C,YAAY;AACvD,cAAM,SAAS,MAAM,SAAS,UAAU,QAAQ,KAAK,KAAK;AAAA,UACxD,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,MAAM,MAAM,EAAE,uBAAuB,CAAC;AACpD,cAAM,YAAY,OAAO,MAAM,CAAC;AAChC,kCAAO,UAAU,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG;AACvC,kCAAO,UAAU,UAAU,UAAU,UAAU,SAAS,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,MACtE,CAAC;AAED,4BAAG,0CAA0C,YAAY;AACvD,cAAM,SAAS,aAAa,QAAQ,WAAW,YAAY,QAAQ,UAAU,CAAC;AAC9E,cAAM,SAAS,MAAM,SAAS,UAAU,QAAQ,KAAK,YAAY;AAAA,UAC/D,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,KAAK,EAAE,aAAa,CAAC;AAAA,MACrC,CAAC;AAED,4BAAG,uDAAuD,YAAY;AAGpE,cAAM,SAAS,aAAa,QAAQ,WAAW,KAAK,QAAQ,GAAG,CAAC;AAChE,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,SAAS,KAAK,GAAG,CAAC;AACnF,cAAM,SAAS,MAAM,SAAS,UAAU,QAAQ,KAAK,KAAK;AAAA,UACxD,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,MAAM,MAAM,EAAE,uBAAuB,CAAC;AACpD,cAAM,YAAY,OAAO,MAAM,CAAC;AAChC,kCAAO,UAAU,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG;AACvC,kCAAO,UAAU,UAAU,UAAU,UAAU,SAAS,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,MACtE,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,YAAY,MAAM;AACzB,4BAAG,2BAA2B,YAAY;AACxC,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AACpD,cAAM,SAAS,MAAM,SAAS,YAAY,QAAQ,MAAM;AAAA,UACtD,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,kCAAO,OAAO,OAAO,MAAM,EAAE,uBAAuB,CAAC;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,mBAAmB,MAAM;AAChC,4BAAG,gBAAgB,YAAY;AAC7B,cAAM,SAAS,aAAa,QAAQ,WAAW,IAAI,CAAC;AAEpD,cAAM,SAAS,CAAC;AAChB,yBAAiB,SAAS,SAAS,UAAU,MAAM,GAAG;AACpD,iBAAO,KAAK,KAAK;AAAA,QACnB;AACA,kCAAO,OAAO,MAAM,EAAE,uBAAuB,CAAC;AAAA,MAChD,CAAC;AAED,4BAAG,gBAAgB,YAAY;AAC7B,cAAM,SAAS,MAAM,SAAS,WAAW,QAAQ;AAAA,UAC/C,EAAE,UAAU,CAAC,WAAW,YAAY,GAAG,WAAW,YAAY,CAAC,EAAE;AAAA,UACjE,EAAE,eAAe,CAAC,iBAAiB,OAAO,SAAS,cAAc,YAAY,CAAC,EAAE;AAAA,QAClF,CAAC;AACD,kCAAO,OAAO,gBAAgB,EAAE,KAAK,CAAC;AACtC,kCAAO,OAAO,qBAAqB,EAAE,KAAK,CAAC;AAG3C,cAAM,IAAI,MAAM,SAAS,UAAU,QAAQ,YAAY;AACvD,kCAAO,CAAC,EAAE,IAAI,SAAS;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,qBAAqB,MAAM;AAClC,4BAAG,uEAAuE,YAAY;AACpF,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,OAAO,CAAC;AAC7D,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,MAAM,CAAC;AAC5D,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,SAAS,MAAM,IAAI,CAAC;AAErF,cAAM,SAAS,MAAM,SAAS,kBAAkB,MAAM;AACtD,kCAAO,OAAO,eAAe,EAAE,KAAK,CAAC;AACrC,kCAAO,OAAO,oBAAoB,EAAE,KAAK,CAAC;AAG1C,cAAM,OAAO,MAAM,SAAS,cAAc,MAAM;AAChD,kCAAO,IAAI,EAAE,IAAI,SAAS;AAG1B,cAAM,QAAQ,MAAM,SAAS,cAAc,MAAM;AACjD,kCAAO,KAAK,EAAE,YAAY;AAG1B,cAAM,QAAQ,MAAM,SAAS,mBAAmB,MAAM;AACtD,kCAAO,MAAM,WAAW,EAAE,KAAK,CAAC;AAChC,kCAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC;AAAA,MACxC,CAAC;AAED,4BAAG,8CAA8C,YAAY;AAC3D,cAAM,SAAS,MAAM,SAAS,kBAAkB,MAAM;AACtD,kCAAO,OAAO,eAAe,EAAE,KAAK,CAAC;AACrC,kCAAO,OAAO,oBAAoB,EAAE,KAAK,CAAC;AAAA,MAC5C,CAAC;AAAA,IACH,CAAC;AAID,gCAAS,sBAAsB,MAAM;AACnC,4BAAG,qCAAqC,YAAY;AAClD,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,OAAO,CAAC;AAC7D,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,OAAO,CAAC;AAC7D,cAAM,SAAS,aAAa,QAAQ,WAAW,MAAM,MAAM,CAAC;AAC5D,cAAM,SAAS,mBAAmB,QAAQ,iBAAiB,MAAM,SAAS,MAAM,IAAI,CAAC;AAErF,cAAM,QAAQ,MAAM,SAAS,mBAAmB,MAAM;AACtD,kCAAO,MAAM,WAAW,EAAE,KAAK,CAAC;AAChC,kCAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC;AACtC,kCAAO,MAAM,oBAAoB,OAAO,CAAC,EAAE,KAAK,CAAC;AACjD,kCAAO,MAAM,oBAAoB,MAAM,CAAC,EAAE,KAAK,CAAC;AAChD,kCAAO,MAAM,0BAA0B,OAAO,CAAC,EAAE,KAAK,CAAC;AAAA,MACzD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers-builtin/conformance.ts"],"sourcesContent":["// Provider Conformance Test Suite\n// Any StorageProvider implementer can import and run these tests to verify conformance.\n//\n// Usage:\n// import { runStorageProviderConformanceTests } from '@utaba/deep-memory';\n// runStorageProviderConformanceTests(() => new MyStorageProvider());\n\nimport { describe, it, expect, beforeEach } from 'vitest';\nimport type { StorageProvider } from '../providers/StorageProvider.js';\nimport type { StoredEntity } from '../types/entities.js';\nimport type { StoredRelationship } from '../types/relationships.js';\nimport type { Provenance } from '../types/provenance.js';\n\nfunction makeProvenance(): Provenance {\n const now = new Date().toISOString();\n return {\n createdBy: 'conformance-test',\n createdByType: 'agent',\n createdAt: now,\n modifiedBy: 'conformance-test',\n modifiedByType: 'agent',\n modifiedAt: now,\n };\n}\n\nfunction makeEntity(id: string, type = 'test-type', label?: string): StoredEntity {\n return {\n id,\n slug: `${type}:${(label ?? id).toLowerCase().replace(/[^a-z0-9]+/g, '-')}`,\n entityType: type,\n label: label ?? id,\n summary: `Summary for ${id}`,\n properties: { key: 'value' },\n provenance: makeProvenance(),\n };\n}\n\nfunction makeRelationship(\n id: string,\n type: string,\n sourceId: string,\n targetId: string,\n bidirectional = false,\n): StoredRelationship {\n return {\n id,\n relationshipType: type,\n sourceEntityId: sourceId,\n targetEntityId: targetId,\n properties: {},\n bidirectional,\n provenance: makeProvenance(),\n };\n}\n\n/**\n * Run the full StorageProvider conformance test suite.\n *\n * @param factory - A function that creates a fresh, empty StorageProvider instance.\n * Called before each test to ensure isolation.\n */\nexport function runStorageProviderConformanceTests(\n factory: () => StorageProvider | Promise<StorageProvider>,\n): void {\n // Use a stable GUID so external cleanup scripts can target it\n const repoId = '40000000-0000-4000-a000-000000000001';\n\n let provider: StorageProvider;\n\n async function setup(): Promise<void> {\n provider = await factory();\n if (provider.initialize) await provider.initialize();\n\n await provider.createRepository({\n repositoryId: repoId,\n label: 'Conformance Test',\n governanceConfig: { mode: 'open' },\n createdAt: new Date().toISOString(),\n createdBy: 'conformance-test',\n });\n }\n\n describe('StorageProvider Conformance Tests', () => {\n beforeEach(async () => {\n await setup();\n });\n\n // ─── Repository ─────────────────────────────────────────\n\n describe('repository operations', () => {\n it('creates a repository', async () => {\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n expect(repo!.repositoryId).toBe(repoId);\n expect(repo!.label).toBe('Conformance Test');\n });\n\n it('returns null for non-existent repository', async () => {\n const repo = await provider.getRepository('ffffffff-ffff-4fff-afff-ffffffffffff');\n expect(repo).toBeNull();\n });\n\n it('lists repositories', async () => {\n const list = await provider.listRepositories();\n expect(list.items.length).toBeGreaterThanOrEqual(1);\n expect(list.items.some((r) => r.repositoryId === repoId)).toBe(true);\n });\n\n it('updates a repository', async () => {\n const updated = await provider.updateRepository(repoId, {\n label: 'Updated Label',\n description: 'Updated description',\n governanceConfig: { mode: 'open', defaultSimilarityThreshold: 0.4 },\n });\n expect(updated.label).toBe('Updated Label');\n expect(updated.description).toBe('Updated description');\n expect(updated.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n\n // Verify persistence\n const fetched = await provider.getRepository(repoId);\n expect(fetched!.label).toBe('Updated Label');\n expect(fetched!.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n });\n\n it('deletes a repository', async () => {\n await provider.deleteRepository(repoId);\n expect(await provider.getRepository(repoId)).toBeNull();\n });\n\n it('returns repository stats', async () => {\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n expect(typeof stats.vocabularyVersion).toBe('string');\n });\n });\n\n // ─── Vocabulary ─────────────────────────────────────────\n\n describe('vocabulary operations', () => {\n it('gets and saves vocabulary', async () => {\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n expect(typeof vocab.version).toBe('string');\n\n const updated = { ...vocab, version: '1.0.0' };\n await provider.saveVocabulary(repoId, updated);\n\n const fetched = await provider.getVocabulary(repoId);\n expect(fetched.version).toBe('1.0.0');\n });\n\n it('returns vocabulary change log', async () => {\n const log = await provider.getVocabularyChangeLog(repoId);\n expect(Array.isArray(log.items)).toBe(true);\n });\n });\n\n // ─── Entities ───────────────────────────────────────────\n\n describe('entity operations', () => {\n it('creates and retrieves an entity', async () => {\n const entity = makeEntity('e1');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntity(repoId, 'e1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.label).toBe('e1');\n });\n\n it('retrieves an entity by slug', async () => {\n const entity = makeEntity('e1', 'test-type', 'Alpha');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntityBySlug(repoId, entity.slug);\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.slug).toBe(entity.slug);\n });\n\n it('returns null for non-existent entity', async () => {\n const result = await provider.getEntity(repoId, 'nonexistent');\n expect(result).toBeNull();\n });\n\n it('returns null for non-existent slug', async () => {\n const result = await provider.getEntityBySlug(repoId, 'nonexistent:slug');\n expect(result).toBeNull();\n });\n\n it('batch retrieves entities', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n\n const map = await provider.getEntities(repoId, ['e1', 'e2', 'missing']);\n expect(map.size).toBe(2);\n expect(map.has('e1')).toBe(true);\n expect(map.has('e2')).toBe(true);\n expect(map.has('missing')).toBe(false);\n });\n\n it('updates an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const updated = await provider.updateEntity(repoId, 'e1', {\n label: 'Updated Label',\n provenance: makeProvenance(),\n });\n expect(updated.label).toBe('Updated Label');\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.label).toBe('Updated Label');\n });\n\n it('clears summary/data/dataFormat when null is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'starting summary',\n data: 'raw content',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n summary: null,\n data: null,\n dataFormat: null,\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBeUndefined();\n expect(fetched!.data).toBeUndefined();\n expect(fetched!.dataFormat).toBeUndefined();\n });\n\n it('preserves summary/data/dataFormat when undefined is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'keep me',\n data: 'keep me too',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n label: 'Renamed',\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBe('keep me');\n expect(fetched!.data).toBe('keep me too');\n expect(fetched!.dataFormat).toBe('text/plain');\n });\n\n it('deletes an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.deleteEntity(repoId, 'e1');\n expect(await provider.getEntity(repoId, 'e1')).toBeNull();\n });\n\n it('finds entities by search term', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'test-type', 'Beta'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'alpha',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by search term case-insensitively', async () => {\n // Locks the invariant that searchTerm matching is case-insensitive on\n // every provider. In-memory lowercases both sides; SQL Server's LIKE\n // is case-insensitive under the default *_CI_AS collation; Cosmos\n // routes through CONTAINS(..., @term, true) on the Document endpoint.\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'ALPHA',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by type filter', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'type-a', 'A'));\n await provider.createEntity(repoId, makeEntity('e2', 'type-b', 'B'));\n\n const result = await provider.findEntities(repoId, {\n entityTypes: ['type-a'],\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.entityType).toBe('type-a');\n });\n\n it('paginates find results', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n await provider.createEntity(repoId, makeEntity('e3'));\n\n const page1 = await provider.findEntities(repoId, { limit: 2, offset: 0 });\n expect(page1.items).toHaveLength(2);\n expect(page1.hasMore).toBe(true);\n\n const page2 = await provider.findEntities(repoId, { limit: 2, offset: 2 });\n expect(page2.items).toHaveLength(1);\n expect(page2.hasMore).toBe(false);\n });\n });\n\n // ─── Relationships ──────────────────────────────────────\n\n describe('relationship operations', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a'));\n await provider.createEntity(repoId, makeEntity('b'));\n await provider.createEntity(repoId, makeEntity('c'));\n });\n\n it('creates and retrieves a relationship', async () => {\n const rel = makeRelationship('r1', 'connects', 'a', 'b');\n await provider.createRelationship(repoId, rel);\n\n const retrieved = await provider.getRelationship(repoId, 'r1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.sourceEntityId).toBe('a');\n expect(retrieved!.targetEntityId).toBe('b');\n });\n\n it('returns null for non-existent relationship', async () => {\n expect(await provider.getRelationship(repoId, 'nonexistent')).toBeNull();\n });\n\n it('gets entity relationships', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const result = await provider.getEntityRelationships(repoId, 'a');\n expect(result.items).toHaveLength(2);\n });\n\n it('filters relationships by direction', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const outbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'out' });\n expect(outbound.items).toHaveLength(1);\n expect(outbound.items[0]!.targetEntityId).toBe('b');\n\n const inbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'in' });\n expect(inbound.items).toHaveLength(1);\n expect(inbound.items[0]!.sourceEntityId).toBe('c');\n });\n\n it('deletes a relationship', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.deleteRelationship(repoId, 'r1');\n expect(await provider.getRelationship(repoId, 'r1')).toBeNull();\n });\n });\n\n // ─── Graph Traversal ────────────────────────────────────\n\n describe('graph traversal', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a', 'node', 'A'));\n await provider.createEntity(repoId, makeEntity('b', 'node', 'B'));\n await provider.createEntity(repoId, makeEntity('c', 'node', 'C'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'links', 'b', 'c'));\n });\n\n it('explores neighborhood at depth 1', async () => {\n const result = await provider.exploreNeighborhood(repoId, 'a', {\n depth: 1,\n direction: 'both',\n limitPerType: 10,\n offsetPerType: 0,\n });\n expect(result.centerId).toBe('a');\n expect(result.layers).toHaveLength(1);\n });\n\n it('finds paths between connected entities', async () => {\n const result = await provider.findPaths(repoId, 'a', 'c', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('c');\n });\n\n it('returns empty paths when no connection', async () => {\n await provider.createEntity(repoId, makeEntity('isolated', 'node', 'Isolated'));\n const result = await provider.findPaths(repoId, 'a', 'isolated', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths).toHaveLength(0);\n });\n\n it('finds paths through non-bidirectional inbound edges', async () => {\n // Graph: a → b ← d (both edges are non-bidirectional)\n // Path from a to d should traverse: a →(outbound) b ←(inbound) d\n await provider.createEntity(repoId, makeEntity('d', 'node', 'D'));\n await provider.createRelationship(repoId, makeRelationship('r3', 'links', 'd', 'b'));\n const result = await provider.findPaths(repoId, 'a', 'd', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('d');\n });\n });\n\n // ─── Timeline ───────────────────────────────────────────\n\n describe('timeline', () => {\n it('returns timeline events', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const result = await provider.getTimeline(repoId, 'e1', {\n limit: 10,\n offset: 0,\n });\n expect(result.events.length).toBeGreaterThanOrEqual(1);\n });\n });\n\n // ─── Bulk Operations ────────────────────────────────────\n\n describe('bulk operations', () => {\n it('exports data', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n\n const chunks = [];\n for await (const chunk of provider.exportAll(repoId)) {\n chunks.push(chunk);\n }\n expect(chunks.length).toBeGreaterThanOrEqual(1);\n });\n\n it('imports data', async () => {\n const result = await provider.importBulk(repoId, [\n { entities: [makeEntity('imported-1'), makeEntity('imported-2')] },\n { relationships: [makeRelationship('ir1', 'links', 'imported-1', 'imported-2')] },\n ]);\n expect(result.entitiesImported).toBe(2);\n expect(result.relationshipsImported).toBe(1);\n\n // Verify imported data is accessible\n const e = await provider.getEntity(repoId, 'imported-1');\n expect(e).not.toBeNull();\n });\n });\n\n // ─── Delete All Contents ───────────────────────────────\n\n describe('deleteAllContents', () => {\n it('deletes all entities and relationships but preserves the repository', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(2);\n expect(result.deletedRelationships).toBe(1);\n\n // Repository still exists\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n\n // Vocabulary still exists\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n\n // Contents are gone\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n });\n\n it('returns zero counts on an empty repository', async () => {\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(0);\n expect(result.deletedRelationships).toBe(0);\n });\n });\n\n // ─── Stats after data ───────────────────────────────────\n\n describe('stats reflect data', () => {\n it('counts entities and relationships', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e3', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(3);\n expect(stats.relationshipCount).toBe(1);\n expect(stats.entityTypeBreakdown['alpha']).toBe(2);\n expect(stats.entityTypeBreakdown['beta']).toBe(1);\n expect(stats.relationshipTypeBreakdown['links']).toBe(1);\n });\n });\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StorageProvider } from '../StorageProvider-
|
|
2
|
-
import '../portability-
|
|
1
|
+
import { S as StorageProvider } from '../StorageProvider-CadKZ85j.cjs';
|
|
2
|
+
import '../portability-CAeyzSCx.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Run the full StorageProvider conformance test suite.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as StorageProvider } from '../StorageProvider-
|
|
2
|
-
import '../portability-
|
|
1
|
+
import { S as StorageProvider } from '../StorageProvider-B2p_XThQ.js';
|
|
2
|
+
import '../portability-CAeyzSCx.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Run the full StorageProvider conformance test suite.
|
|
@@ -261,10 +261,10 @@ function runStorageProviderConformanceTests(factory) {
|
|
|
261
261
|
it("filters relationships by direction", async () => {
|
|
262
262
|
await provider.createRelationship(repoId, makeRelationship("r1", "connects", "a", "b"));
|
|
263
263
|
await provider.createRelationship(repoId, makeRelationship("r2", "connects", "c", "a"));
|
|
264
|
-
const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "
|
|
264
|
+
const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "out" });
|
|
265
265
|
expect(outbound.items).toHaveLength(1);
|
|
266
266
|
expect(outbound.items[0].targetEntityId).toBe("b");
|
|
267
|
-
const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "
|
|
267
|
+
const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "in" });
|
|
268
268
|
expect(inbound.items).toHaveLength(1);
|
|
269
269
|
expect(inbound.items[0].sourceEntityId).toBe("c");
|
|
270
270
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers-builtin/conformance.ts"],"sourcesContent":["// Provider Conformance Test Suite\n// Any StorageProvider implementer can import and run these tests to verify conformance.\n//\n// Usage:\n// import { runStorageProviderConformanceTests } from '@utaba/deep-memory';\n// runStorageProviderConformanceTests(() => new MyStorageProvider());\n\nimport { describe, it, expect, beforeEach } from 'vitest';\nimport type { StorageProvider } from '../providers/StorageProvider.js';\nimport type { StoredEntity } from '../types/entities.js';\nimport type { StoredRelationship } from '../types/relationships.js';\nimport type { Provenance } from '../types/provenance.js';\n\nfunction makeProvenance(): Provenance {\n const now = new Date().toISOString();\n return {\n createdBy: 'conformance-test',\n createdByType: 'agent',\n createdAt: now,\n modifiedBy: 'conformance-test',\n modifiedByType: 'agent',\n modifiedAt: now,\n };\n}\n\nfunction makeEntity(id: string, type = 'test-type', label?: string): StoredEntity {\n return {\n id,\n slug: `${type}:${(label ?? id).toLowerCase().replace(/[^a-z0-9]+/g, '-')}`,\n entityType: type,\n label: label ?? id,\n summary: `Summary for ${id}`,\n properties: { key: 'value' },\n provenance: makeProvenance(),\n };\n}\n\nfunction makeRelationship(\n id: string,\n type: string,\n sourceId: string,\n targetId: string,\n bidirectional = false,\n): StoredRelationship {\n return {\n id,\n relationshipType: type,\n sourceEntityId: sourceId,\n targetEntityId: targetId,\n properties: {},\n bidirectional,\n provenance: makeProvenance(),\n };\n}\n\n/**\n * Run the full StorageProvider conformance test suite.\n *\n * @param factory - A function that creates a fresh, empty StorageProvider instance.\n * Called before each test to ensure isolation.\n */\nexport function runStorageProviderConformanceTests(\n factory: () => StorageProvider | Promise<StorageProvider>,\n): void {\n // Use a stable GUID so external cleanup scripts can target it\n const repoId = '40000000-0000-4000-a000-000000000001';\n\n let provider: StorageProvider;\n\n async function setup(): Promise<void> {\n provider = await factory();\n if (provider.initialize) await provider.initialize();\n\n await provider.createRepository({\n repositoryId: repoId,\n label: 'Conformance Test',\n governanceConfig: { mode: 'open' },\n createdAt: new Date().toISOString(),\n createdBy: 'conformance-test',\n });\n }\n\n describe('StorageProvider Conformance Tests', () => {\n beforeEach(async () => {\n await setup();\n });\n\n // ─── Repository ─────────────────────────────────────────\n\n describe('repository operations', () => {\n it('creates a repository', async () => {\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n expect(repo!.repositoryId).toBe(repoId);\n expect(repo!.label).toBe('Conformance Test');\n });\n\n it('returns null for non-existent repository', async () => {\n const repo = await provider.getRepository('ffffffff-ffff-4fff-afff-ffffffffffff');\n expect(repo).toBeNull();\n });\n\n it('lists repositories', async () => {\n const list = await provider.listRepositories();\n expect(list.items.length).toBeGreaterThanOrEqual(1);\n expect(list.items.some((r) => r.repositoryId === repoId)).toBe(true);\n });\n\n it('updates a repository', async () => {\n const updated = await provider.updateRepository(repoId, {\n label: 'Updated Label',\n description: 'Updated description',\n governanceConfig: { mode: 'open', defaultSimilarityThreshold: 0.4 },\n });\n expect(updated.label).toBe('Updated Label');\n expect(updated.description).toBe('Updated description');\n expect(updated.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n\n // Verify persistence\n const fetched = await provider.getRepository(repoId);\n expect(fetched!.label).toBe('Updated Label');\n expect(fetched!.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n });\n\n it('deletes a repository', async () => {\n await provider.deleteRepository(repoId);\n expect(await provider.getRepository(repoId)).toBeNull();\n });\n\n it('returns repository stats', async () => {\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n expect(typeof stats.vocabularyVersion).toBe('string');\n });\n });\n\n // ─── Vocabulary ─────────────────────────────────────────\n\n describe('vocabulary operations', () => {\n it('gets and saves vocabulary', async () => {\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n expect(typeof vocab.version).toBe('string');\n\n const updated = { ...vocab, version: '1.0.0' };\n await provider.saveVocabulary(repoId, updated);\n\n const fetched = await provider.getVocabulary(repoId);\n expect(fetched.version).toBe('1.0.0');\n });\n\n it('returns vocabulary change log', async () => {\n const log = await provider.getVocabularyChangeLog(repoId);\n expect(Array.isArray(log.items)).toBe(true);\n });\n });\n\n // ─── Entities ───────────────────────────────────────────\n\n describe('entity operations', () => {\n it('creates and retrieves an entity', async () => {\n const entity = makeEntity('e1');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntity(repoId, 'e1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.label).toBe('e1');\n });\n\n it('retrieves an entity by slug', async () => {\n const entity = makeEntity('e1', 'test-type', 'Alpha');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntityBySlug(repoId, entity.slug);\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.slug).toBe(entity.slug);\n });\n\n it('returns null for non-existent entity', async () => {\n const result = await provider.getEntity(repoId, 'nonexistent');\n expect(result).toBeNull();\n });\n\n it('returns null for non-existent slug', async () => {\n const result = await provider.getEntityBySlug(repoId, 'nonexistent:slug');\n expect(result).toBeNull();\n });\n\n it('batch retrieves entities', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n\n const map = await provider.getEntities(repoId, ['e1', 'e2', 'missing']);\n expect(map.size).toBe(2);\n expect(map.has('e1')).toBe(true);\n expect(map.has('e2')).toBe(true);\n expect(map.has('missing')).toBe(false);\n });\n\n it('updates an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const updated = await provider.updateEntity(repoId, 'e1', {\n label: 'Updated Label',\n provenance: makeProvenance(),\n });\n expect(updated.label).toBe('Updated Label');\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.label).toBe('Updated Label');\n });\n\n it('clears summary/data/dataFormat when null is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'starting summary',\n data: 'raw content',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n summary: null,\n data: null,\n dataFormat: null,\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBeUndefined();\n expect(fetched!.data).toBeUndefined();\n expect(fetched!.dataFormat).toBeUndefined();\n });\n\n it('preserves summary/data/dataFormat when undefined is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'keep me',\n data: 'keep me too',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n label: 'Renamed',\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBe('keep me');\n expect(fetched!.data).toBe('keep me too');\n expect(fetched!.dataFormat).toBe('text/plain');\n });\n\n it('deletes an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.deleteEntity(repoId, 'e1');\n expect(await provider.getEntity(repoId, 'e1')).toBeNull();\n });\n\n it('finds entities by search term', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'test-type', 'Beta'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'alpha',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by search term case-insensitively', async () => {\n // Locks the invariant that searchTerm matching is case-insensitive on\n // every provider. In-memory lowercases both sides; SQL Server's LIKE\n // is case-insensitive under the default *_CI_AS collation; Cosmos\n // routes through CONTAINS(..., @term, true) on the Document endpoint.\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'ALPHA',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by type filter', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'type-a', 'A'));\n await provider.createEntity(repoId, makeEntity('e2', 'type-b', 'B'));\n\n const result = await provider.findEntities(repoId, {\n entityTypes: ['type-a'],\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.entityType).toBe('type-a');\n });\n\n it('paginates find results', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n await provider.createEntity(repoId, makeEntity('e3'));\n\n const page1 = await provider.findEntities(repoId, { limit: 2, offset: 0 });\n expect(page1.items).toHaveLength(2);\n expect(page1.hasMore).toBe(true);\n\n const page2 = await provider.findEntities(repoId, { limit: 2, offset: 2 });\n expect(page2.items).toHaveLength(1);\n expect(page2.hasMore).toBe(false);\n });\n });\n\n // ─── Relationships ──────────────────────────────────────\n\n describe('relationship operations', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a'));\n await provider.createEntity(repoId, makeEntity('b'));\n await provider.createEntity(repoId, makeEntity('c'));\n });\n\n it('creates and retrieves a relationship', async () => {\n const rel = makeRelationship('r1', 'connects', 'a', 'b');\n await provider.createRelationship(repoId, rel);\n\n const retrieved = await provider.getRelationship(repoId, 'r1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.sourceEntityId).toBe('a');\n expect(retrieved!.targetEntityId).toBe('b');\n });\n\n it('returns null for non-existent relationship', async () => {\n expect(await provider.getRelationship(repoId, 'nonexistent')).toBeNull();\n });\n\n it('gets entity relationships', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const result = await provider.getEntityRelationships(repoId, 'a');\n expect(result.items).toHaveLength(2);\n });\n\n it('filters relationships by direction', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const outbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'outbound' });\n expect(outbound.items).toHaveLength(1);\n expect(outbound.items[0]!.targetEntityId).toBe('b');\n\n const inbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'inbound' });\n expect(inbound.items).toHaveLength(1);\n expect(inbound.items[0]!.sourceEntityId).toBe('c');\n });\n\n it('deletes a relationship', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.deleteRelationship(repoId, 'r1');\n expect(await provider.getRelationship(repoId, 'r1')).toBeNull();\n });\n });\n\n // ─── Graph Traversal ────────────────────────────────────\n\n describe('graph traversal', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a', 'node', 'A'));\n await provider.createEntity(repoId, makeEntity('b', 'node', 'B'));\n await provider.createEntity(repoId, makeEntity('c', 'node', 'C'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'links', 'b', 'c'));\n });\n\n it('explores neighborhood at depth 1', async () => {\n const result = await provider.exploreNeighborhood(repoId, 'a', {\n depth: 1,\n direction: 'both',\n limitPerType: 10,\n offsetPerType: 0,\n });\n expect(result.centerId).toBe('a');\n expect(result.layers).toHaveLength(1);\n });\n\n it('finds paths between connected entities', async () => {\n const result = await provider.findPaths(repoId, 'a', 'c', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('c');\n });\n\n it('returns empty paths when no connection', async () => {\n await provider.createEntity(repoId, makeEntity('isolated', 'node', 'Isolated'));\n const result = await provider.findPaths(repoId, 'a', 'isolated', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths).toHaveLength(0);\n });\n\n it('finds paths through non-bidirectional inbound edges', async () => {\n // Graph: a → b ← d (both edges are non-bidirectional)\n // Path from a to d should traverse: a →(outbound) b ←(inbound) d\n await provider.createEntity(repoId, makeEntity('d', 'node', 'D'));\n await provider.createRelationship(repoId, makeRelationship('r3', 'links', 'd', 'b'));\n const result = await provider.findPaths(repoId, 'a', 'd', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('d');\n });\n });\n\n // ─── Timeline ───────────────────────────────────────────\n\n describe('timeline', () => {\n it('returns timeline events', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const result = await provider.getTimeline(repoId, 'e1', {\n limit: 10,\n offset: 0,\n });\n expect(result.events.length).toBeGreaterThanOrEqual(1);\n });\n });\n\n // ─── Bulk Operations ────────────────────────────────────\n\n describe('bulk operations', () => {\n it('exports data', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n\n const chunks = [];\n for await (const chunk of provider.exportAll(repoId)) {\n chunks.push(chunk);\n }\n expect(chunks.length).toBeGreaterThanOrEqual(1);\n });\n\n it('imports data', async () => {\n const result = await provider.importBulk(repoId, [\n { entities: [makeEntity('imported-1'), makeEntity('imported-2')] },\n { relationships: [makeRelationship('ir1', 'links', 'imported-1', 'imported-2')] },\n ]);\n expect(result.entitiesImported).toBe(2);\n expect(result.relationshipsImported).toBe(1);\n\n // Verify imported data is accessible\n const e = await provider.getEntity(repoId, 'imported-1');\n expect(e).not.toBeNull();\n });\n });\n\n // ─── Delete All Contents ───────────────────────────────\n\n describe('deleteAllContents', () => {\n it('deletes all entities and relationships but preserves the repository', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(2);\n expect(result.deletedRelationships).toBe(1);\n\n // Repository still exists\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n\n // Vocabulary still exists\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n\n // Contents are gone\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n });\n\n it('returns zero counts on an empty repository', async () => {\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(0);\n expect(result.deletedRelationships).toBe(0);\n });\n });\n\n // ─── Stats after data ───────────────────────────────────\n\n describe('stats reflect data', () => {\n it('counts entities and relationships', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e3', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(3);\n expect(stats.relationshipCount).toBe(1);\n expect(stats.entityTypeBreakdown['alpha']).toBe(2);\n expect(stats.entityTypeBreakdown['beta']).toBe(1);\n expect(stats.relationshipTypeBreakdown['links']).toBe(1);\n });\n });\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers-builtin/conformance.ts"],"sourcesContent":["// Provider Conformance Test Suite\n// Any StorageProvider implementer can import and run these tests to verify conformance.\n//\n// Usage:\n// import { runStorageProviderConformanceTests } from '@utaba/deep-memory';\n// runStorageProviderConformanceTests(() => new MyStorageProvider());\n\nimport { describe, it, expect, beforeEach } from 'vitest';\nimport type { StorageProvider } from '../providers/StorageProvider.js';\nimport type { StoredEntity } from '../types/entities.js';\nimport type { StoredRelationship } from '../types/relationships.js';\nimport type { Provenance } from '../types/provenance.js';\n\nfunction makeProvenance(): Provenance {\n const now = new Date().toISOString();\n return {\n createdBy: 'conformance-test',\n createdByType: 'agent',\n createdAt: now,\n modifiedBy: 'conformance-test',\n modifiedByType: 'agent',\n modifiedAt: now,\n };\n}\n\nfunction makeEntity(id: string, type = 'test-type', label?: string): StoredEntity {\n return {\n id,\n slug: `${type}:${(label ?? id).toLowerCase().replace(/[^a-z0-9]+/g, '-')}`,\n entityType: type,\n label: label ?? id,\n summary: `Summary for ${id}`,\n properties: { key: 'value' },\n provenance: makeProvenance(),\n };\n}\n\nfunction makeRelationship(\n id: string,\n type: string,\n sourceId: string,\n targetId: string,\n bidirectional = false,\n): StoredRelationship {\n return {\n id,\n relationshipType: type,\n sourceEntityId: sourceId,\n targetEntityId: targetId,\n properties: {},\n bidirectional,\n provenance: makeProvenance(),\n };\n}\n\n/**\n * Run the full StorageProvider conformance test suite.\n *\n * @param factory - A function that creates a fresh, empty StorageProvider instance.\n * Called before each test to ensure isolation.\n */\nexport function runStorageProviderConformanceTests(\n factory: () => StorageProvider | Promise<StorageProvider>,\n): void {\n // Use a stable GUID so external cleanup scripts can target it\n const repoId = '40000000-0000-4000-a000-000000000001';\n\n let provider: StorageProvider;\n\n async function setup(): Promise<void> {\n provider = await factory();\n if (provider.initialize) await provider.initialize();\n\n await provider.createRepository({\n repositoryId: repoId,\n label: 'Conformance Test',\n governanceConfig: { mode: 'open' },\n createdAt: new Date().toISOString(),\n createdBy: 'conformance-test',\n });\n }\n\n describe('StorageProvider Conformance Tests', () => {\n beforeEach(async () => {\n await setup();\n });\n\n // ─── Repository ─────────────────────────────────────────\n\n describe('repository operations', () => {\n it('creates a repository', async () => {\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n expect(repo!.repositoryId).toBe(repoId);\n expect(repo!.label).toBe('Conformance Test');\n });\n\n it('returns null for non-existent repository', async () => {\n const repo = await provider.getRepository('ffffffff-ffff-4fff-afff-ffffffffffff');\n expect(repo).toBeNull();\n });\n\n it('lists repositories', async () => {\n const list = await provider.listRepositories();\n expect(list.items.length).toBeGreaterThanOrEqual(1);\n expect(list.items.some((r) => r.repositoryId === repoId)).toBe(true);\n });\n\n it('updates a repository', async () => {\n const updated = await provider.updateRepository(repoId, {\n label: 'Updated Label',\n description: 'Updated description',\n governanceConfig: { mode: 'open', defaultSimilarityThreshold: 0.4 },\n });\n expect(updated.label).toBe('Updated Label');\n expect(updated.description).toBe('Updated description');\n expect(updated.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n\n // Verify persistence\n const fetched = await provider.getRepository(repoId);\n expect(fetched!.label).toBe('Updated Label');\n expect(fetched!.governanceConfig.defaultSimilarityThreshold).toBe(0.4);\n });\n\n it('deletes a repository', async () => {\n await provider.deleteRepository(repoId);\n expect(await provider.getRepository(repoId)).toBeNull();\n });\n\n it('returns repository stats', async () => {\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n expect(typeof stats.vocabularyVersion).toBe('string');\n });\n });\n\n // ─── Vocabulary ─────────────────────────────────────────\n\n describe('vocabulary operations', () => {\n it('gets and saves vocabulary', async () => {\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n expect(typeof vocab.version).toBe('string');\n\n const updated = { ...vocab, version: '1.0.0' };\n await provider.saveVocabulary(repoId, updated);\n\n const fetched = await provider.getVocabulary(repoId);\n expect(fetched.version).toBe('1.0.0');\n });\n\n it('returns vocabulary change log', async () => {\n const log = await provider.getVocabularyChangeLog(repoId);\n expect(Array.isArray(log.items)).toBe(true);\n });\n });\n\n // ─── Entities ───────────────────────────────────────────\n\n describe('entity operations', () => {\n it('creates and retrieves an entity', async () => {\n const entity = makeEntity('e1');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntity(repoId, 'e1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.label).toBe('e1');\n });\n\n it('retrieves an entity by slug', async () => {\n const entity = makeEntity('e1', 'test-type', 'Alpha');\n await provider.createEntity(repoId, entity);\n\n const retrieved = await provider.getEntityBySlug(repoId, entity.slug);\n expect(retrieved).not.toBeNull();\n expect(retrieved!.id).toBe('e1');\n expect(retrieved!.slug).toBe(entity.slug);\n });\n\n it('returns null for non-existent entity', async () => {\n const result = await provider.getEntity(repoId, 'nonexistent');\n expect(result).toBeNull();\n });\n\n it('returns null for non-existent slug', async () => {\n const result = await provider.getEntityBySlug(repoId, 'nonexistent:slug');\n expect(result).toBeNull();\n });\n\n it('batch retrieves entities', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n\n const map = await provider.getEntities(repoId, ['e1', 'e2', 'missing']);\n expect(map.size).toBe(2);\n expect(map.has('e1')).toBe(true);\n expect(map.has('e2')).toBe(true);\n expect(map.has('missing')).toBe(false);\n });\n\n it('updates an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const updated = await provider.updateEntity(repoId, 'e1', {\n label: 'Updated Label',\n provenance: makeProvenance(),\n });\n expect(updated.label).toBe('Updated Label');\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.label).toBe('Updated Label');\n });\n\n it('clears summary/data/dataFormat when null is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'starting summary',\n data: 'raw content',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n summary: null,\n data: null,\n dataFormat: null,\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBeUndefined();\n expect(fetched!.data).toBeUndefined();\n expect(fetched!.dataFormat).toBeUndefined();\n });\n\n it('preserves summary/data/dataFormat when undefined is passed', async () => {\n const entity: StoredEntity = {\n ...makeEntity('e1'),\n summary: 'keep me',\n data: 'keep me too',\n dataFormat: 'text/plain',\n };\n await provider.createEntity(repoId, entity);\n\n await provider.updateEntity(repoId, 'e1', {\n label: 'Renamed',\n provenance: makeProvenance(),\n });\n\n const fetched = await provider.getEntity(repoId, 'e1');\n expect(fetched!.summary).toBe('keep me');\n expect(fetched!.data).toBe('keep me too');\n expect(fetched!.dataFormat).toBe('text/plain');\n });\n\n it('deletes an entity', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.deleteEntity(repoId, 'e1');\n expect(await provider.getEntity(repoId, 'e1')).toBeNull();\n });\n\n it('finds entities by search term', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'test-type', 'Beta'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'alpha',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by search term case-insensitively', async () => {\n // Locks the invariant that searchTerm matching is case-insensitive on\n // every provider. In-memory lowercases both sides; SQL Server's LIKE\n // is case-insensitive under the default *_CI_AS collation; Cosmos\n // routes through CONTAINS(..., @term, true) on the Document endpoint.\n await provider.createEntity(repoId, makeEntity('e1', 'test-type', 'Alpha'));\n\n const result = await provider.findEntities(repoId, {\n searchTerm: 'ALPHA',\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.label).toBe('Alpha');\n });\n\n it('finds entities by type filter', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'type-a', 'A'));\n await provider.createEntity(repoId, makeEntity('e2', 'type-b', 'B'));\n\n const result = await provider.findEntities(repoId, {\n entityTypes: ['type-a'],\n limit: 10,\n offset: 0,\n });\n expect(result.items).toHaveLength(1);\n expect(result.items[0]!.entityType).toBe('type-a');\n });\n\n it('paginates find results', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n await provider.createEntity(repoId, makeEntity('e2'));\n await provider.createEntity(repoId, makeEntity('e3'));\n\n const page1 = await provider.findEntities(repoId, { limit: 2, offset: 0 });\n expect(page1.items).toHaveLength(2);\n expect(page1.hasMore).toBe(true);\n\n const page2 = await provider.findEntities(repoId, { limit: 2, offset: 2 });\n expect(page2.items).toHaveLength(1);\n expect(page2.hasMore).toBe(false);\n });\n });\n\n // ─── Relationships ──────────────────────────────────────\n\n describe('relationship operations', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a'));\n await provider.createEntity(repoId, makeEntity('b'));\n await provider.createEntity(repoId, makeEntity('c'));\n });\n\n it('creates and retrieves a relationship', async () => {\n const rel = makeRelationship('r1', 'connects', 'a', 'b');\n await provider.createRelationship(repoId, rel);\n\n const retrieved = await provider.getRelationship(repoId, 'r1');\n expect(retrieved).not.toBeNull();\n expect(retrieved!.sourceEntityId).toBe('a');\n expect(retrieved!.targetEntityId).toBe('b');\n });\n\n it('returns null for non-existent relationship', async () => {\n expect(await provider.getRelationship(repoId, 'nonexistent')).toBeNull();\n });\n\n it('gets entity relationships', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const result = await provider.getEntityRelationships(repoId, 'a');\n expect(result.items).toHaveLength(2);\n });\n\n it('filters relationships by direction', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'connects', 'c', 'a'));\n\n const outbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'out' });\n expect(outbound.items).toHaveLength(1);\n expect(outbound.items[0]!.targetEntityId).toBe('b');\n\n const inbound = await provider.getEntityRelationships(repoId, 'a', { direction: 'in' });\n expect(inbound.items).toHaveLength(1);\n expect(inbound.items[0]!.sourceEntityId).toBe('c');\n });\n\n it('deletes a relationship', async () => {\n await provider.createRelationship(repoId, makeRelationship('r1', 'connects', 'a', 'b'));\n await provider.deleteRelationship(repoId, 'r1');\n expect(await provider.getRelationship(repoId, 'r1')).toBeNull();\n });\n });\n\n // ─── Graph Traversal ────────────────────────────────────\n\n describe('graph traversal', () => {\n beforeEach(async () => {\n await provider.createEntity(repoId, makeEntity('a', 'node', 'A'));\n await provider.createEntity(repoId, makeEntity('b', 'node', 'B'));\n await provider.createEntity(repoId, makeEntity('c', 'node', 'C'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'a', 'b'));\n await provider.createRelationship(repoId, makeRelationship('r2', 'links', 'b', 'c'));\n });\n\n it('explores neighborhood at depth 1', async () => {\n const result = await provider.exploreNeighborhood(repoId, 'a', {\n depth: 1,\n direction: 'both',\n limitPerType: 10,\n offsetPerType: 0,\n });\n expect(result.centerId).toBe('a');\n expect(result.layers).toHaveLength(1);\n });\n\n it('finds paths between connected entities', async () => {\n const result = await provider.findPaths(repoId, 'a', 'c', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('c');\n });\n\n it('returns empty paths when no connection', async () => {\n await provider.createEntity(repoId, makeEntity('isolated', 'node', 'Isolated'));\n const result = await provider.findPaths(repoId, 'a', 'isolated', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths).toHaveLength(0);\n });\n\n it('finds paths through non-bidirectional inbound edges', async () => {\n // Graph: a → b ← d (both edges are non-bidirectional)\n // Path from a to d should traverse: a →(outbound) b ←(inbound) d\n await provider.createEntity(repoId, makeEntity('d', 'node', 'D'));\n await provider.createRelationship(repoId, makeRelationship('r3', 'links', 'd', 'b'));\n const result = await provider.findPaths(repoId, 'a', 'd', {\n maxDepth: 3,\n limit: 5,\n offset: 0,\n });\n expect(result.paths.length).toBeGreaterThanOrEqual(1);\n const firstPath = result.paths[0]!;\n expect(firstPath.entityIds[0]).toBe('a');\n expect(firstPath.entityIds[firstPath.entityIds.length - 1]).toBe('d');\n });\n });\n\n // ─── Timeline ───────────────────────────────────────────\n\n describe('timeline', () => {\n it('returns timeline events', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n const result = await provider.getTimeline(repoId, 'e1', {\n limit: 10,\n offset: 0,\n });\n expect(result.events.length).toBeGreaterThanOrEqual(1);\n });\n });\n\n // ─── Bulk Operations ────────────────────────────────────\n\n describe('bulk operations', () => {\n it('exports data', async () => {\n await provider.createEntity(repoId, makeEntity('e1'));\n\n const chunks = [];\n for await (const chunk of provider.exportAll(repoId)) {\n chunks.push(chunk);\n }\n expect(chunks.length).toBeGreaterThanOrEqual(1);\n });\n\n it('imports data', async () => {\n const result = await provider.importBulk(repoId, [\n { entities: [makeEntity('imported-1'), makeEntity('imported-2')] },\n { relationships: [makeRelationship('ir1', 'links', 'imported-1', 'imported-2')] },\n ]);\n expect(result.entitiesImported).toBe(2);\n expect(result.relationshipsImported).toBe(1);\n\n // Verify imported data is accessible\n const e = await provider.getEntity(repoId, 'imported-1');\n expect(e).not.toBeNull();\n });\n });\n\n // ─── Delete All Contents ───────────────────────────────\n\n describe('deleteAllContents', () => {\n it('deletes all entities and relationships but preserves the repository', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(2);\n expect(result.deletedRelationships).toBe(1);\n\n // Repository still exists\n const repo = await provider.getRepository(repoId);\n expect(repo).not.toBeNull();\n\n // Vocabulary still exists\n const vocab = await provider.getVocabulary(repoId);\n expect(vocab).toBeDefined();\n\n // Contents are gone\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(0);\n expect(stats.relationshipCount).toBe(0);\n });\n\n it('returns zero counts on an empty repository', async () => {\n const result = await provider.deleteAllContents(repoId);\n expect(result.deletedEntities).toBe(0);\n expect(result.deletedRelationships).toBe(0);\n });\n });\n\n // ─── Stats after data ───────────────────────────────────\n\n describe('stats reflect data', () => {\n it('counts entities and relationships', async () => {\n await provider.createEntity(repoId, makeEntity('e1', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e2', 'alpha'));\n await provider.createEntity(repoId, makeEntity('e3', 'beta'));\n await provider.createRelationship(repoId, makeRelationship('r1', 'links', 'e1', 'e2'));\n\n const stats = await provider.getRepositoryStats(repoId);\n expect(stats.entityCount).toBe(3);\n expect(stats.relationshipCount).toBe(1);\n expect(stats.entityTypeBreakdown['alpha']).toBe(2);\n expect(stats.entityTypeBreakdown['beta']).toBe(1);\n expect(stats.relationshipTypeBreakdown['links']).toBe(1);\n });\n });\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Y as PropertyFilter, h as DetailLevel, i as Entity, l as EntitySummary, j as EntityBrief, a6 as RelationshipSummary } from './portability-
|
|
1
|
+
import { Y as PropertyFilter, h as DetailLevel, i as Entity, l as EntitySummary, j as EntityBrief, a6 as RelationshipSummary } from './portability-CAeyzSCx.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* An entity as returned inside a TraversalResult — the projected entity plus
|
|
@@ -57,7 +57,7 @@ interface TraversalSpec {
|
|
|
57
57
|
/** Whether to deduplicate entities in the result set. Default: true. */
|
|
58
58
|
dedup?: boolean;
|
|
59
59
|
/**
|
|
60
|
-
* Whether to include a relationship summary (
|
|
60
|
+
* Whether to include a relationship summary (out/in counts by type)
|
|
61
61
|
* on each entity in the result. Default: false.
|
|
62
62
|
*
|
|
63
63
|
* Native GraphTraversalProviders (Gremlin, Cypher) can return this in a single
|
|
@@ -118,7 +118,12 @@ interface TraversalStart {
|
|
|
118
118
|
* A single step in the traversal — one hop along a relationship edge.
|
|
119
119
|
*/
|
|
120
120
|
interface TraversalStep {
|
|
121
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Direction to traverse, relative to the entity at the start of the hop:
|
|
123
|
+
* - `'out'` — follow edges where the current entity is the source
|
|
124
|
+
* - `'in'` — follow edges where the current entity is the target
|
|
125
|
+
* - `'both'` — follow edges in either direction
|
|
126
|
+
*/
|
|
122
127
|
direction: 'out' | 'in' | 'both';
|
|
123
128
|
/**
|
|
124
129
|
* Relationship types to follow in this step.
|
|
@@ -221,18 +226,18 @@ interface TraversalRelationship {
|
|
|
221
226
|
/**
|
|
222
227
|
* Walk direction at the last hop, with mode-specific semantics:
|
|
223
228
|
*
|
|
224
|
-
* - **`'path'` mode** — `'
|
|
225
|
-
* `sourceEntityId` to `targetEntityId`, `'
|
|
229
|
+
* - **`'path'` mode** — `'out'` when the walk crossed the edge from
|
|
230
|
+
* `sourceEntityId` to `targetEntityId`, `'in'` when it crossed in
|
|
226
231
|
* the opposite direction. Computed relative to the entity at the
|
|
227
232
|
* start of the hop within each `TraversalPath`.
|
|
228
|
-
* - **`'all'` mode** — always `'
|
|
233
|
+
* - **`'all'` mode** — always `'out'`. Reflects the stored edge
|
|
229
234
|
* topology (`sourceEntityId` → `targetEntityId`), not any particular
|
|
230
235
|
* walk; the deduped union has no walk context. Callers can derive
|
|
231
236
|
* walk-direction relative to any anchor using `sourceEntityId` /
|
|
232
237
|
* `targetEntityId`.
|
|
233
238
|
* - **`'terminal'` mode** — relationships are not returned.
|
|
234
239
|
*/
|
|
235
|
-
direction: '
|
|
240
|
+
direction: 'out' | 'in';
|
|
236
241
|
properties: Record<string, unknown>;
|
|
237
242
|
}
|
|
238
243
|
interface TraversalPath {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Y as PropertyFilter, h as DetailLevel, i as Entity, l as EntitySummary, j as EntityBrief, a6 as RelationshipSummary } from './portability-
|
|
1
|
+
import { Y as PropertyFilter, h as DetailLevel, i as Entity, l as EntitySummary, j as EntityBrief, a6 as RelationshipSummary } from './portability-CAeyzSCx.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* An entity as returned inside a TraversalResult — the projected entity plus
|
|
@@ -57,7 +57,7 @@ interface TraversalSpec {
|
|
|
57
57
|
/** Whether to deduplicate entities in the result set. Default: true. */
|
|
58
58
|
dedup?: boolean;
|
|
59
59
|
/**
|
|
60
|
-
* Whether to include a relationship summary (
|
|
60
|
+
* Whether to include a relationship summary (out/in counts by type)
|
|
61
61
|
* on each entity in the result. Default: false.
|
|
62
62
|
*
|
|
63
63
|
* Native GraphTraversalProviders (Gremlin, Cypher) can return this in a single
|
|
@@ -118,7 +118,12 @@ interface TraversalStart {
|
|
|
118
118
|
* A single step in the traversal — one hop along a relationship edge.
|
|
119
119
|
*/
|
|
120
120
|
interface TraversalStep {
|
|
121
|
-
/**
|
|
121
|
+
/**
|
|
122
|
+
* Direction to traverse, relative to the entity at the start of the hop:
|
|
123
|
+
* - `'out'` — follow edges where the current entity is the source
|
|
124
|
+
* - `'in'` — follow edges where the current entity is the target
|
|
125
|
+
* - `'both'` — follow edges in either direction
|
|
126
|
+
*/
|
|
122
127
|
direction: 'out' | 'in' | 'both';
|
|
123
128
|
/**
|
|
124
129
|
* Relationship types to follow in this step.
|
|
@@ -221,18 +226,18 @@ interface TraversalRelationship {
|
|
|
221
226
|
/**
|
|
222
227
|
* Walk direction at the last hop, with mode-specific semantics:
|
|
223
228
|
*
|
|
224
|
-
* - **`'path'` mode** — `'
|
|
225
|
-
* `sourceEntityId` to `targetEntityId`, `'
|
|
229
|
+
* - **`'path'` mode** — `'out'` when the walk crossed the edge from
|
|
230
|
+
* `sourceEntityId` to `targetEntityId`, `'in'` when it crossed in
|
|
226
231
|
* the opposite direction. Computed relative to the entity at the
|
|
227
232
|
* start of the hop within each `TraversalPath`.
|
|
228
|
-
* - **`'all'` mode** — always `'
|
|
233
|
+
* - **`'all'` mode** — always `'out'`. Reflects the stored edge
|
|
229
234
|
* topology (`sourceEntityId` → `targetEntityId`), not any particular
|
|
230
235
|
* walk; the deduped union has no walk context. Callers can derive
|
|
231
236
|
* walk-direction relative to any anchor using `sourceEntityId` /
|
|
232
237
|
* `targetEntityId`.
|
|
233
238
|
* - **`'terminal'` mode** — relationships are not returned.
|
|
234
239
|
*/
|
|
235
|
-
direction: '
|
|
240
|
+
direction: 'out' | 'in';
|
|
236
241
|
properties: Record<string, unknown>;
|
|
237
242
|
}
|
|
238
243
|
interface TraversalPath {
|