@mirk/store 0.4.2 → 0.6.1

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/sql.js ADDED
@@ -0,0 +1,14 @@
1
+ import {
2
+ buildLimitOffset,
3
+ buildOrderBy,
4
+ buildWhereClause,
5
+ hashName,
6
+ jsonPath
7
+ } from "./chunk-DP4D7CJY.js";
8
+ export {
9
+ buildLimitOffset,
10
+ buildOrderBy,
11
+ buildWhereClause,
12
+ hashName,
13
+ jsonPath
14
+ };
@@ -32,6 +32,13 @@ interface VectorSearchOptions {
32
32
  topK?: number;
33
33
  /** Minimum cosine similarity; results below are excluded. Default: no floor. */
34
34
  minScore?: number;
35
+ /** Pre-KNN filter: only consider documents whose metadata satisfies ALL of these
36
+ * exact-match conditions. Applied before scoring, so topK is out of the passing
37
+ * set only. `where` and `whereNot` are independent — both may be provided. */
38
+ where?: Record<string, unknown>;
39
+ /** Pre-KNN filter: exclude documents whose metadata satisfies ANY of these
40
+ * exact-match conditions. Applied before scoring. */
41
+ whereNot?: Record<string, unknown>;
35
42
  }
36
43
  /** A synchronous vector similarity store with per-collection documents.
37
44
  *
@@ -46,12 +53,31 @@ interface VectorStore {
46
53
  upsertMany<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, docs: ReadonlyArray<VectorDocument<M>>): void;
47
54
  /** Fetch a document by id, or null. */
48
55
  get<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, id: string): VectorDocument<M> | null;
56
+ /** Check whether a document exists by (collection, id). */
57
+ has(collection: string, id: string): boolean;
49
58
  /** Remove a document by id. Returns true if it existed. */
50
59
  remove(collection: string, id: string): boolean;
51
60
  /** Number of documents in a collection. */
52
61
  count(collection: string): number;
53
- /** k-nearest-neighbour search by cosine similarity, highest score first. */
62
+ /** k-nearest-neighbour search by cosine similarity, highest score first.
63
+ * Supports pre-KNN filtering via opts.where / opts.whereNot. */
54
64
  search<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, query: Vector, opts?: VectorSearchOptions): VectorSearchResult<M>[];
55
65
  }
66
+ /** The async face of the same vector store. Remote backends (e.g. Qdrant) implement
67
+ * this natively; sync backends reach it via {@link toAsyncVector}.
68
+ *
69
+ * Hand-written rather than derived from VectorStore via a mapped type: per-method
70
+ * generics (`get<M>`, `search<M>`, …) collapse to `unknown` under inference — same
71
+ * constraint as the KV AsyncStore twin in src/types.ts. */
72
+ interface AsyncVectorStore {
73
+ readonly meta: VectorStoreMeta;
74
+ upsert<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, doc: VectorDocument<M>): Promise<void>;
75
+ upsertMany<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, docs: ReadonlyArray<VectorDocument<M>>): Promise<void>;
76
+ get<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, id: string): Promise<VectorDocument<M> | null>;
77
+ has(collection: string, id: string): Promise<boolean>;
78
+ remove(collection: string, id: string): Promise<boolean>;
79
+ count(collection: string): Promise<number>;
80
+ search<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, query: Vector, opts?: VectorSearchOptions): Promise<VectorSearchResult<M>[]>;
81
+ }
56
82
 
