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

recliner-js

v1.0.3

Published

A mini couchdb in your browser

Downloads

10

Readme

Recliner-JS

A CouchDB like DB, which runs in your browser.
Access your saved attachments locally with REST API:

<img src=`/recliner/dbname/doc_id/attachment_name`>

"Buy Me A Coffee"

Features

  1. Uses same REST API like Couch DB.
  2. Implements CouchDB replicator protocol for seem less replication with backend.
  3. Can Lazy load Blobs(video media) from cloud.
  4. Partial content and stream supported.
  5. Uses IndexedDB as its backend DB and hence no storage restrictions.
  6. Mango like queries for searching and replication.
  7. Typescript based client to access REST API.

Build and integeration

With Vanila JS

  1. git clone the package.
  2. npm run jsbuild to create a rollup ES6 bundle dist/index.js
  3. In your service worker you can import Recliner this way import {Recliner} from '.path/to/recliner-js/index.js';

With Typescript

  1. Simple install it npm i recliner-js
  2. import it in your typescript as usual import {Recliner} from 'recliner-js';

Usage

In your service worker add this:

import {Recliner} from 'recliner-js';
const recliner = new Recliner();//create instance
self.addEventListener("fetch",(e)=>{
    const url_path = Recliner.getPathFromUrl(e.request);
    //mounts recliner
    if(url_path.startsWith("/recliner")){
        e.respondWith(recliner.process(e.request));
    }else{
        // do whatever else
    }
});

Now you can access docs and attachments saved in your recliner DB via URL

<img src=`/recliner/dbname/doc_id/attachment_name`>

CRUD with DB

There are two ways to interact with DB:

  1. Using regular fetch in your JS code using REST API similar to CouchDB*.
const getADoc = await fetch(`/recliner/dbname/docid`);
if(getADoc.status === 200){
    return await getADoc.json();//{_id,_rev,ok: true}
}

See complete list of Rest API

*Though many , but not all Couch REST API is supported. See Difference from CouchDB section.

  1. Use the a client instead: UsageDAO
import {UsageDAO} from 'recliner-js';
//Create
await UsageDAO.postADoc(dbname,{name:"person1",age:30});
//Retrieve
const doc = await UsageDAO.readADoc(dbname,docid);
//Update
await UsageDAO.updateADoc(dbname,doc._id,{name:"person1",age:34});
//Delete 
await UsageDAO.deleteADoc(dbname,doc._id);

//query
const findResult = await UsageDOA.findByPagination({
    dbanme,
    selector:{
        age:{$lt: 40},
        income: {$within:[10000,20000]},
        loc: {$isinpolygon:[]}//has some GIS capability
    }
});

//Save Attachments
await UsageDAO.addAttachmentsToDocID(dbname,doc._id,{
    "my_doc.pdf":DOC_BLOB,
    "my_video.webm":VIDEO_BLOB  
});

//Save attach wth a cloud URl.
//this way when such docs get replicated the Attachments are not sent. As they can be downloaded at end system using the cloud URL
await UsageDAO.addAnAttachmentToExistingDoc(dbname,doc,attachment_name,blob,new_edits,cloud_url,content_type);
//CRUD with attachments on DOC is available

//Replication: say fetch last 10 post
await UsageDAO.replicate({
    selector:{
        post_id
        type:"post",
        time:{$lt: now}
    },
    limit: 10,
    source:{
        url:"/recliner/my_db"
    },
    target:{
        url: "/proxy/couchdb/dbname",
        headers:{
            token:"some_token"
        }
    }
});

Partial content and Media streaming

Save the document with a cloud_url in a _attachments property.

await fetch("/recliner/dbname/docid",{
    method:"PUT",
    body:{
        _id:docid
        name:"person1",
        _attachments:{
            "my_video.webm":{
                cloud_url:"some_valid_cloud_url_which_supports_partial_content",
            }
        }
    }
});

Now this is can be streamed using:

