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

@donothing/kept

v2.3.0

Published

A toy object store built on a real database (sqlite3)

Downloads

7

Readme

888    d8P                 888    
888   d8P                  888    
888  d8P                   888    
888d88K     .d88b. 88888b. 888888 
8888888b   d8P  Y8b888 "88b888    
888  Y88b  88888888888  888888    
888   Y88b Y8b.    888 d88PY88b.  
888    Y88b "Y8888 88888P"  "Y888 
                   888            
                   888            
                   888

Kept: a database for puppies

Kept builds a toy object store on top of sqlite3.

You probably don't want to use this for your serious project. Here's why.

import { Store } from '@donothing/kept'

const store = Store('puppies.db')

// insert a new object, and get an id back that you
// can use to retrieve it
const id = await store.add({ name: 'Rover', breed: 'Alsatian' })

// get an object that has previously been stored
const rover = await store.get(id)

// update an existing object or create a new object at a specific ID
await store.put(id, { ...rover, weight: 540 })

// Atomically update an existing object. This is relatively slow and
// can fail in high-concurrency.
await store.update(id, (dog) => {
  return {
    ...dog,
    name: 'Fido'
  }
})

// delete a specific object from the store
await store.delete(id)

// get all the objects where a specific property has the given value
const alsatians = await store.findBy('breed', 'Alsatian')

// just gimme all the objects
const puppers = await store.all()

// we're done here
await store.close()

Complex queries

To do more complex queries, call .query(build) with a function build that takes a query builder and returns a querybuilder.

If you return the builder as-is, this is the equivalent of .all()

const doggos = await store.query(dogs => dogs)

Where clauses

You can filter down the results with .where(predicate) or the equivalent .and(predicate).

A predicate function is passed an object representing each record in the store and returns a value that represents a boolean.

const alsatians = await store.query(
  dogs => dogs
    .where(dog => dog.get('breed').eq('Alsatian'))
)

additional clauses can be added by chaining .where(...) or .and(...)

const doggos = await store.query(
  dogs => dogs
    .where(dog => dog.get('breed').eq('Alsatian'))
    .and(dog => dog.get('weight').eq(35))
)

Comparisons

on an expression, .eq( ) can be passed a string or number, or another expression and represents an equality comparison

value.eq('something')
value.eq(12)
value.eq(value)

You can also use .gt(...) or .lt(...) for "greater than" or "less than" comparisons.

These either take a number or a second expression

value.gt(4)
value.lt(2)
value.lt(value)

Boolean operations

Truth values can be combined in the normal ways using .and(...), .or(...) and .not().

// all objects with a weight less than 4
// OR a name starting wtih 'F'
dog.get('weight').lt(4)
  .or(dog.get('name').like('F%'))

// all objects where the name does NOT start
// with 'F'
dog.get('name').not.like('F%') // these two expressions are equivalent
dog.get('name').like('F%').not()

Values

You can get other values from an expression with .get(property: string) or .id()

// get the id for this record
(obj) => obj.id()

// gets the property 'foo' on obj
(obj) => obj.get('foo')

Any

The .any(...) method allows you to inspect each item of an array property.

// matches objects like { ingredients: ['Sugar', 'Flour', 'Eggs'] }
recipe =>
  recipe.get('ingredients').any(ingredient => ingredient.like('Sugar'))

Order by

orderBy uses a subset of the query DSL that returns TValues, the second argument must be either 'asc' or 'desc'.

// get all alsatians, from lightest to heaviest
const doggos = await store.query(
  dogs => dogs
    .where(dog => dog.get('breed').eq('Alsatian'))
    // the first parameter should be some value derived from the object
    // the second parameter should be 'asc' or 'desc'
    .orderBy(dog => dog.get('weight'), 'asc')
)

Limit and Offset

To get a partial result set, you can specify offset and limit

import { equal, prop } from '@donothing/kept'

const doggos = await store.query(
  dogs => dogs
    .where(dog => dog.get('breed').eq('Alsatian'))
    .orderBy(dog => dog.get('weight'), 'asc')
    .offset(3) // start at the 4th result
    .limit(5) // return up to 5 results
)