JavaScript API Reference

The JavaScript SDK exports openLix(), SqliteBackend, and FsBackend from @lix-js/sdk. openLix() returns a Lix instance: an in-process handle to one Lix repository.

import { openLix } from "@lix-js/sdk";

const lix = await openLix();

openLix()

const lix = await openLix(options?);

Options:

OptionTypeDescription
backendFsBackend | SqliteBackendOptional storage backend. Omit it for the default in-memory backend.

Use FsBackend for a filesystem workspace directory backed by RocksDB at <workspace>/.lix/.internal/rocksdb:

import { FsBackend, openLix } from "@lix-js/sdk";

const lix = await openLix({
	backend: new FsBackend({
		path: "./workspace",
		syncAllFiles: true,
	}),
});

Pass lixDir for filesystem sync with repository metadata in an external .lix directory. This does not write <workspace>/.lix:

const lix = await openLix({
	backend: new FsBackend({
		path: "./workspace",
		lixDir: "/tmp/session/.lix",
		syncAllFiles: true,
	}),
});

Set syncAllFiles: false to start filesystem sync with no regular workspace files, then import selected files with importFilesystemPaths(). Imported paths are exact workspace-relative file paths, not directories or globs. They may be written with or without a leading slash, for example "notes/today.md" or "/notes/today.md". This scopes disk import, file watching, and materialization; it does not filter unrelated Lix SQL state.

const lix = await openLix({
	backend: new FsBackend({
		path: "./workspace",
		syncAllFiles: false,
	}),
});
await lix.importFilesystemPaths(["notes/today.md"]);

Use SqliteBackend when a single .lix SQLite file is the application document itself, for example when defining a new file format and using Lix as the application file format:

import { openLix, SqliteBackend } from "@lix-js/sdk";

const lix = await openLix({
	backend: new SqliteBackend({ path: "app.lix" }),
});

Lix instance

execute()

const result = await lix.execute(sql, params?);

Executes one DataFusion SQL statement against the active Lix session.

Parameters:

ParameterTypeDescription
sqlstringOne SQL statement. Use DataFusion SQL, not SQLite SQL.
paramsReadonlyArray<LixRuntimeValue>Optional positional parameters addressed as $1, $2, and so on.

LixRuntimeValue accepts JSON values, Uint8Array, ArrayBuffer, or a Value.

Result:

type ExecuteResult = {
	columns: string[];
	rows: Row[];
	rowsAffected: number;
	notices: LixNotice[];
};
FieldDescription
columnsColumn names in result order. Empty for statements that do not return rows.
rowsResult rows. Each row exposes typed accessors by column name or index.
rowsAffectedNumber of rows affected by write statements.
noticesNon-fatal engine notices with { code, message, hint? }.

Example:

const result = await lix.execute(
	"SELECT path, data FROM lix_file WHERE path = $1",
	["/hello.txt"],
);

const path = result.rows[0]?.value("path").asText();
const data = result.rows[0]?.value("data").asBytes();

beginTransaction()

const tx = await lix.beginTransaction();

Starts a transaction. While it is open, execute statements on the transaction handle.

const tx = await lix.beginTransaction();
try {
	await tx.execute("INSERT INTO lix_file (path, data) VALUES (?, ?)", [
		"/hello.txt",
		new TextEncoder().encode("hello"),
	]);
	await tx.commit();
} catch (error) {
	await tx.rollback();
	throw error;
}

activeVersionId()

const versionId = await lix.activeVersionId();

Returns the id of the version the Lix handle is currently reading and writing.

createVersion()

const version = await lix.createVersion({
	name: "Explore",
});

Creates a version.

Options:

OptionTypeDescription
namestringVersion name.
idstringOptional explicit version id.
fromCommitIdstringOptional commit id to start from.

Result:

type CreateVersionResult = {
	id: string;
	name: string;
	hidden: boolean;
	commitId: string;
};

switchVersion()

await lix.switchVersion({ versionId });

Switches the Lix handle to another version. Plain SQL tables read and write the active version.

mergeVersionPreview()

const preview = await lix.mergeVersionPreview({
	sourceVersionId: draft.id,
});

Computes the merge result from sourceVersionId into the currently active target version without applying it.

Result:

type MergeVersionPreviewResult = {
	outcome: "alreadyUpToDate" | "fastForward" | "mergeCommitted";
	targetVersionId: string;
	sourceVersionId: string;
	baseCommitId: string;
	targetHeadCommitId: string;
	sourceHeadCommitId: string;
	changeStats: MergeChangeStats;
	conflicts: MergeConflict[];
};

mergeVersion()

const merge = await lix.mergeVersion({
	sourceVersionId: draft.id,
});

Merges sourceVersionId into the currently active target version.

Result:

type MergeVersionResult = {
	outcome: "alreadyUpToDate" | "fastForward" | "mergeCommitted";
	targetVersionId: string;
	sourceVersionId: string;
	baseCommitId: string;
	targetHeadBeforeCommitId: string;
	sourceHeadBeforeCommitId: string;
	targetHeadAfterCommitId: string;
	createdMergeCommitId: string | null;
	changeStats: MergeChangeStats;
};

MergeChangeStats:

type MergeChangeStats = {
	total: number;
	added: number;
	modified: number;
	removed: number;
};

MergeConflict:

type MergeConflict = {
	kind: "sameEntityChanged";
	schemaKey: string;
	entityPk: string[];
	fileId: string | null;
	target: MergeConflictSide;
	source: MergeConflictSide;
};

close()

await lix.close();

Closes the Lix handle and its backend resources.

Transaction

Transactions expose:

MethodDescription
execute(sql, params?)Execute SQL inside the transaction.
commit()Commit the transaction and close the transaction handle.
rollback()Roll back the transaction and close the transaction handle.

Row

Rows are returned by execute().

const row = result.rows[0]!;
SurfaceReturn typeDescription
row.columnsstring[]Column names for this row.
row.get(columnName)LixNativeValueNative JS value for a column. Throws if the column is missing.
row.tryGet(columnName)LixNativeValue | undefinedNative JS value, or undefined when the column is missing.
row.value(columnName)ValueTyped Value for a column. Throws if the column is missing.
row.tryValue(columnName)Value | undefinedTyped Value, or undefined when the column is missing.
row.getAt(index)LixNativeValueNative JS value by column index.
row.valueAt(index)ValueTyped Value by column index.
row.values()Value[]All typed values in column order.
row.toObject()Record<string, LixNativeValue>Object of native JS values keyed by column name.
row.toValueMap()Record<string, Value>Object of typed values keyed by column name.

LixNativeValue is null, boolean, number, string, JSON, or Uint8Array.

Value

Value preserves the SQL type returned by the engine.

Accessors:

MethodReturn typeDescription
asInteger()number | undefinedReturns a number for integer values.
asBoolean()boolean | undefinedReturns a boolean for boolean values.
asReal()number | undefinedReturns a number for real values.
asText()string | undefinedReturns a string for text values.
asJson()JsonValue | undefinedReturns a JSON value for JSON values.
asBytes()Uint8Array | undefinedReturns bytes for blob values.
toJSON()LixValueSerializes the typed value.

Constructors:

MethodDescription
Value.null()Create a SQL null value.
Value.integer(value)Create an integer value.
Value.boolean(value)Create a boolean value.
Value.real(value)Create a real number value.
Value.text(value)Create a text value.
Value.json(value)Create a JSON value.
Value.blob(value)Create a blob value from Uint8Array.
Value.from(raw)Convert a JS value, LixValue, Uint8Array, or ArrayBuffer into a Value.