<video src="/recliner/dbname/docid/my_video.webm">

The video player will automatically stream the video via recliner. Using the cloud_url, the docs will be partially downloaded and saved for offline use, and then streamed to video element. So next time when user stream the same video, its pulled out from the local cache.

However for all this to work, you need to configure recliner for what all mime type you want to support for streaming.

import {Recliner} from 'recliner-js';

const recliner = new Recliner(24,{
    "video/webm":1000_000,//1MB of partial content size for streaming
    "audio/mp3":1000_00//0.1MB of partial content size for streaming
});

When configured this way, then whenever an attachments of type webm and mp3 are requested, they are automatically streamed. If partial content of a doc is not present locally, than using the cloud_url its partial content is first pulled from cloud, saved in indexedDB and then streamed to the corresponding requesting GUI components like : video and audio tags. Next time same partial content will be streamed from local DB, instead of fetching it from cloud_url.

REST API supported

"/recliner/:db";
"/recliner/:db/_design/:ddoc";
"/recliner/:db/_find";
"/recliner/:db/_index";
"/recliner/_replicate";
"/recliner/:db/_changes";
"/recliner/:db/_bulk_get";
"/recliner/:db/_revs_diff";
"/recliner/:db/_local/:docid";
"/recliner/:db/:docid";
"/recliner/:db/:docid/:attachment";
"/recliner/:db/_db_design";
"/recliner/:db/_run_update_function";
"/recliner/_delete_recliner";

Gotchas

  1. For a multientry search the field name muts end with _m
  2. Supported query operators: $lt,$lte,$eq,$ne,$gte,$gt,$exists,$within,$nin,$regex,$in,$isinpolygon,$isnotinpolygon,$nwithin

Difference from CouchDB

  1. DB level design docs, saved via UsageDAO.putADBDesign, can be used to configure various function at DB level :
export interface DBDesignDoc{
    //name of the DB
    for_db:string;
    //before insertion docs are validated using this 
    doc_validation_function?:string;//this is stringified JS function
    
    //used for map reduce
    map_functions?: Record<string,string>;
    reduce_functions?:Record<string,string>;

    //can be used to mass modify docs using a selector
    update_functions?:Record<string,string>;

    /**
     * Used during remote to local replication using view query as source. [one can pass viewQueryUrl to replication info, to start view based replication]
     * This functions are used to filter view result before replicating them to local DB.
     */
    view_result_filter_functions?:Record<string,string>;
}
  1. Views are not supported, however Indexes, Map and Reduce is still supported using UsageDAO.postQueryToDBDesign<D>(dbname:string, query:MapReduceQuery).
  2. Design docs are not replicated by default when doing remote to local or local to remote replication. However for local to local replication design docs are copied. By local means database present in the browser. By remote means the one located and accessed via HTTPS on DB server(or via a proxy).
  3. _local attribute can be added on doc. They remain solely on local machine, and is removed when are replicated. So some values you wanted to keep in doc, but don;t want to send to server can be saved here. CouchDB Local Docs is supported, which are never replicated.

Though the most important API, to deal with docs and attachments and Database is implemented. And many which deemed insignificant where dropped.

Running the Demo

Type this commands in order

  1. npm run i install dev dependencies
  2. npm run build builds for typescript system
  3. npm run predemo adds ".js" extension to build for demo purpose.
  4. npm run demo : open http://localhost:8000/demo/index.html to view the demo

Version update

1.0.3

  1. Added redner_functions in DB design doc. Using which custom output, orher than json can be created for queries.
  2. Added UsageDAO.render method for get cutom rendered blob outputs
  3. Added GET method support for /recliner/:dbname/_find?q=${btoa(JSON.stringify(query))}, so the custom render can be created from URL too.

1.0.2

  1. Added PUT _single_tx_put so that insert of mutiple docs can be done in single transaction.

1.0.1

  1. Added support for rollup, so recliner can be used with vanilla JS. See Build and integeration section in the readme to see how to use in vanilla js.