@utaba/deep-memory 0.16.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.
@@ -473,8 +473,13 @@ interface SearchOptions extends PaginationOptions {
473
473
  entityTypes?: string[];
474
474
  }
475
475
 
476
- /** Direction filter for relationship queries */
477
- type RelationshipDirection = 'outbound' | 'inbound' | 'both';
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
- /** Aggregated relationship counts by type and direction */
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
- outbound: Record<string, number>;
528
- inbound: Record<string, number>;
537
+ out: Record<string, number>;
538
+ in: Record<string, number>;
529
539
  }
530
540
  /** Result of a bulk relationship removal */
531
541
  interface RemoveRelationshipsResult {
@@ -668,10 +678,22 @@ interface ValidationResult {
668
678
  errors: ValidationError[];
669
679
  }
670
680
 
671
- /** Paginated result wrapper */
681
+ /**
682
+ * Paginated result wrapper.
683
+ *
684
+ * `total` is the exact count of items matching the query when the storage
685
+ * provider can compute it cheaply (typically via a parallel `COUNT(1)` or
686
+ * equivalent on an indexed predicate). It is `undefined` when computing an
687
+ * exact total would be more expensive than the query itself — e.g. the Cosmos
688
+ * `findEntities` path with `properties` filters, where the server-side
689
+ * approximate prefilter would inflate a count by false positives that are
690
+ * only resolved client-side. Callers that need a "more pages?" signal should
691
+ * use `hasMore`, which providers derive from `total` when present and from
692
+ * `items.length === limit` otherwise.
693
+ */
672
694
  interface PaginatedResult<T> {
673
695
  items: T[];
674
- total: number;
696
+ total: number | undefined;
675
697
  hasMore: boolean;
676
698
  limit: number;
677
699
  offset: number;
@@ -1194,4 +1216,4 @@ interface ImportResult {
1194
1216
  warnings: ImportWarning[];
1195
1217
  }
1196
1218
 
1197
- export type { ConceptSearchOptions as $, EntityTypeDefinition as A, BulkImportOptions as B, CreateEntityInput as C, DetailLevel as D, Entity as E, VocabularyProposal as F, GovernanceConfig as G, VocabularyProposalResult as H, ImportChunk as I, ProvenanceContext as J, Provenance as K, FindEntitiesQuery as L, MemoryVocabulary as M, DeleteEntitiesResult as N, ReembedResult as O, PropertyFilter as P, Relationship as Q, RelationshipSummary as R, StorageRepositoryConfig as S, RemoveRelationshipsResult as T, UpdateEntityInput as U, VocabularyChangeRecord as V, GraphResult as W, ExploreOptions as X, Neighborhood as Y, PathOptions as Z, PathResult as _, EntitySummary as a, ScoredEntity as a0, TimelineOptions as a1, TimelineResult as a2, ValidateEntitiesOptions as a3, EntityValidationPage as a4, ValidateRelationshipsOptions as a5, RelationshipValidationPage as a6, RepositoryConfig as a7, RepositorySummary as a8, ExportOptions as a9, PropertySchema as aA, PropertyType as aB, ProvenanceFilter as aC, RelationshipDirection as aD, RelationshipTypeDefinition as aE, RelationshipTypeInput as aF, RelationshipValidationIssue as aG, RepositoryMetadata as aH, StorageNeighborhoodGroup as aI, StorageNeighborhoodLayer as aJ, StoragePath as aK, StorageTimelineEvent as aL, TimelineEntityRef as aM, TimelineEvent as aN, TimelineRelationshipDetail as aO, VocabularyInput as aP, ExportArchive as aa, ImportOptions as ab, ImportResult as ac, ExportStreamItem as ad, ImportStreamHeader as ae, SearchOptions as af, SearchHit as ag, AdaptiveConcurrencyAdjustEvent as ah, AdaptiveConcurrencyAdjustReason as ai, AdaptiveConcurrencyHandle as aj, AdaptiveConcurrencyOptions as ak, EnrichedRelationship as al, EntityMap as am, EntityTypeInput as an, EntityValidationIssue as ao, ExportLegalMetadata as ap, ExportManifest as aq, ExportPipelineMetadata as ar, GetEntitiesOptions as as, GetEntityOptions as at, GovernanceMode as au, ImportWarning as av, NeighborhoodCenter as aw, NeighborhoodGroup as ax, NeighborhoodLayer as ay, Path as az, EntityBrief as b, StoredRepository as c, RepositoryFilter as d, PaginatedResult as e, StoredRepositorySummary as f, RepositoryUpdate as g, DeleteProgressCallback as h, RepositoryStats as i, PaginationOptions as j, StoredEntity as k, StoredEntityUpdate as l, StorageFindQuery as m, StoredRelationship as n, RelationshipQueryOptions as o, StorageExploreOptions as p, StorageNeighborhood as q, StoragePathOptions as r, StoragePathResult as s, StorageTimelineOptions as t, StorageTimelineResult as u, ExportChunk as v, BulkImportResult as w, ResolvedVocabulary as x, ValidationResult as y, CreateRelationshipInput as z };
1219
+ export type { Provenance as $, AdaptiveConcurrencyAdjustEvent as A, BulkImportOptions as B, ConceptSearchOptions as C, DeleteEntitiesResult as D, EnrichedRelationship as E, FindEntitiesQuery as F, GetEntitiesOptions as G, GovernanceMode as H, GraphResult as I, ImportChunk as J, ImportOptions as K, ImportResult as L, ImportStreamHeader as M, ImportWarning as N, MemoryVocabulary as O, Neighborhood as P, NeighborhoodCenter as Q, NeighborhoodGroup as R, NeighborhoodLayer as S, PaginatedResult as T, PaginationOptions as U, Path as V, PathOptions as W, PathResult as X, PropertyFilter as Y, PropertySchema as Z, PropertyType as _, AdaptiveConcurrencyAdjustReason as a, ProvenanceContext as a0, ProvenanceFilter as a1, ReembedResult as a2, Relationship as a3, RelationshipDirection as a4, RelationshipQueryOptions as a5, RelationshipSummary as a6, RelationshipTypeDefinition as a7, RelationshipTypeInput as a8, RelationshipValidationIssue as a9, StoredRelationship as aA, StoredRepository as aB, StoredRepositorySummary as aC, TimelineEntityRef as aD, TimelineEvent as aE, TimelineOptions as aF, TimelineRelationshipDetail as aG, TimelineResult as aH, UpdateEntityInput as aI, ValidateEntitiesOptions as aJ, ValidateRelationshipsOptions as aK, ValidationResult as aL, VocabularyChangeRecord as aM, VocabularyInput as aN, VocabularyProposal as aO, VocabularyProposalResult as aP, RelationshipValidationPage as aa, RemoveRelationshipsResult as ab, RepositoryConfig as ac, RepositoryFilter as ad, RepositoryMetadata as ae, RepositoryStats as af, RepositorySummary as ag, RepositoryUpdate as ah, ResolvedVocabulary as ai, ScoredEntity as aj, SearchHit as ak, SearchOptions as al, StorageExploreOptions as am, StorageFindQuery as an, StorageNeighborhood as ao, StorageNeighborhoodGroup as ap, StorageNeighborhoodLayer as aq, StoragePath as ar, StoragePathOptions as as, StoragePathResult as at, StorageRepositoryConfig as au, StorageTimelineEvent as av, StorageTimelineOptions as aw, StorageTimelineResult as ax, StoredEntity as ay, StoredEntityUpdate as az, AdaptiveConcurrencyHandle as b, AdaptiveConcurrencyOptions as c, BulkImportResult as d, CreateEntityInput as e, CreateRelationshipInput as f, DeleteProgressCallback as g, DetailLevel as h, Entity as i, EntityBrief as j, EntityMap as k, EntitySummary as l, EntityTypeDefinition as m, EntityTypeInput as n, EntityValidationIssue as o, EntityValidationPage as p, ExploreOptions as q, ExportArchive as r, ExportChunk as s, ExportLegalMetadata as t, ExportManifest as u, ExportOptions as v, ExportPipelineMetadata as w, ExportStreamItem as x, GetEntityOptions as y, GovernanceConfig as z };
@@ -473,8 +473,13 @@ interface SearchOptions extends PaginationOptions {
473
473
  entityTypes?: string[];
474
474
  }
475
475
 
476
- /** Direction filter for relationship queries */
477
- type RelationshipDirection = 'outbound' | 'inbound' | 'both';
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
- /** Aggregated relationship counts by type and direction */
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
- outbound: Record<string, number>;
528
- inbound: Record<string, number>;
537
+ out: Record<string, number>;
538
+ in: Record<string, number>;
529
539
  }
530
540
  /** Result of a bulk relationship removal */
531
541
  interface RemoveRelationshipsResult {
@@ -668,10 +678,22 @@ interface ValidationResult {
668
678
  errors: ValidationError[];
669
679
  }
670
680
 
671
- /** Paginated result wrapper */
681
+ /**
682
+ * Paginated result wrapper.
683
+ *
684
+ * `total` is the exact count of items matching the query when the storage
685
+ * provider can compute it cheaply (typically via a parallel `COUNT(1)` or
686
+ * equivalent on an indexed predicate). It is `undefined` when computing an
687
+ * exact total would be more expensive than the query itself — e.g. the Cosmos
688
+ * `findEntities` path with `properties` filters, where the server-side
689
+ * approximate prefilter would inflate a count by false positives that are
690
+ * only resolved client-side. Callers that need a "more pages?" signal should
691
+ * use `hasMore`, which providers derive from `total` when present and from
692
+ * `items.length === limit` otherwise.
693
+ */
672
694
  interface PaginatedResult<T> {
673
695
  items: T[];
674
- total: number;
696
+ total: number | undefined;
675
697
  hasMore: boolean;
676
698
  limit: number;
677
699
  offset: number;
@@ -1194,4 +1216,4 @@ interface ImportResult {
1194
1216
  warnings: ImportWarning[];
1195
1217
  }
1196
1218
 
1197
- export type { ConceptSearchOptions as $, EntityTypeDefinition as A, BulkImportOptions as B, CreateEntityInput as C, DetailLevel as D, Entity as E, VocabularyProposal as F, GovernanceConfig as G, VocabularyProposalResult as H, ImportChunk as I, ProvenanceContext as J, Provenance as K, FindEntitiesQuery as L, MemoryVocabulary as M, DeleteEntitiesResult as N, ReembedResult as O, PropertyFilter as P, Relationship as Q, RelationshipSummary as R, StorageRepositoryConfig as S, RemoveRelationshipsResult as T, UpdateEntityInput as U, VocabularyChangeRecord as V, GraphResult as W, ExploreOptions as X, Neighborhood as Y, PathOptions as Z, PathResult as _, EntitySummary as a, ScoredEntity as a0, TimelineOptions as a1, TimelineResult as a2, ValidateEntitiesOptions as a3, EntityValidationPage as a4, ValidateRelationshipsOptions as a5, RelationshipValidationPage as a6, RepositoryConfig as a7, RepositorySummary as a8, ExportOptions as a9, PropertySchema as aA, PropertyType as aB, ProvenanceFilter as aC, RelationshipDirection as aD, RelationshipTypeDefinition as aE, RelationshipTypeInput as aF, RelationshipValidationIssue as aG, RepositoryMetadata as aH, StorageNeighborhoodGroup as aI, StorageNeighborhoodLayer as aJ, StoragePath as aK, StorageTimelineEvent as aL, TimelineEntityRef as aM, TimelineEvent as aN, TimelineRelationshipDetail as aO, VocabularyInput as aP, ExportArchive as aa, ImportOptions as ab, ImportResult as ac, ExportStreamItem as ad, ImportStreamHeader as ae, SearchOptions as af, SearchHit as ag, AdaptiveConcurrencyAdjustEvent as ah, AdaptiveConcurrencyAdjustReason as ai, AdaptiveConcurrencyHandle as aj, AdaptiveConcurrencyOptions as ak, EnrichedRelationship as al, EntityMap as am, EntityTypeInput as an, EntityValidationIssue as ao, ExportLegalMetadata as ap, ExportManifest as aq, ExportPipelineMetadata as ar, GetEntitiesOptions as as, GetEntityOptions as at, GovernanceMode as au, ImportWarning as av, NeighborhoodCenter as aw, NeighborhoodGroup as ax, NeighborhoodLayer as ay, Path as az, EntityBrief as b, StoredRepository as c, RepositoryFilter as d, PaginatedResult as e, StoredRepositorySummary as f, RepositoryUpdate as g, DeleteProgressCallback as h, RepositoryStats as i, PaginationOptions as j, StoredEntity as k, StoredEntityUpdate as l, StorageFindQuery as m, StoredRelationship as n, RelationshipQueryOptions as o, StorageExploreOptions as p, StorageNeighborhood as q, StoragePathOptions as r, StoragePathResult as s, StorageTimelineOptions as t, StorageTimelineResult as u, ExportChunk as v, BulkImportResult as w, ResolvedVocabulary as x, ValidationResult as y, CreateRelationshipInput as z };
1219
+ export type { Provenance as $, AdaptiveConcurrencyAdjustEvent as A, BulkImportOptions as B, ConceptSearchOptions as C, DeleteEntitiesResult as D, EnrichedRelationship as E, FindEntitiesQuery as F, GetEntitiesOptions as G, GovernanceMode as H, GraphResult as I, ImportChunk as J, ImportOptions as K, ImportResult as L, ImportStreamHeader as M, ImportWarning as N, MemoryVocabulary as O, Neighborhood as P, NeighborhoodCenter as Q, NeighborhoodGroup as R, NeighborhoodLayer as S, PaginatedResult as T, PaginationOptions as U, Path as V, PathOptions as W, PathResult as X, PropertyFilter as Y, PropertySchema as Z, PropertyType as _, AdaptiveConcurrencyAdjustReason as a, ProvenanceContext as a0, ProvenanceFilter as a1, ReembedResult as a2, Relationship as a3, RelationshipDirection as a4, RelationshipQueryOptions as a5, RelationshipSummary as a6, RelationshipTypeDefinition as a7, RelationshipTypeInput as a8, RelationshipValidationIssue as a9, StoredRelationship as aA, StoredRepository as aB, StoredRepositorySummary as aC, TimelineEntityRef as aD, TimelineEvent as aE, TimelineOptions as aF, TimelineRelationshipDetail as aG, TimelineResult as aH, UpdateEntityInput as aI, ValidateEntitiesOptions as aJ, ValidateRelationshipsOptions as aK, ValidationResult as aL, VocabularyChangeRecord as aM, VocabularyInput as aN, VocabularyProposal as aO, VocabularyProposalResult as aP, RelationshipValidationPage as aa, RemoveRelationshipsResult as ab, RepositoryConfig as ac, RepositoryFilter as ad, RepositoryMetadata as ae, RepositoryStats as af, RepositorySummary as ag, RepositoryUpdate as ah, ResolvedVocabulary as ai, ScoredEntity as aj, SearchHit as ak, SearchOptions as al, StorageExploreOptions as am, StorageFindQuery as an, StorageNeighborhood as ao, StorageNeighborhoodGroup as ap, StorageNeighborhoodLayer as aq, StoragePath as ar, StoragePathOptions as as, StoragePathResult as at, StorageRepositoryConfig as au, StorageTimelineEvent as av, StorageTimelineOptions as aw, StorageTimelineResult as ax, StoredEntity as ay, StoredEntityUpdate as az, AdaptiveConcurrencyHandle as b, AdaptiveConcurrencyOptions as c, BulkImportResult as d, CreateEntityInput as e, CreateRelationshipInput as f, DeleteProgressCallback as g, DetailLevel as h, Entity as i, EntityBrief as j, EntityMap as k, EntitySummary as l, EntityTypeDefinition as m, EntityTypeInput as n, EntityValidationIssue as o, EntityValidationPage as p, ExploreOptions as q, ExportArchive as r, ExportChunk as s, ExportLegalMetadata as t, ExportManifest as u, ExportOptions as v, ExportPipelineMetadata as w, ExportStreamItem as x, GetEntityOptions as y, GovernanceConfig as z };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/index.ts"],"sourcesContent":["// Provider interface re-exports — @utaba/deep-memory/providers\n\nexport type { StorageProvider, EnsureSchemaResult } from './StorageProvider.js';\nexport type { EmbeddingProvider, EmbeddingProviderFactory } from './EmbeddingProvider.js';\nexport type {\n SearchProvider,\n SearchableEntity,\n} from './SearchProvider.js';\nexport type {\n LockProvider,\n LockOptions,\n LockHandle,\n} from './LockProvider.js';\nexport type {\n GraphTraversalProvider,\n GraphTraversalCapabilities,\n} from './GraphTraversalProvider.js';\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/index.ts"],"sourcesContent":["// Provider interface re-exports — @utaba/deep-memory/providers\n\nexport type { StorageProvider, EnsureSchemaResult, EntityReadOptions } from './StorageProvider.js';\nexport type { EmbeddingProvider, EmbeddingProviderFactory } from './EmbeddingProvider.js';\nexport type {\n SearchProvider,\n SearchableEntity,\n} from './SearchProvider.js';\nexport type {\n LockProvider,\n LockOptions,\n LockHandle,\n} from './LockProvider.js';\nexport type {\n GraphTraversalProvider,\n GraphTraversalCapabilities,\n} from './GraphTraversalProvider.js';\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -1,6 +1,6 @@
1
- export { E as EnsureSchemaResult, S as StorageProvider } from '../StorageProvider-BGtKZZt4.cjs';
2
- import { af as SearchOptions, e as PaginatedResult, ag as SearchHit } from '../portability-P1hL-bOa.cjs';
3
- import { T as TraversalSpec, a as TraversalResult } from '../traversal-CBE5h5ob.cjs';
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 (outbound/inbound
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, S as StorageProvider } from '../StorageProvider-D_o2Hksf.js';
2
- import { af as SearchOptions, e as PaginatedResult, ag as SearchHit } from '../portability-P1hL-bOa.js';
3
- import { T as TraversalSpec, a as TraversalResult } from '../traversal-B_84kGaO.js';
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 (outbound/inbound
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
  */
@@ -226,6 +226,16 @@ function runStorageProviderConformanceTests(factory) {
226
226
  (0, import_vitest.expect)(result.items).toHaveLength(1);
227
227
  (0, import_vitest.expect)(result.items[0].label).toBe("Alpha");
228
228
  });
229
+ (0, import_vitest.it)("finds entities by search term case-insensitively", async () => {
230
+ await provider.createEntity(repoId, makeEntity("e1", "test-type", "Alpha"));
231
+ const result = await provider.findEntities(repoId, {
232
+ searchTerm: "ALPHA",
233
+ limit: 10,
234
+ offset: 0
235
+ });
236
+ (0, import_vitest.expect)(result.items).toHaveLength(1);
237
+ (0, import_vitest.expect)(result.items[0].label).toBe("Alpha");
238
+ });
229
239
  (0, import_vitest.it)("finds entities by type filter", async () => {
230
240
  await provider.createEntity(repoId, makeEntity("e1", "type-a", "A"));
231
241
  await provider.createEntity(repoId, makeEntity("e2", "type-b", "B"));
@@ -275,10 +285,10 @@ function runStorageProviderConformanceTests(factory) {
275
285
  (0, import_vitest.it)("filters relationships by direction", async () => {
276
286
  await provider.createRelationship(repoId, makeRelationship("r1", "connects", "a", "b"));
277
287
  await provider.createRelationship(repoId, makeRelationship("r2", "connects", "c", "a"));
278
- const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "outbound" });
288
+ const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "out" });
279
289
  (0, import_vitest.expect)(outbound.items).toHaveLength(1);
280
290
  (0, import_vitest.expect)(outbound.items[0].targetEntityId).toBe("b");
281
- const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "inbound" });
291
+ const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "in" });
282
292
  (0, import_vitest.expect)(inbound.items).toHaveLength(1);
