npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lix-js/sdk

v0.4.6

Published

> [!NOTE] > The readme is mirrored from [opral/lix-sdk](https://github.com/opral/lix-sdk). The source code is in the [opral/monorepo](https://github.com/opral/monorepo/tree/main/packages/lix-sdk).

Downloads

369,597

Readme

[!NOTE] The readme is mirrored from opral/lix-sdk. The source code is in the opral/monorepo.

[!NOTE] This repository serves as an issue tracker and documentation storage. The source code is in opral/monorepo.

Lix SDK

NPM Downloads Discord

Lix SDK

Introduction

Lix is a change control system that runs in the browser and an SDK to build web apps.

A change control system allows storing, tracking, querying, and reviewing changes in different file formats, e.g., .xlsx, .sqlite, or .inlang. Compared to a version control system, a change control system understands “what” changed in a file, e.g., cell C43 in the financials spreadsheet changed.

Lix is not a git replacement, nor is it designed for software engineering. The goal is to bring change control workflows to industries other than software engineering like health, finance, policy making, design, etc.

Try a demo lix app.

Features

  • 📌 Versioning: The possibility to create divergent states (branches in Git).
  • ⚡ CI/CD: Automations as we know them from software engineering.
  • 🔀 Change Proposals: (WIP #242) Similar workflow to pull requests in Git.
  • 🤝 Collaboration: Lix comes with built-in sync, enabling asynchronous (Git-like) and real-time collaboration (Google Docs-like) capabilities.
  • ✅ Validation Rules: (WIP #239) Define and enforce validation rules for your data.

Good to know

  • 🔍 Everything is SQL: Querying lix happens via SQL. No new query language to learn. The lix SDK conveniently exposes Kysely, a type-safe SQL query builder.
  • 🌐 Browser-based: Lix targets the browser as target platform. Node/unix dependencies are ruled out.

Getting Started

[!TIP] The documentation is a work in progress. If you have any questions, please open issues in the GitHub repository.

[!NOTE] The getting started uses a JSON file but you can store any file in lix, even a SQLite database, as long as a plugin for the file format is provided.

Installation

Install the Lix SDK package:

npm install @lix-js/sdk

Open a lix

[!NOTE] We plan to have locally installed plugins in the future with no need to provide them upfront, see #241.

Create and open a new Lix file:

import { newLixFile, openLixInMemory } from "@lix-js/sdk";
import { plugin as jsonPlugin } from "@lix-js/plugin-json";

// Create a new empty Lix file
const lixFile = await newLixFile();

// Open the Lix file in memory
const lix = await openLixInMemory({
	blob: lixFile,
	providePlugins: [jsonPlugin],
});

Insert files

Inserting an examplary JSON file into lix:

const json = {
	name: "Hello World",
	version: "1.0.0",
	settings: {
		enableFeatureX: true,
		maxUsers: 10,
	},
};

// Insert the file 
const file = await lix.db
	.insertInto("file")
	.values({
		path: "/example.json",
		data: new TextEncoder().encode(JSON.stringify(json)),
	})
	.returningAll()
	.executeTakeFirstOrThrow();

console.log("JSON file inserted with ID:", file.id);

Update Files

Let's update our JSON file with some changes:

{
	name: "Hello World",
-	version: "1.0.0",
+	version: "1.1.0",
	settings: {
		enableFeatureX: true,
-		maxUsers: 10,
+		maxUsers: 20,
	},
};
// updating the json from the previous example
json["version"] = "1.1.0";
json["settings"]["maxUsers"] = 20;

// Update the file
await lix.db
	.updateTable("file")
	.set({
		data: new TextEncoder().encode(JSON.stringify(updatedJson)),
	})
	.where("path", "=", "/example.json")
	.execute();

Lix detect changes in file updates via the file-queue and the provided plugin which detects changes.

Query Changes

Now we can query the changes that were made to the JSON file:

// Get all changes for this file
const changes = await lix.db
	.selectFrom("change")
	.where("file_id", "=", file.id)
	.innerJoin("snapshot", "snapshot.id", "change.snapshot_id")
	.execute();

console.log("Changes for the JSON file:", changes);

Create and switch a version

const versionB = await createVersion({ lix, name: "B" });

// Create a new version based on the parent version
await switchVersion({ lix, to: versionB });

console.log("New version created:", versionB.id);

Querying changes in a specific version

We'll update the JSON again by bumping the version to 1.2.0 with a new maxUsers count of 30:

{
	name: "Hello World",
-	version: "1.1.0",
+	version: "1.2.0",
	settings: {
		enableFeatureX: true,
-		maxUsers: 20,
+		maxUsers: 30,
	},
};

Querying changes in a specific version is simple by using the changeInVersion() filter:

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

const changes = await lix.db
	.selectFrom("change")
	.where("file_id", "=", file.id)
  .where(changeInVersion(versionB))
	.innerJoin("snapshot", "snapshot.id", "change.snapshot_id")
	.execute();

console.log(
  `Changes for the JSON file in version ${versionB.name}:`, changes
);

Querying a file

The file table is derived from the changes in the current version. Hence, querying the file after updating the json in the previous step will return the updated file:

const file = await lix.db
  .selectFrom("file")
  .where("path", "=", "/example.json")
  .selectAll()
  .executeTakeFirstOrThrow();

console.log(file)
{
	"name": "Hello World",
	"version": "1.2.0",
	"settings": {
		"enableFeatureX": true,
		"maxUsers": 30,
	},
}

Switch Back

Switch back to version A and you will see that the changes of version B are not present:

await switchVersion({ lix, to: versionA })

console.log("Switched to version: main");

// Get the file data in this version
const originalFile = lix.db
	.selectFrom("file")
	.where("path", "=", "/example.json")
	.selectAll()
	.executeTakeFirstOrThrow();

const originalContent = JSON.parse(originalFile.content);
console.log("Original content in main version:", originalContent);
{
	"name": "Hello World",
	"version": "1.1.0",
	"settings": {
		"enableFeatureX": true,
		"maxUsers": 20,
	},
}

Merge Changes

Merge changes from version B into version A:

await mergeVersion({lix, sourceVersion: versionB, targetVersion: versionA});

// Check the merged state
const file_after_merge = lix.db
	.selectFrom("file")
	.where("id", "=", file.id)
	.select("data")
	.executeTakeFirstOrThrow();

console.log("File state after merge:", JSON.parse(file_after_merge.data));
{
	"name": "Hello World",
	"version": "1.2.0",
	"settings": {
		"enableFeatureX": true,
		"maxUsers": 30,
	},
}

Plugins

Lix uses plugins to understand and track changes in different file formats. Documentation is work in progress. Find example plugins here:

Building apps

Example use cases

Apps that revolve around changes are prime use cases to be built on lix. Having an “edit -> review -> automate” workflow is a good indicator for an app that revolves around changes:

  • document editors (markdown, PDF, etc.)
  • accounting solutions (auditing)
  • content creation tools (Figma, Adobe Premiere)
  • spreadsheets (Excel, Google Sheets)
  • CAD software (Fusion 360, Autodesk)
  • data science (Jupyter Notebooks)
  • dashboards (Analytics, Infrastructure)

Advantages

Developing a web app with lix is reduced to providing a user interface that opens and saves a file.

Open a file, provide a UI, done

Backend features like auth, permissions, change control, and automations are solved on a file rather than an application-specific level. Lix knows who the actors are (auth), allows actors to conduct changes (permissions), is aware of how data changes over time (change history), can merge changes (collaboration), and uses the knowledge of changes to trigger automations (automation pipelines).

Backend features for files

In contrast, cloud-based apps are substantially more difficult to build because they require:

  • Auth (could be solved with a backend as a service)
  • Integrations (no interop between apps)
  • Ensure data privacy and security
  • Scaling complexity of storing all customer data
  • Replicating change control features like history, branching, etc.