57
- export type { Vector as V, VectorDocument as a, VectorSearchOptions as b, VectorSearchResult as c, VectorStore as d, VectorStoreMeta as e };
83
+ export type { AsyncVectorStore as A, Vector as V, VectorDocument as a, VectorSearchOptions as b, VectorSearchResult as c, VectorStore as d, VectorStoreMeta as e };
@@ -0,0 +1,69 @@
1
+ import { S as StoreFilter } from './types-DHLdLZ_W.js';
2
+
3
+ /** A document to be full-text indexed. `meta` is an exact-match-filterable
4
+ * payload persisted as JSON by disk-backed backends, so it must be JSON-
5
+ * serializable; values JSON can't represent (`undefined`, functions) are dropped
6
+ * on persistence — don't rely on them. */
7
+ interface SearchTextDocument<M = Record<string, unknown>> {
8
+ /** Unique id within the collection. */
9
+ id: string;
10
+ /** Single-field text to tokenize and index. Back-compat shorthand for
11
+ * `fields: { text }`. */
12
+ text: string;
13
+ /** Provide either `text` or `fields`, not both. */
14
+ fields?: never;
15
+ /** Typed context stored alongside the text. */
16
+ meta?: M;
17
+ }
18
+ interface SearchFieldDocument<M = Record<string, unknown>> {
19
+ /** Unique id within the collection. */
20
+ id: string;
21
+ /** Named text fields to tokenize and index with optional query-time weights
22
+ * (for example `{ title, body }`). All documents in a collection must use the
23
+ * same field names. */
24
+ fields: Record<string, string>;
25
+ /** Provide either `text` or `fields`, not both. */
26
+ text?: never;
27
+ /** Typed context stored alongside the text. */
28
+ meta?: M;
29
+ }
30
+ type SearchDocument<M = Record<string, unknown>> = SearchTextDocument<M> | SearchFieldDocument<M>;
31
+ interface SearchOptions {
32
+ /** Maximum results to return. Default: 10. */
33
+ limit?: number;
34
+ /** Exact-match filter on document `meta` (uses `filter.where`, evaluated with
35
+ * the shared `matchesWhere`). Applied before limit, after the FTS MATCH. */
36
+ filter?: StoreFilter;
37
+ /** Per-field bm25 weights. Fields not listed default to 1. Higher means more
38
+ * important; e.g. `{ title: 4, body: 1 }` boosts title matches. */
39
+ fieldWeights?: Record<string, number>;
40
+ }
41
+ /** A ranked search hit. `score` is the bm25 relevance — higher is more relevant. */
42
+ interface SearchResult<M = Record<string, unknown>> {
43
+ id: string;
44
+ /** bm25 relevance. Higher = more relevant. (sqlite exposes `-bm25(fts)`; the
45
+ * in-memory reference computes the same quantity directly.) */
46
+ score: number;
47
+ /** The document's `meta`, or `{}` when none was indexed. */
48
+ meta: M;
49
+ }
50
+ /** A synchronous full-text search store with per-collection documents.
51
+ *
52
+ * Ranking is bm25 with the FTS5 default parameters (k1 = 1.2, b = 0.75), plus
53
+ * optional query-time per-field weights. The in-memory reference and the sqlite
54
+ * `.search` facet produce the same RANKING on clear relevance differences;
55
+ * exact float scores need not match across backends (the same parity caveat as
56
+ * /vector). */
57
+ interface SearchStore {
58
+ /** Insert or replace a document by (collection, id). */
59
+ index<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, doc: SearchDocument<M>): void;
60
+ /** Insert or replace many documents in one collection. */
61
+ indexMany<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, docs: ReadonlyArray<SearchDocument<M>>): void;
62
+ /** Remove a document by id. Returns true if it existed. */
63
+ remove(collection: string, id: string): boolean;
64
+ /** bm25-ranked keyword search, highest score first. Supports an exact-match
65
+ * meta `filter`. An empty/whitespace query returns `[]`. */
66
+ search<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, query: string, opts?: SearchOptions): SearchResult<M>[];
67
+ }
68
+
69
+ export type { SearchDocument as S, SearchOptions as a, SearchResult as b, SearchStore as c, SearchFieldDocument as d, SearchTextDocument as e };
@@ -20,6 +20,17 @@ interface StoreFilter {
20
20
  /** Number of results to skip. */
21
21
  offset?: number;
22
22
  }
