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

sostore

v0.1.3

Published

Synchronous reactive store and state

Downloads

4

Readme

sostore

Reactive, synchronizing, store and state manager.

How and why

The goal of this project is to create a unified state management system, that can either be used in front-end frameworks as a state or a store. It also should optionally be persistent and synchronizing across multiple clients.

Main Functionality

  1. To serve as a minimal database (store) on the client side
  2. To serve as a state manager for front-end frameworks
  3. Optionally persistent
  4. Optionally synchronizing to a remote database and other clients
  5. Reactive store and state (changes automatically reflected on the front-end framework components).

Main objectives:

  1. Ease of use with least amount of overhead
  2. Compatibility with
    • Multiple front-end frameworks
    • Multiple clients (browsers, react-native ...etc)
    • Multiple servers (serverless, CF workers ...etc)
  3. Fast and performant
  4. Lightweight

Installation

npm install sostore

Usage

Basic usage as a state manager

import { Component } from "react";
import { Observable, observe } from "sostore";

const state = new Observable({
	number: 0,
}).target;

@observe
class App extends Component {
	render() {
		return (
			<button onClick={() => state.number++}>clicked: {state.number}</button>
		);
	}
}

export default App;

The state can also live inside the component:

import { Component } from "react";
import { Observable, observe } from "sostore";

@observe
class App extends Component {
	// define state inside component
	st = new Observable({ number: 0 }).target;

	// you can also define a computed property
	get clickedBy10() {
		return this.st.number * 10;
	}

	render() {
		return (
			<button
				onClick={() => {
					this.st.number++;
				}}
			>
				clicked: {this.clickedBy10}
			</button>
		);
	}
}

click here for live example

Usage as store

import { Component } from "react";
import {
	observe,
	Document,
	Store,
	SubDocument,
	mapSubModel,
	IDB,
	CloudFlareApexoDB,
} from "sostore";

// define your models
class Child extends SubDocument {
	name: string = "";
	age: number = 10;
}

class Person extends Document {
	name: string = "";
	// subdocument model
    // and default value as an empty array
	children = mapSubModel(Child, [Child.new()]);
}

// create a store
// all parameters are optional
const myStore = new Store<Person>({
	// define the model to be used for your documents
	model: Person,
	// define encoding/decoding functions
    // to modify data before persistence
	encode: (input) => btoa(input),
	decode: (input) => atob(input),
	// debounce rate is a number in milliseconds
	// is the least amount of time between
    // any two persistence operations
	debounceRate: 500,
	// a callback to be executed
    // when sync has started/ended
	onSyncStart: () => alert("sync has started"),
	onSyncEnd: () => alert("sync has ended"),

	// local persistence layer
	// this example uses IndexedDB
	localPersistence: new IDB({
		name: "mydatabase",
	}),

	// remote persistence layer
	// this example uses a remote persistence layer
	// that has been designed
    // specifically for apexo.app
	remotePersistence: new CloudFlareApexoDB({
		endpoint: "http://myapp.com",
		name: "mydatabase",
		token: "mytoken",
	}),
});



// use your store
@observe
class App extends Component {
	render() {
		return (
			<div>
				<button onClick={() => myStore.add(Person.new())}>Add new child</button>
				{myStore.list.map((person) => (
					<div key={person.id}>
						<pre>{JSON.stringify(person, null, 4)}</pre>
					</div>
				))}
			</div>
		);
	}
}

To write your own persistence layer, please refer to: src/persistence/local.ts and src/persistence/remote.ts.

API: Properties of the store object:

  • .list: an array of all documents in the store except deleted documents.
  • .copy: an array of all documents in the store, including deleted documents, however, the array and its objects are not reactive (not observable/reactive).
  • .add: add document to the store.
  • .get: get document by id field.
  • .delete: delete document by given id.
  • .restoreItem: restore deleted item by given id.
  • .update: update item fields by given id.
  • .sync: synchronizes local with remote database.
  • .inSync: returns true if local is in sync with remote, false otherwise.
  • loaded: A promise that would resolve once the store has initially loaded from the local persistence layer (e.g. indexeddb).
  • isOnline: returns true if the remote persistence layer is accessible, false otherwise.
  • backup: returns a backup string that can be used in the restore method below.
  • restore: restores the store to a specific version defined by the input string (this affect the local and the remote persistence layer, if defined).

License: MIT