Boxops.Fjord.Client 0.6.2

dotnet add package Boxops.Fjord.Client --version 0.6.2
                    
NuGet\Install-Package Boxops.Fjord.Client -Version 0.6.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Boxops.Fjord.Client" Version="0.6.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Boxops.Fjord.Client" Version="0.6.2" />
                    
Directory.Packages.props
<PackageReference Include="Boxops.Fjord.Client" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Boxops.Fjord.Client --version 0.6.2
                    
#r "nuget: Boxops.Fjord.Client, 0.6.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Boxops.Fjord.Client@0.6.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Boxops.Fjord.Client&version=0.6.2
                    
Install as a Cake Addin
#tool nuget:?package=Boxops.Fjord.Client&version=0.6.2
                    
Install as a Cake Tool

Boxops.Fjord.Client

A .NET client for Fjord DB — an embedded, immutable fact database.

dotnet add package Boxops.Fjord.Client

No dependencies. net8.0 and net10.0.

A database is built once — schema, then facts — sealed, and thereafter only read. Facts are typed records identified by a FactId, grouped by predicate, and queried in sigla, a typed, Datalog-flavoured language.

What it is for

This is a second implementation of the wire protocol, sharing no constants, no enums and no code with the Rust one. That is deliberate: a client written against the same types can agree with the server by accident, and this one agrees only with the specification. It has already earned that twice — it found a block header length stated in one place and miscounted in another, and a fingerprint that would have depended on the client's byte order.

There is also a byte-for-byte golden test: this client's encoding of a fixed corpus is checked against the Rust encoder's, with the schema and the corpus stated independently on each side, because a shared statement would make the two agree by construction.

Writing facts

using Boxops.Fjord.Client;

// A predicate id is this client's own: what crosses the wire is the *name*, and a
// nested reference takes its predicate from the field's declared target. So a client
// may declare only the shapes it writes, in whatever order reads well.
const uint File = 0;
const uint Symbol = 1;

// The fingerprint is carried, never computed: `fjord schema fingerprint` prints it, and
// the number only says which schema these shapes were written against.
var schema = new FjordSchema(
    [
        new FjordPredicate("src.File", FjordType.String, null),
        new FjordPredicate("src.Symbol", FjordType.String, null),
        new FjordPredicate("codemarkup.SymbolXRef", FjordType.Rec(
            ("target", FjordType.Reference(Symbol)),
            ("file", FjordType.Reference(File)),
            ("span", FjordType.Rec(
                ("start", FjordType.Integer),
                ("length", FjordType.Integer)))), null),
    ],
    fingerprint: 0x2c8d1f4b9a7e3506);

using var connection = FjordConnection.Connect(
    FjordAddress.Parse("/tmp/fjord.sock//code"),
    schema,
    SessionMode.ReadWrite);

// Record fields are **positional**, in the order the schema declares them — that order
// is the physical key order, so it is the schema's to decide and not the caller's.
FjordFact FileFact(string path) => new(File, FjordValue.Of(path));

// A reference names its file and its symbol by nesting the whole fact. No id, and no
// bookkeeping.
FjordFact SymbolFact(string symbol) => new(Symbol, FjordValue.Of(symbol));

FjordFact XRefFact(string symbol, string path, long start, long length) =>
    new(2, FjordValue.Rec(
        FjordValue.Of(FjordRef.To(SymbolFact(symbol))),
        FjordValue.Of(FjordRef.To(FileFact(path))),
        FjordValue.Rec(FjordValue.Of(start), FjordValue.Of(length))));

var summary = connection.Write(
    2, [XRefFact("scip-python . store 1.0 codec/Codec#", "store/codec.py", 412, 5)]);

Console.WriteLine($"created {summary.Created}, deduped {summary.Deduped}");

A reference is the whole target fact, nested inline — not an id. So a producer keeps no map from its own entities to assigned identities, and needs no emission order: it emits what it holds where it stands, and the server interns each nested fact, creating it or finding what that key already names. Sending the same facts twice writes nothing, which is what makes retrying after a dropped connection safe.

The schema is yours to state

Nothing in the protocol describes the data model: the value codec sends no field names, no type markers and no record arities, because both ends already have them. So a client states the schema it uses and asserts it at the handshake by fingerprint — which turns "we disagree about the data model" from a corrupted database into a refused connection, before a byte of data flows.

You do not have to know how facts are stored. The storage codec is order-preserving, self-delimiting and frozen on disk; none of that is on the wire, and a client never sees it.

Status

0.4.0. No authentication — the transport is the trust boundary. See the repository for the full inventory of what is and is not built.

Licence

MIT.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.6.2 39 9/30/2026
0.6.1 48 9/28/2026
0.2.0 123 9/6/2026
0.1.0 115 8/21/2026