23
+ /** Optional collection capability for adapters that can push `field IN (...)`
24
+ * down to the backing store while preserving the normal StoreFilter semantics.
25
+ * Graph frontier traversal uses this when present and falls back to plain
26
+ * `list()` when absent. */
27
+ interface SyncStoreInQuery {
28
+ listWhereIn<T>(collection: string, field: string, values: readonly unknown[], filter?: StoreFilter): T[];
29
+ }
30
+ /** Async twin of SyncStoreInQuery for remote-capable stores. */
31
+ interface AsyncStoreInQuery {
32
+ listWhereIn<T>(collection: string, field: string, values: readonly unknown[], filter?: StoreFilter): Promise<T[]>;
33
+ }
23
34
  /**
24
35
  * A typed key-value + collection store. **Synchronous.**
25
36
  *
@@ -80,4 +91,4 @@ interface AsyncStore {
80
91
  count(collection: string, filter?: StoreFilter): Promise<number>;
81
92
  }
82
93
 
83
- export type { AsyncStore as A, StoreFilter as S, StoreMeta as a, SyncStore as b };
94
+ export type { AsyncStore as A, StoreFilter as S, AsyncStoreInQuery as a, StoreMeta as b, SyncStore as c, SyncStoreInQuery as d };
package/dist/vector.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { V as Vector, d as VectorStore, e as VectorStoreMeta, a as VectorDocument, b as VectorSearchOptions, c as VectorSearchResult } from './types-BqSZEMAB.js';
1
+ import { V as Vector, d as VectorStore, e as VectorStoreMeta, a as VectorDocument, b as VectorSearchOptions, c as VectorSearchResult, A as AsyncVectorStore } from './types-B0XrD10b.js';
2
+ export { m as matchesWhere } from './filter-B9hP-TKF.js';
2
3
 
3
4
  /** Cosine similarity in [-1, 1]. Exact. Shared by the in-memory backend and the
4
5
  * sqlite backend's search path. Returns 0 for length mismatch or a zero vector
@@ -32,10 +33,15 @@ declare class InMemoryVectorStore implements VectorStore {
32
33
  upsert<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, doc: VectorDocument<M>): void;
33
34
  upsertMany<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, docs: ReadonlyArray<VectorDocument<M>>): void;
34
35
  get<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, id: string): VectorDocument<M> | null;
36
+ has(collection: string, id: string): boolean;
35
37
  remove(collection: string, id: string): boolean;
36
38
  count(collection: string): number;
37
39
  search<M extends Record<string, unknown> = Record<string, unknown>>(collection: string, query: Vector, opts?: VectorSearchOptions): VectorSearchResult<M>[];
38
40
  private collectionFor;
39
41
  }
40
42
 
41
- export { InMemoryVectorStore, Vector, VectorDocument, VectorSearchOptions, VectorSearchResult, VectorStore, VectorStoreMeta, assertDimensions, bufferToVector, cosineSimilarity, isUsableVector, vectorToBuffer };
43
+ /** Lift a synchronous VectorStore to the {@link AsyncVectorStore} interface. The
44
+ * bridge only goes this direction — sync ⊂ async. */
45
+ declare function toAsyncVector(store: VectorStore): AsyncVectorStore;
46
+
47
+ export { AsyncVectorStore, InMemoryVectorStore, Vector, VectorDocument, VectorSearchOptions, VectorSearchResult, VectorStore, VectorStoreMeta, assertDimensions, bufferToVector, cosineSimilarity, isUsableVector, toAsyncVector, vectorToBuffer };
package/dist/vector.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
- InMemoryVectorStore
3
- } from "./chunk-EDVHBRXG.js";
2
+ InMemoryVectorStore,
3
+ toAsyncVector
4
+ } from "./chunk-OUY3D4RT.js";
4
5
  import {
5
6
  assertDimensions,
6
7
  bufferToVector,
@@ -8,11 +9,16 @@ import {
8
9
  isUsableVector,
9
10
  vectorToBuffer
10
11
  } from "./chunk-BXM3YDOC.js";
12
+ import {
13
+ matchesWhere
14
+ } from "./chunk-KPMRRYTL.js";
11
15
  export {
12
16
  InMemoryVectorStore,
13
17
  assertDimensions,
14
18
  bufferToVector,
15
19
  cosineSimilarity,
16
20
  isUsableVector,
21
+ matchesWhere,
22
+ toAsyncVector,
17
23
  vectorToBuffer
18
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirk/store",
3
- "version": "0.4.2",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "description": "Code-split storage ports + source adapters under one namespace. KV + collection store and vector similarity store as interface subpaths; the sqlite source-adapter implements both over one connection.",
6
6
  "license": "Apache-2.0",
@@ -25,6 +25,7 @@
25
25
  "homepage": "https://github.com/nightwork-dev/mirk/tree/main/packages/store#readme",
26
26
  "bugs": "https://github.com/nightwork-dev/mirk/issues",
27
27
  "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
28
29
  "exports": {
29
30
  ".": {
30
31
  "import": "./dist/index.js",
@@ -38,6 +39,18 @@
38
39
  "import": "./dist/vector.js",
39
40
  "types": "./dist/vector.d.ts"
40
41
  },
42
+ "./search": {
43
+ "import": "./dist/search.js",
44
+ "types": "./dist/search.d.ts"
45
+ },
46
+ "./graph": {
47
+ "import": "./dist/graph.js",
48
+ "types": "./dist/graph.d.ts"
49
+ },
50
+ "./sql": {
51
+ "import": "./dist/sql.js",
52
+ "types": "./dist/sql.d.ts"
53
+ },
41
54
  "./sqlite": {
42
55
  "import": "./dist/adapters/sqlite.js",
43
56
  "types": "./dist/adapters/sqlite.d.ts"
@@ -74,7 +87,6 @@
74
87
  "test": "vitest run",
75
88
  "test:watch": "vitest",
76
89
  "typecheck": "tsc --noEmit",
77
- "build": "rm -rf dist && tsup src/index.ts src/kv.ts src/vector.ts src/adapters/sqlite.ts --format esm --dts --external better-sqlite3 --external sqlite-vec"
78
- },
79
- "types": "./dist/index.d.ts"
90
+ "build": "rm -rf dist && tsup src/index.ts src/kv.ts src/vector.ts src/search.ts src/graph.ts src/sql.ts src/adapters/sqlite.ts --format esm --dts --external better-sqlite3 --external sqlite-vec"
91
+ }
80
92
  }