283
293
  (0, import_vitest.expect)(inbound.items[0].sourceEntityId).toBe("c");
284
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 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,5 +1,5 @@
1
- import { S as StorageProvider } from '../StorageProvider-BGtKZZt4.cjs';
2
- import '../portability-P1hL-bOa.cjs';
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-D_o2Hksf.js';
2
- import '../portability-P1hL-bOa.js';
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.
@@ -202,6 +202,16 @@ function runStorageProviderConformanceTests(factory) {
202
202
  expect(result.items).toHaveLength(1);
203
203
  expect(result.items[0].label).toBe("Alpha");
204
204
  });
205
+ it("finds entities by search term case-insensitively", async () => {
206
+ await provider.createEntity(repoId, makeEntity("e1", "test-type", "Alpha"));
207
+ const result = await provider.findEntities(repoId, {
208
+ searchTerm: "ALPHA",
209
+ limit: 10,
210
+ offset: 0
211
+ });
212
+ expect(result.items).toHaveLength(1);
213
+ expect(result.items[0].label).toBe("Alpha");
214
+ });
205
215
  it("finds entities by type filter", async () => {
206
216
  await provider.createEntity(repoId, makeEntity("e1", "type-a", "A"));
207
217
  await provider.createEntity(repoId, makeEntity("e2", "type-b", "B"));
@@ -251,10 +261,10 @@ function runStorageProviderConformanceTests(factory) {
251
261
  it("filters relationships by direction", async () => {
252
262
  await provider.createRelationship(repoId, makeRelationship("r1", "connects", "a", "b"));
253
263
  await provider.createRelationship(repoId, makeRelationship("r2", "connects", "c", "a"));
254
- const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "outbound" });
264
+ const outbound = await provider.getEntityRelationships(repoId, "a", { direction: "out" });
255
265
  expect(outbound.items).toHaveLength(1);
256
266
  expect(outbound.items[0].targetEntityId).toBe("b");
257
- const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "inbound" });
267
+ const inbound = await provider.getEntityRelationships(repoId, "a", { direction: "in" });
258
268
  expect(inbound.items).toHaveLength(1);
259
269
  expect(inbound.items[0].sourceEntityId).toBe("c");
260
270
  });