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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@x5e/gink

v0.20240923.1727135143

Published

an eventually consistent database

Downloads

621

Readme

Gink in General

Gink is a versioned, eventually consistent, multi-paradigm database management system. It takes a "protocol-first" approach, which facilitates multiple implementations that can share data. Additionally, some of the data structures available in Gink are designed to operate similarly to native JavaScript data structures, which removes the steep learning curve found in other backend solutions. For example, Gink has directory, sequence, and key set data structures, which behave similarly to Objects, Arrays, and Sets, respectively.

Take a look at the full docs here.

The typescript implementation can be used in one of three modes:

Installation

npm install @x5e/gink

If you'd prefer to import from a CDN:

<!-- Get the latest version -->
<script src="https://cdn.jsdelivr.net/npm/@x5e/gink/content_root/generated/packed.min.js"></script>

<!-- Get a specific version -->
<script src="https://cdn.jsdelivr.net/npm/@x5e/[email protected]
/content_root/generated/packed.min.js"></script>

<script>
    // Make sure to access the modules using gink.module if you go through the CDN.
    const store = new gink.IndexedDbStore('example');
</script>

Examples

To see examples for all data structures in the TypeScript implementation, check out our full docs.

Import and initialize database and database:

import { Database, IndexedDbStore, Directory } from "@x5e/gink";

const store = new IndexedDbStore('examples');
const instance = new Database(store);

All following examples will assume you have a store and instance.

Data Structures

Box

A Box is a very simple data structure that can hold only one value at a time; you can set or get its value.

Create the box:

const aBox: Box = await instance.createBox();

Set and get its value, and check the size

await aBox.set("example value");

// Get the value - this will return "example value"
const result = await aBox.get();

// Will always have a size of 0 or 1 (in this case, 1)
const size = await aBox.size();

Directory

The Directory aims to mimic the functionality of a TypeScript object. If you know how to use an Object, you should already know how to use the directory!

Create the directory:

const directory = await instance.createDirectory();

Setting {Key: Value} pairs and getting them:

await directory.set("key1", "value1");
await directory.set("foo", "bar");
const result = await directory.get("key1");

Get the directory as a JavaScript Map:

const asMap = await directory.toMap();

Storing sub-Directories:

const subdir = await instance.createDirectory();
await directory.set("new dir", subdir);

Sequence

A Sequence is the Gink version of a JavaScript Array. Sequences are specifically ordered by time of insertion, so they end up representing a queue quite well. Due to the fact they are ordered by insertion, Sequences do not support unshift like a JS Array.

Create a new Sequence:

const seq: Sequence = await instance.createSequence();

Pushing and popping

await seq.push("A");
await seq.push("B");
await seq.push("C");

// Deletes and returns "C"
const popped = await seq.pop();

// Deletes and returns "A"
const index_popped = await seq.pop(0);

Get the Gink Sequence as a JavaScript Array:

const as_array = await seq.toArray();

Getting and moving values:

await seq.push("B");
// Saving the muid of this transaction to use later
const cMuid = await seq.push("C");
await seq.push("D");

// Get the value at the end of the sequence
const atEnd = await seq.at(-1); // returns "D"

// first value, returns "B"
const beginning = await seq.at(0);

// Reordering
// Moves position 0 ("B") to the last position
await seq.move(0, -1);
// now looks like ["C", "D", "B"]

// Moving elements by their Muid
await seq.move(cMuid, 1);
// now looks like ["D", "C", "B"]

Get all entries in the sequence:

// returns an async iterator across everything in the list
// returns pairs of (Muid, Value)
const entries = await seq.entries();

All Containers

Most of these examples use a Directory for simplicity, but these operations can be performed on any container and have many applications.

Back in time

A parameter you may come across in many different functions of Gink is asOf. asOf can be used to look back to a specific time, or just look back to a specfic number of changes ago.

One easy way to interact with asOf is to save timestamps after certain operations.

const directory = instance.createDirectory();

// saving a timestamp before anything is added
const time0 = generateTimestamp();
await directory.set("foo", "bar");
// saving timestamp after key "foo" has been added.
const time1 = generateTimestamp();
await directory.set("A", "B");

Looking at the directory using the timestamps:

// at time0, the directory was empty.
// this will return Map{}
const emptyMap = directory.toMap(time0);

// at time1, the directory did not have the key "A"
// this will return false
let hasA = directory.has("A", time1);

Another way to look back in time is by using a "relative" timestamp. In this case, relative just means looking back a certain number of bundles ago. Think of the current state of the database as 0, so the previous bundle would be -1, etc.

// Since adding "A": "B" was the last bundle,
// this looks back before it, so it will return false.
let hasA = directory.has("A", -1);

// to visualize, the map at asOf=-1 would look like
// Map{"foo"=>"bar"} (using the directory above)
const fooMap = directory.toMap(-1);
Clear

All containers may be completely cleared out by using Container.clear(). By default, clearing out a container does not mean the data is gone, just that the container will now be empty. If the purge parameter is set to true, the data will be completely purged from the instance.

const directory = await instance.createDirectory();

await directory.set('A', 'B');

// save the muid from the clearance
// pass true to clear() to purge, defaults to false
const clearMuid = await directory.clear(false);

// will return false after clearance
const hasA = await directory.has("A");

// using the timestamp of the muid to look back before the clearance.
// returns true
const hasABeforeClear = await directory.has("A", clearMuid.timestamp)

Instance

Connecting to other instances

TODO