1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
//! kglite — pure-Rust knowledge graph engine.
//!
//! Cypher pipeline, snapshot/working CoW transactions, columnar /
//! mmap / disk storage backends, and optional format loaders (RDF,
//! OKF). Pre-packaged domain dataset loaders live in the separate
//! kglite-datasets project. The Python wheel (`pip install kglite`)
//! is built by the sibling `kglite-py` crate; the Bolt and MCP
//! protocol servers are separate workspace binaries.
//!
//! ## Public API
//!
//! Downstream Rust consumers (the Python wheel, the C ABI, the
//! CLI, the bolt and mcp server binaries) should depend on the
//! curated [`api`] module — those items get semver guarantees.
//! Anything else is an implementation detail. Non-Rust bindings
//! (Java today) reach that same surface through the C ABI.
//!
//! See `docs/rust/embedding.md` for the embedder guide.
pub mod datatypes;
pub mod error;
// Engine internals — sealed behind the curated `api` facade.
// `pub(crate)` so no downstream crate can reach `kglite::graph::*` directly;
// the `api` re-exports below still resolve (re-exporting a `pub` item out of a
// `pub(crate)` module is legal). A CI grep (`scripts/check_api_chokepoint.sh`)
// keeps the wrapper crates honest.
pub(crate) mod graph;
pub mod graphgen;
#[cfg(feature = "okf")]
pub mod okf;
pub mod param;
pub(crate) mod serde_codec;
/// Curated stable Rust API. Downstream consumers should depend on
/// items here, not on the underlying module structure (which may
/// move between minor releases).
pub mod api {
// ── Root prelude ──────────────────────────────────────────────────────
// The root holds only the cross-cutting *data model* (the types every
// binding speaks) plus the standalone top-level capabilities; everything
// else is clustered into a submodule by concern. Each item lives in
// exactly one of them — no root↔submodule duplication.
pub use crate::datatypes::values::{NodeValue, PathValue, RelValue};
pub use crate::datatypes::Value;
pub use crate::error::{KgError, KgErrorCode};
pub use crate::graph::dir_graph::DirGraph;
/// The old→new node-index mapping `DirGraph::vacuum` returns.
pub use crate::graph::dir_graph::NodeRemap;
#[cfg(feature = "fastembed")]
pub use crate::graph::embedder::fastembed::FastEmbedAdapter;
pub use crate::graph::embedder::Embedder;
pub use crate::graph::explore::{explore_markdown, ExploreOptions};
/// Streaming synthetic-graph generator — `generate_to_dir(&config, dir)`
/// streams the benchmark/demo graph as CSVs + a manifest in bounded memory.
/// Surfaced through the wheel as `kglite.graphgen(...)`.
pub use crate::graphgen::{generate_to_dir as graphgen, GraphGenConfig, GraphGenStats};
/// The petgraph types this API's own signatures already speak.
///
/// `NodeIndex` and `EdgeIndex` are the slot handles every `GraphRead` /
/// `GraphWrite` call takes and returns; `Direction` is the in/out argument
/// on every adjacency call (`edges_directed`, `count_edges_filtered`,
/// `fluent::filter_by_connection`). Re-exported so a consumer need not add
/// its own `petgraph` dependency pinned to *the same major* the engine
/// links — a mismatch there is a type error at the call site, not a version
/// warning, so the coupling is the engine's to carry.
pub use petgraph::graph::{EdgeIndex, NodeIndex};
pub use petgraph::Direction;
// Thin pure-Rust graph handle for embedders + the free functions backing
// it. The wheel crate (`kglite-py`) defines its own, Python-flavored
// `KnowledgeGraph` separately — same name, different audience
// (`pip install kglite` users), polars-style.
pub use crate::graph::handle::{
discover_property_keys_excluding, discover_property_keys_from_data,
infer_selection_node_type, is_canonical_node_column, KnowledgeGraph,
CANONICAL_NODE_COLUMNS,
};
/// Core schema data types — the node and edge records (`NodeData` /
/// `EdgeData`), the projected `NodeInfo`, geo/temporal validity configs
/// (`SpatialConfig` / `TemporalConfig`), and the declarative
/// schema-definition + validation types. Generic across bindings.
/// `EdgeData` is included because `GraphWrite::add_edge` and
/// `DiskGraph::from_stable_digraph` name it in public signatures, so it
/// must be publicly nameable too.
pub use crate::graph::schema::{
parse_spatial_column_types_from_pairs, parse_temporal_column_types_from_pairs,
ConnectionSchemaDefinition, EdgeData, NodeData, NodeInfo, NodeSchemaDefinition,
SchemaDefinition, SchemaInstall, SpatialConfig, TemporalConfig, ValidationError,
};
/// The fluent **selection** data model — the cursor state threaded
/// through the fluent query chain (and through Selection-scoped
/// capabilities like `algorithms::vector_search`, `fluent`
/// set-ops/subgraph, and the spatial predicates). `CowSelection` is
/// the Arc copy-on-write wrapper a binding holds as its cursor;
/// `CurrentSelection` is the underlying level/plan state; `PlanStep`
/// is an `explain()` plan entry. Pure core types (petgraph node
/// indices and hash maps), no binding coupling. The operations that
/// consume them live in `api::fluent`.
pub use crate::graph::schema::{
CowSelection, CurrentSelection, PlanStep, SelectionLevel, SelectionOperation,
};
/// The single external schema **dialect** — the `{"nodes": {...},
/// "connections": {...}}` shape users write — and its parser. Every
/// binding's `define_schema` routes through here rather than hand-walking
/// its own dict: the Python wheel converts its dict to a [`Value`] and
/// calls `schema_from_value`, the C ABI's `kglite_define_schema` parses
/// JSON with `schema_from_json`. Keeping one grammar matters most for the
/// C ABI, where a published signature can never change within a major, so
/// a second dialect would be permanent. `SchemaParseErrorKind` lets a
/// binding raise its own conventional exception class.
pub use crate::graph::schema_json::{
schema_from_json, schema_from_value, SchemaParseError, SchemaParseErrorKind,
};
/// Arena guard for direct `GraphRead` traversals on disk-backed graphs.
/// Acquire via [`DirGraph::begin_read_pass`] and keep alive while
/// borrowed node/edge weights live; `None` on memory/mapped backends.
pub use crate::graph::storage::disk::graph::DiskQueryGuard;
/// Interned property-/type-key handle (`InternedKey`, a transparent
/// `u64` newtype) + the `StringInterner` that mints them.
/// `InternedKey::from_str(..)` computes the hash **without registering
/// the name** — safe for lookups and removals, but a key that reaches a
/// *write* unregistered reads back in-session and then breaks
/// enumeration and persistence (the name cannot be resolved). For
/// writes, use `DirGraph::set_node_property` (registers for you) or
/// register via `StringInterner::try_get_or_intern` first.
pub use crate::graph::storage::interner::{InternedKey, InternerCollision, StringInterner};
/// The canonical graph read trait — node/edge/property accessors
/// shared by every storage backend. Non-object-safe (GATs on the
/// iterator-returning methods), so consumers take `&impl GraphRead`,
/// never `&dyn`. Lifted for cross-binding read access.
pub use crate::graph::storage::GraphRead;
/// The canonical graph write trait (`GraphWrite: GraphRead`) —
/// storage-variant-routed mutation, including `set_node_property` and its
/// siblings. Non-object-safe like `GraphRead`: consumers take
/// `&mut impl GraphWrite`, never `&mut dyn`. Implemented by the storage
/// backends — reach it as `graph.graph.set_node_property(..)` on a
/// `DirGraph` (the `graph` field is public), the same call the Cypher
/// `SET` executor makes. Bridge string keys via
/// `StringInterner::try_get_or_intern` (`DirGraph::interner` is public).
pub use crate::graph::storage::GraphWrite;
/// The authoritative read handle for one node's properties.
///
/// A `&NodeData` is one *replica* of a columnar type's column store;
/// `NodeView` is the store the storage backend answers with, and its
/// enumeration methods are complete for every storage variant.
/// Obtain one from `GraphRead::node_view` / `DirGraph::node_view`; do not
/// hold it across a `Python::attach` boundary — resolve to owned values
/// first. See `crates/kglite/src/graph/storage/node_view.rs`.
pub use crate::graph::storage::NodeView;
/// The temporal query context (`At` / `During` / `Today` / `All`) — the
/// as-of filter a binding's cursor carries for temporal-validity
/// auto-filtering.
pub use crate::graph::TemporalContext;
// `Arc<DirGraph>` → `&mut DirGraph` + version bump.
pub use crate::graph::handle::make_dir_graph_mut;
/// Parameter-shape helpers for bindings — wire-shaped values
/// (JSON / protobuf-map / etc.) ↔ `kglite::api::Value`. The
/// canonical converters both ways, so no binding re-implements the
/// JSON dispatch: `json_value_to_kglite_value` (inbound params) and
/// `kglite_value_to_json` (outbound result cells, in natural
/// untagged JSON).
pub mod param {
pub use crate::param::{
json_object_to_value_map, json_value_to_kglite_value, kglite_value_to_json,
};
}
/// Bulk graph construction + maintenance. `add_edges_from_specs` is
/// the DataFrame-free edge-ingest path that non-Python bindings use
/// (the C ABI's `kglite_create_edges_batch` wraps it); the DataFrame-based
/// `add_nodes` / `add_connections` / `replace_connections` are the
/// Rust-side bulk-ingest path (`DataFrame` in, operation report out).
/// That `DataFrame` is kglite's own columnar container
/// (`crate::datatypes::values::DataFrame`, built on `Value`) — kglite
/// does not depend on polars. `update_node_properties`,
/// `purge_provisional_nodes`, and
/// `extend_graph` (merge one graph into another) round out the
/// generic, non-Selection mutation surface. `create_connections`
/// (edge-create between the two ends of a selection) is here too, since
/// `CurrentSelection` is itself an api type.
pub mod mutation {
/// Structured mutation reports — what a write touched (nodes/edges
/// created/updated/deleted, per operation). Returned by the mutation
/// functions above; every binding surfaces them after a mutating call.
pub use crate::graph::introspection::reporting::{
ConnectionOperationReport, NodeOperationReport, OperationReport, OperationReports,
};
pub use crate::graph::mutation::add_properties::{add_properties, PropertySpec};
pub use crate::graph::mutation::extend::{extend_graph, ExtendReport};
// `AddPropertiesReport` is deliberately not re-exported: it was not part
// of the public surface before this module was split out, and the API
// baseline pins that surface.
pub use crate::graph::mutation::maintain::{
add_connections, add_edges_from_specs, add_nodes, create_connections,
purge_provisional_nodes, replace_connections, update_node_properties, EdgeSpec,
EdgeSpecReport,
};
/// Validate a graph against a `SchemaDefinition`.
pub use crate::graph::mutation::validation::validate_graph;
}
/// Selection-scoped operations — selection set algebra
/// (`union`/`intersection`/`difference`/`symmetric_difference`),
/// subgraph extract / expand / stats, and the **shared selection-based
/// query-primitive layer** used by both Cypher and the fluent API. Each op
/// takes `(&DirGraph, &mut CurrentSelection, …already-marshalled params)`
/// and mutates the selection in place; a binding building a fluent surface
/// composes these directly (the wheel's `kg_fluent` / `kg_introspection`
/// PyO3 methods marshal Python args, then call straight into here). The
/// `core::*` primitives stay *defined* in `crate::graph::core`; this is
/// their curated, stable re-export surface.
pub mod fluent {
// Selection set algebra + subgraph.
pub use crate::graph::mutation::set_ops::{
difference_selections, intersection_selections, symmetric_difference_selections,
union_selections,
};
pub use crate::graph::mutation::subgraph::{
expand_selection, extract_subgraph, get_subgraph_stats, SubgraphStats,
};
// Filtering / sorting / pagination over a selection.
pub use crate::graph::core::filtering::{
filter_by_connection, filter_nodes, filter_nodes_any, filter_nodes_by_label,
filter_orphan_nodes, limit_nodes_per_group, offset_nodes, sort_nodes,
};
// Traversal (parent→child level expansion) + its config/filter types.
pub use crate::graph::core::traversal::{
format_for_dictionary, format_for_storage, get_children_properties,
make_comparison_traversal, make_traversal, MethodConfig, TemporalEdgeFilter,
};
// Per-level calculations / equation evaluation / counts.
pub use crate::graph::core::calculations::{
count_nodes_by_parent, count_nodes_in_level, process_equation, store_count_results,
EvaluationResult, StatResult,
};
// Node/connection/property retrieval from a selection + result types.
pub use crate::graph::core::data_retrieval::{
format_unique_values_for_storage, get_connections, get_node_degrees, get_nodes,
get_property_values, get_unique_values, LevelConnections, LevelNodes, LevelValues,
UniqueValues,
};
// Aggregate statistics over selected nodes.
pub use crate::graph::core::statistics::{
calculate_grouped_property_stats, calculate_property_stats, collect_selected_nodes,
get_parent_child_pairs, GroupedPropertyStats, PropertyStats,
};
// Pattern-match execution (shared with Cypher MATCH).
pub use crate::graph::core::pattern_matching::{
parse_pattern, MatchBinding, PatternExecutor, PatternMatch,
};
pub use crate::graph::core::value_operations::format_value_compact;
// Spatial predicates over a selection (geo filters / centroids /
// bounds).
pub use crate::graph::features::spatial::{
calculate_centroid, contains_point, get_bounds, intersects_geometry, near_point,
near_point_m, within_bounds, wkt_centroid,
};
// Temporal validity predicates (per NodeData + TemporalConfig).
pub use crate::graph::features::temporal::{
node_is_temporally_valid, node_overlaps_range, node_passes_context,
};
}
/// Embedding ingest + vector-index construction — how a binding gets
/// vectors *into* a graph. `set_embeddings` replaces a store,
/// `add_embeddings` upserts into one, `build_vector_index` builds the
/// HNSW index that accelerates whole-corpus top-k, `store_name` /
/// `store_key` are the one place the `"{text_column}_emb"` store name is
/// minted, and `resolve_source_column` is the one place a source column is
/// validated and resolved (identity aliases included) — a binding that
/// reads the column's text itself goes through it so the validating half
/// and the reading half cannot disagree. Each ingest
/// call validates every id and dimension before it touches a store and
/// bumps the graph version on a non-empty write, so it is all-or-nothing
/// under a plain `&mut DirGraph`.
///
/// Querying by vector needs no surface here: `vector_score` and
/// `text_score` both take a caller-supplied query vector through
/// `cypher_query`.
pub mod embeddings {
pub use crate::graph::embeddings::{
add_embeddings, build_vector_index, list_embeddings, resolve_source_column,
set_embeddings, store_key, store_name, EmbeddingIngestReport, EmbeddingStoreInfo,
VectorIndexReport,
};
}
/// Graph algorithms — pathfinding, components, centrality, community
/// detection. The typed, direct-call surface: each takes `&DirGraph` +
/// plain params and returns a result struct, for bindings that want
/// structs rather than result rows. (The same algorithms are reachable
/// per-query as Cypher procedures.) `vector_search` +
/// `VectorSearchResult` are here too — vector search is scoped to a
/// selection.
pub mod algorithms {
pub use crate::graph::algorithms::graph_algorithms::{
all_paths, are_connected, are_connected_with, betweenness_centrality,
closeness_centrality, connected_components, degree_centrality, get_node_info,
get_path_connections, label_propagation, leiden_communities, louvain_communities,
node_degree, pagerank, shortest_path, shortest_path_cost, shortest_path_cost_batch,
shortest_path_cost_batch_with, shortest_path_cost_weighted, shortest_path_cost_with,
shortest_path_costs_from, shortest_path_weighted, weakly_connected_components,
AllPathsOptions, CentralityOptions, CentralityResult, CommunityOptions,
CommunityResult, DegreeCentralityOptions, EdgeDir, LabelPropagationOptions,
PagerankOptions, PathNodeInfo, PathOptions, PathResult,
};
pub use crate::graph::algorithms::hnsw::HnswParams;
pub use crate::graph::algorithms::vector::{
vector_search, DistanceMetric, VectorSearchOptions, VectorSearchResult,
};
pub use crate::graph::algorithms::Interrupt;
}
/// Timeseries date/query helpers — the pure date-parsing and
/// range-finding utilities behind inline timeseries support.
/// `parse_date_query` maps a user string ("2013" / "2010..2015") to a
/// `NaiveDate` + `DatePrecision`; `TimeseriesConfig` / `NodeTimeseries`
/// are the config/data types.
pub mod timeseries {
pub use crate::graph::features::timeseries::{
date_from_ymd, expand_end, find_range, parse_date_query, validate_channel_length,
validate_keys_sorted, validate_resolution, DatePrecision, InlineTimeseriesConfig,
NodeTimeseries, TimeSpec, TimeseriesConfig,
};
}
/// Schema/graph introspection — the compute primitives behind
/// `describe()` / schema overview (connectivity, per-type stats,
/// neighbor schema) + the detail-level enums + a bug-report writer.
/// The typed schema-discovery surface every binding builds its
/// agent-facing schema from.
pub mod introspection {
pub use crate::graph::introspection::bug_report::write_bug_report;
/// Debug-string helpers (schema / selection dumps) for diagnostics.
pub use crate::graph::introspection::debugging;
pub use crate::graph::introspection::describe::{compute_description, mcp_quickstart};
pub use crate::graph::introspection::schema_overview::{
compute_connection_type_stats, compute_neighbors_schema, compute_property_stats,
compute_schema,
};
pub use crate::graph::introspection::{
compute_type_connectivity, derive_edge_counts_from_triples, schema_overview_to_json,
ConnectionDetail, ConnectionTypeStats, CypherDetail, FluentDetail, SchemaOverview,
EXACT_PROPERTY_STATS_MAX_NODES,
};
}
/// Graph I/O: `.kgl` load/save, format exporters (GraphML / GEXF /
/// D3-JSON / CSV), the N-Triples (RDF) streaming loader + progress
/// callbacks, embedding-vector file export/import, and streaming
/// disk subset export.
pub mod io {
pub use crate::graph::io::export::{
to_csv, to_csv_dir, to_d3_json, to_gexf, to_graphml, to_text,
};
/// Dependency-free relational exit: a deterministic SQLite-dialect SQL
/// script (`sqlite3 out.db < dump.sql`). Node types become tables,
/// connection types become link tables.
pub use crate::graph::io::export_sql::to_sqlite_dump;
/// Everything a `.kgl` write needs done to the graph before its bytes
/// exist: metadata stamp plus the column-consolidation pass whose row
/// order *is* the file's node binding. A binding that wants the bytes
/// rather than a file calls this and then `write_kgl_to`; `save_graph`
/// runs it internally.
pub use crate::graph::io::file::prepare_kgl_write;
/// Embedding-vector file export / import.
pub use crate::graph::io::file::{
export_embeddings_to_file, import_embeddings_from_file, EmbeddingExportFilter,
ImportStats,
};
/// `.kgl` load / save (the canonical persistence format). `save_graph`
/// and `save_graph_with` are the single save dispatch and report
/// `SaveError`, whose `Refused` variant is a save declined *before*
/// the path was touched — a write-ahead sidecar beside the target
/// holds commits this checkpoint would strand. Bindings map that to
/// their own class for a bad request, not to an I/O failure.
///
/// `materialize_disk_graph` is the convert-and-publish composite behind
/// `enable_disk_mode(path=...)`: it runs the same guard, converts the
/// graph to disk storage *inside* the destination, and publishes it, so
/// the live handle ends on the generation a fresh open would read.
pub use crate::graph::io::file::{
load_file, load_kgl_bytes, materialize_disk_graph, prepare_save, save_graph,
save_graph_with, write_kgl, write_kgl_to, write_kgl_with, SaveError,
};
pub use crate::graph::io::ntriples::{
load_ntriples, Cancelled, NTriplesConfig, ProgressEvent, ProgressSink, ProgressValue,
};
/// `open_or_create_graph` treats its mode as a *creation default* and
/// never touches an existing graph's own mode;
/// `open_or_create_graph_in_mode` treats it as the caller's explicit
/// request and converts (or refuses) on an existing graph too. A
/// binding that took the mode from a user wants the latter.
pub use crate::graph::io::open::{
open_or_create_graph, open_or_create_graph_in_mode, GraphFileIdentity,
GraphWriterLease, LeaseHolder, LeaseRefusal, OpenDisposition, OpenGraphResult,
};
/// General-purpose RDF loader (Turtle / N-Triples / N-Quads /
/// TriG). Gated behind the `rdf` Cargo feature.
#[cfg(feature = "rdf")]
pub use crate::graph::io::rdf::{load_rdf, RdfConfig, RdfStats};
/// Streaming disk subset export (bounded-memory subgraph save).
pub use crate::graph::mutation::subgraph_streaming::{
pass_a_scan, pass_a_scan_to_file, save_subset, save_subset_streaming_disk, RankIndex,
SubsetSpec,
};
/// The persisted-format version numbers this build reads and writes:
/// [`KGL_FORMAT_VERSION`] is the `.kgl` snapshot format stamped into new
/// saves, [`WAL_FORMAT_VERSION`] the write-ahead-log frame format, and
/// [`MIN_READABLE_WAL_FORMAT_VERSION`] the oldest WAL frame format this
/// build can replay. All three are distinct from the engine SemVer a
/// binding reads via the ABI version probe — they describe the on-disk
/// format lifecycle, not the library version. Exposed so a binding can
/// report the storage format it operates against.
pub use crate::graph::schema::KGL_FORMAT_VERSION;
pub use crate::graph::wal::{MIN_READABLE_WAL_FORMAT_VERSION, WAL_FORMAT_VERSION};
}
/// Storage backend configuration — the in-memory / mmap / disk backends
/// (`GraphBackend` + `DiskGraph` / `MappedGraph` constructors), the
/// per-type lookup, and the embedding store. CLAUDE.md designates
/// storage-backend configuration a direct-api concern.
pub mod storage {
pub use crate::graph::schema::EmbeddingStore;
pub use crate::graph::storage::backend::GraphBackend;
pub use crate::graph::storage::disk::graph::DiskGraph;
pub use crate::graph::storage::lookups::TypeLookup;
/// The cross-binding create-in-mode builder: resolve a mode string to
/// a [`StorageMode`] and build a fresh graph in that backend. Shared by
/// the wheel (`storage='mapped'/'disk'`), the bolt/mcp servers
/// (`--storage`), and the C ABI (`kglite_graph_new_in_mode`).
/// `live_storage_mode` answers "which mode is this graph actually in?"
/// — the classification every binding needs after an open — and
/// `convert_dir_graph_to_mode` is the explicit switch between the two
/// portable backends, refusing the disk directions structurally.
pub use crate::graph::storage::mode::{
convert_dir_graph_to_mode, live_storage_mode, new_dir_graph_in_mode, StorageMode,
};
pub use crate::graph::storage::MappedGraph;
}
/// Change data capture — the opt-in in-process change stream a binding
/// exposes through `db.cdc.*`, plus the commit-boundary drain any owner of
/// a bare `DirGraph` must call for its commits to be published (the same
/// obligation the durable paths carry for `flush_wal`). Cypher-first: a
/// binding needs none of this to *read* the stream, only to say where its
/// commit boundaries are.
pub mod cdc {
pub use crate::graph::cdc::{
disable, drain_at_commit, enable, needs_before_images, parse_selectors,
publish_drained, read, status, CdcChange, CdcEnrichment, CdcEvent, CdcEventKind,
CdcHandle, CdcHandoff, CdcLog, CdcSelector, CdcStatus, EdgeState, NodeState,
DEFAULT_CAPACITY, MAX_CAPACITY,
};
}
/// Durable transactions — the write-ahead log (append / recover / replay)
/// and the write-capture recording layer behind a binding's `durable()`
/// feature. The in-process WAL mechanism (distinct from the checkpoint
/// save in `io`).
pub mod durable {
/// Binding-agnostic durable-open + checkpoint orchestration: the
/// recover→replay→wrap→append ordering every owner of a log performs at
/// open (`open_log`, which also enforces the unconditional
/// recovery-on-open refusal), and the two halves of the four-step
/// checkpoint that bracket a binding's own save. `ensure_recovered` is
/// that same refusal for an opener that attaches no log at all, and is
/// already applied by `io::open_or_create_graph`.
pub use crate::graph::durability::{
checkpoint_epilogue, checkpoint_prologue, ensure_recovered, open_log, DurableOpenError,
};
pub use crate::graph::mutation::wal_replay::apply_frames;
pub use crate::graph::storage::recording::{
resolve_ops, wrap_for_durability, BeforeImage, CaptureOrigin, RawOp, RecordingGraph,
};
pub use crate::graph::wal::{recover, wal_path, DurabilityLevel, SyncMode, Wal, WalFrame};
}
/// Code-entity read surface — resolve / locate / contextualize entities
/// (`Type::method` helpers + source-location types) on any graph with
/// the code schema (Function/Class/… nodes carrying `file_path`/`line`).
/// Defined on the graph handle, independent of the builder: graphs built
/// by an external builder (codingest) get the same surface.
pub mod code_entities {
pub use crate::graph::handle::{
code_entity_context, find_code_entities, resolve_code_entity, source_location,
CodeContextLookup, CodeEntityContext, CodeEntityMatch, CODE_TYPES,
};
pub use crate::graph::{SourceLocation, SourceLookup};
}
/// Blueprint loader + builder — declarative graph construction
/// from a YAML/JSON spec + a directory of CSVs. The wheel's
/// `from_blueprint` and the C ABI's `kglite_blueprint_build` are both
/// thin wrappers around [`load_blueprint_file`] + [`build`].
pub mod blueprint {
pub use crate::graph::blueprint::build::{build, BuildReport, FlatSpec};
pub use crate::graph::blueprint::json_records::{from_records, RecordsReport};
pub use crate::graph::blueprint::schema::{
load_blueprint_file, AggregateEdge, Blueprint, CalendarLink, ComputeOp, Connections,
FkEdge, JunctionEdge, NodeSpec, Settings, TimeKey, TimeseriesSpec,
};
}
/// Cypher parser + planner + executor primitives. Downstream
/// consumers can build their own custom Cypher pipelines using
/// these items; for the canonical pipeline see [`session`].
pub mod cypher {
pub use crate::graph::languages::cypher::ast::{
CypherQuery, Expression, OutputFormat, ReturnItem,
};
/// Bind label / relationship-type positions written as parameters
/// (`MATCH (n:$label)`) before validation and planning. `session`
/// runs this for every statement it prepares; a binding that drives
/// the parse → optimize → execute steps itself must call it too, or
/// a parameterised label silently matches nothing.
pub use crate::graph::languages::cypher::dynamic_labels;
pub use crate::graph::languages::cypher::executor::write::execute_mutable;
pub use crate::graph::languages::cypher::executor::CypherExecutor;
pub use crate::graph::languages::cypher::generate_explain_result;
pub use crate::graph::languages::cypher::is_mutation_query;
pub use crate::graph::languages::cypher::parameter_names;
/// Parse a Cypher statement into a `CypherQuery`.
///
/// This must stay the **cached** parser
/// (`parse_cache::parse_cypher_cached`), the same one
/// `session::execute` uses: a repeated statement is a hash lookup plus
/// an AST clone rather than a full re-parse. Pointing it at the raw
/// `parser::parse_cypher` makes every binding that pre-parses to
/// classify a statement (the wheel does it on `cypher` /
/// `Session.cypher` / `Transaction.cypher` / `frozen`) pay a second
/// full parse per call — measured at 25% of a small parameterised
/// query.
pub use crate::graph::languages::cypher::parse_cypher;
pub use crate::graph::languages::cypher::parse_with_mutation_check;
pub use crate::graph::languages::cypher::planner;
pub use crate::graph::languages::cypher::planner::mark_lazy_eligibility;
pub use crate::graph::languages::cypher::planner::schema_check::validate_schema;
/// Where query-warning *echoes* go, process-wide. The structured
/// `QueryDiagnostics::warnings` channel is unconditional and
/// unaffected; this only moves the `warning:` line off stderr, for a
/// binding that presents warnings itself.
pub use crate::graph::languages::cypher::planner::schema_check::{
query_warning_sink, set_query_warning_sink, QueryWarningSink,
};
pub use crate::graph::languages::cypher::planner::simplification::rewrite_text_score;
pub use crate::graph::languages::cypher::query_features;
pub use crate::graph::languages::cypher::result::{
materialise_lazy, materialise_lazy_range, materialise_lazy_row, CypherResult,
LazyResultDescriptor,
};
/// Operator-declared value codecs — position-scoped, bidirectional
/// literal conversions (`'Q42'` ↔ `42`) bound to a property. Bindings
/// build a `Vec<ValueCodec>` (e.g. from a YAML manifest) and pass it via
/// `session::ExecuteOptions::value_codecs`. See `value_codec` module
/// docs for the safety model.
pub use crate::graph::languages::cypher::value_codec::{CodecKind, StoredType, ValueCodec};
pub use crate::graph::languages::cypher::QueryFeatures;
// Specific Cypher-pipeline items a binding implementing a native
// `cypher()` method (the wheel) reaches. Exposed INDIVIDUALLY — not as
// whole `ast`/`executor`/`parser`/`result` submodules — so the rest of
// the executor/parser internals stay un-exported and the optimizer can
// keep inlining the per-query hot path. (Re-exporting the whole
// executor module measurably regressed cypher micro-query latency by
// ~60% on tiny graphs.)
pub use crate::graph::languages::cypher::executor::helpers::{
resolve_edge_property, resolve_node_property,
};
pub use crate::graph::languages::cypher::optimize;
pub use crate::graph::languages::cypher::planner::schema_check::collect_unknown_pattern_warnings;
pub use crate::graph::languages::cypher::result::{
ClauseStats, EdgeBinding, MutationStats, QueryDiagnostics, ResultRow,
};
}
/// Canonical query + transaction surface — single source of
/// truth for the Cypher pipeline + snapshot/working CoW
/// transaction model. See `docs/rust/session.md`.
pub mod session {
/// `LOAD CSV` filesystem capability. Every binding decides what its
/// callers get; see `ExecuteOptions::csv_import`.
pub use crate::graph::languages::cypher::executor::load_csv::CsvImportPolicy;
pub use crate::graph::session::{
execute_mut, execute_read, resolve_noderefs, CommitOutcome, ExecuteOptions,
ExecuteOutcome, Session, Transaction, QUERY_THREAD_STACK_SIZE,
};
}
}