• This repository has been archived on 26/Oct/2022
  • Stars
    star
    227
  • Rank 170,530 (Top 4 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A beautifully-simple framework-agnostic modern state management library.

Store

A beautifully-simple framework-agnostic modern state management library.

Debug

Features

  • Simple: there's barely anything to learn and no boilerplate code required. Thanks to our usage of Proxys you just have to wrap your state with store, mutate it and retrieve values from it just like if it was a regular object, and listen to changes via onChange or useStore.
  • Framework-agnostic: Store doesn't make any assumptions about your UI framework of choice, in fact it can also be used without one.
  • React support: an hook for React is provided, because that's the UI framework I'm using. Support for other UI frameworks can be added easily, PRs are very welcome.
  • TypeScript-ready: Store is written in TypeScript and enables you to get a fully typed app with no extra effort.

Read more about how Store compares against other libraries in the FAQ section below.

Install

npm install --save store@npm:@fabiospampinato/store

Usage

Core

store

The first step is wrapping the objects containing the state of your app with the store function, this way Store will be able to transparently detect when mutations occur.

Example usage:

import {store} from 'store';

const CounterApp = {
  store: store ({ value: 0 }),
  increment: () => CounterApp.store.value += 1,
  decrement: () => CounterApp.store.value -= 1
};
  • ℹ️ The object passed to store can contain a variety of values:
  • ℹ️ store will wrap your object with a Proxy, which will detect mutations, and return a proxied object.
  • ℹ️ Never mutate the raw object passed to store directly, as those mutations won't be detected, always go through the proxied object returned by store instead. I'd suggest you to wrap your raw objects with store immediately so you won't even keep a reference to them.
  • ℹ️ In order to trigger a change simply mutate the proxied object returned by store as if it was a regular object.
  • ℹ️ Mutations happening at locations that need to be reached via a Symbol aren't detected (e.g. { [Symbol ()]: { undetected: true }).

isStore

This function checks if the passed value is a recognized Proxy object or not.

Example usage:

import {store, isStore} from 'store';

isStore ( store ( {} ) ); // => true
isStore ( {} ); // => false

isIdle

When no store is passed to it it checks if all known stores have no pending updates, i.e. some changes happened to them and at least one onChange listener has not been called yet.

If a store is passed it checks only if the passed store has no pending updates.

This is its interface:

function isIdle ( store?: Store ): boolean;

Example usage:

import {store, isIdle} from 'store';

const proxy1 = store ( {} );
const proxy2 = store ( {} );

isIdle (); // => true
isIdle ( proxy1 ); // => true
isIdle ( proxy2 ); // => true

proxy1.foo = true;

isIdle (); // => false
isIdle ( proxy1 ); // => false
isIdle ( proxy2 ); // => true

onChange

Next you'll probably want to listen for changes to your stores, the onChange function is how you do that in a framework-agnostic way.

This is its interface:

// Single store, without selector, listen to all changes to the store
function onChange ( store: Store, listener: ( data: Store ) => any ): Disposer;

// Multiple stores, without selector, listen to all changes to any store
function onChange ( stores: Store[], listener: ( ...data: Store[] ) => any ): Disposer;

// Single store, with selector, listen to only changes that cause the value returned by the selector to change
function onChange ( store: Store, selector: ( store: Store ) => Data, listener: ( data: Data ) => any ): Disposer;

// Single store, with selector, with comparator, listen to only changes that cause the value returned by the selector to change and the comparator to return true
function onChange ( store: Store, selector: ( store: Store ) => Data, comparator: ( dataPrev: Data, dataNext: Data ) => boolean, listener: ( data: Data ) => any ): Disposer;

// Multiple stores, with selector, listen to only changes that cause the value returned by the selector to change
function onChange ( stores: Store[], selector: ( ...stores: Store[] ) => Data, listener: ( data: Data ) => any ): Disposer;

// Multiple stores, with selector, with comparator, listen to only changes that cause the value returned by the selector to change and the comparator to return true
function onChange ( stores: Store[], selector: ( ...stores: Store[] ) => Data, comparator: ( dataPrev: Data, dataNext: Data ) => boolean, listener: ( data: Data ) => any ): Disposer;
  • The store/stores argument is either a single proxied object retuned by the store function or an array of those.
  • The listener argument is the function that will be called when a change to the provided stores occurs. It will be called with the value returned by the selector, if a selector was provided, or with all the provided stores as its arguments otherwise.
  • The selector optional argument is a function that computes some value that will be passed to the listener as its first argument. It's called with all the provided stores as its arguments.
  • The comparator optional argument is a function that checks for equality between the previous value returned by the selector and the current one.
  • The return value is a disposer, a function that when called will terminate this specific listening operation.

Example usage:

import areShallowEqual from 'are-shallow-equal';
import {store, onChange} from 'store';

const CounterApp = {
  store: store ({ value: 0 }),
  increment: () => CounterApp.store.value += 1,
  decrement: () => CounterApp.store.value -= 1
};

// No selector

const disposer1 = onChange ( CounterApp.store, store => {
  console.log ( 'Value changed, new value:', store.value );
  disposer1 (); // Preventing this listener to be called again
});

// With selector

const disposer2 = onChange ( CounterApp.store, store => store.value % 2 === 0, isEven => {
  console.log ( 'Is the new value even?', isEven );
});

// With selector, with comparator

const disposer = onChange ( CounterApp.store, store => ({ sqrt: Math.sqrt ( store.value ) }), areShallowEqual, ({ sqrt }) => {
  console.log ( 'The new square root is:', sqrt );
});

CounterApp.increment (); // This will cause a mutation, causing the listeners to be called
CounterApp.increment (); // This will cause another mutation, but the listeners will still be called once as these mutations are occurring in a single event loop tick

setTimeout ( CounterApp.increment, 100 ); // This will cause the remaining listener to be called again
  • ℹ️ Using a selector that retrieves only parts of the store will improve performance.
  • ℹ️ It's possible that the listener will be called even if the object returned by the selector, or the entire store, didn't actually change.
  • ℹ️ Calls to listeners are automatically coalesced and batched together for performance, so if you synchronously, i.e. within a single event loop tick, mutate a store multiple times and there's a listener listening for those changes that listener will only be called once.
  • ℹ️ Using a comparator can improve performance if your selector only selects a small part of a large object.
    • ℹ️ The comparator is not called if the library is certain that the value returned by the selector did or didn't change.
      • ℹ️ As a consequence of this the comparator is never called with primitive values.
    • ℹ️ When using a comparator the selector should return a new object, not one that might get mutated, or the comparator will effectively get called with the same objects.

batch

Synchronous mutations, i.e. mutations that happen within a single event loop tick, are batched and coalesced together automatically, if you sometimes also want to batch and coalesce mutations happening inside an asynchronous function or two arbitrary points in time you can use the batch function.

This is its interface:

function batch<P extends Promise<any>> ( fn: () => P ): P;

// Helper methods
batch.start = function (): void;
batch.stop = function (): void;

Example usage:

import {batch, store} from 'store';

const myStore = store ( { foo: 123 } );

// Function-based batching

batch ( async () => {
  myStore.foo = 0;
  await someAsyncFunction ();
  myStore.foo = 1;
});

// Manual batching

batch.start ();
for ( const nr of [1, 2, 3, 4, 5] ) {
  myStore.foo = nr;
  await someAsyncFunction ();
}
batch.stop ();
  • ℹ️ This function is critical for performance when performing a very large number of mutations in an asynchronous way.
  • ℹ️ When batching and coalescing asynchronous mutations by passing a function to batch everything is taken care of for you: if the passed function throws batching is stopped automatically, nested batch calls are not a problem either.
  • ℹ️ When batching and coalescing asynchronous mutations manually using batch.start and batch.stop you have to make sure that batch.stop is always called the same number of times that batch.start was called, or batching will never stop. So make sure that for instance thrown errors or early exits are not an issue.

target

This function unwraps a store and returns the raw plain object used under the hood.

This is its interface:

function target<T> ( store: T ): T;

Example usage:

import {store, target, isStore} from 'store';

const myStore = store ( { foo: 123 } );
const rawObject = target ( myStore );

isStore ( myStore ); // => true
isStore ( rawObject ); // => false

debug

debug provides a simple way to access your stores and see at a glance how and when they change from the DevTools.

Debug

This is its interface:

type Global = {
  stores: Store[], // Access all stores
  log: () => void // Log all stores
};

type Options = {
  collapsed: true, // Whether the logged groups should be collapsed
  logStoresNew: false, // Whether to log new store that have been created
  logChangesDiff: true, // Whether to log diffs (added, updated, removed) state changes
  logChangesFull: false // Whether to log the previous and current state in their entirity
};

function debug ( options?: Options ): Global;

Example usage:

import {debug} from 'store';

debug ();

Once called, debug defines a global object named STORE, which you can then access from the DevTools, and returns it.

Example usage:

STORE.stores[0].value += 1; // Manually triggering a mutation
STORE.log (); // Logging all stores to the console
  • ℹ️ It's important to call debug before creating any stores.
  • ℹ️ It's important to call debug only during development, as it may perform some potentially slow computations.

Hooks

Hooks provides a simple way to "hook" into Store's internal events.

Each hook has the following interface:

class Hook {
  subscribe ( listener: Function ): Disposer
}
  • subscribe registers a function for being called every time that hook is triggered.
    • The returned value is a disposer, a function that when called will terminate this specific subscription.

These are all the currently available hooks:

const Hooks = {
  store: {
    change: Hook, // Triggered whenever a store is mutated
    changeBatch: Hook, // Triggered whenever a store is mutated (batched)
    new: Hook // Triggered whenever a new store is created. This hook is used internally for implementing `debug`
  }
};

Example usage:

import {Hooks} from 'store';

const disposer = Hooks.store.new.subscribe ( store => {
  console.log ( 'New store:', store );
});

disposer ();

If you need some more hooks for your Store plugin let me know and I'll make sure to add them.

We currently don't have an official "Store DevTools Extension", but it would be super cool to have one. Perhaps it could provide a GUI for debug's functionalities, and/or implement other features like time-travel debugging. If you're interested in developing this please do get in touch! 😃

Extra/React

These extra features, intended to be used with React, are available from a dedicated subpackage.

useStore

useStore is a React hook for accessing a store's, or multiple stores's, values from within a functional component in a way that makes the component re-render whenever those values change.

This is its interface:

// Single store, without selector, re-render after any change to the store
function useStore ( store: Store ): Store;

// Multiple stores, without selector, re-render after any change to any store
function useStore ( stores: Store[] ): Store[];

// Single store, with selector, re-render only after changes that cause the value returned by the selector to change
function useStore ( store: Store, selector: ( store: Store ) => Data, dependencies: ReadonlyArray<any> = [] ): Data;

// Single store, with selector, with comparator, re-render only after changes that cause the value returned by the selector to change and the comparator to return true
function useStore ( store: Store, selector: ( store: Store ) => Data, comparator: ( dataPrev: Data, dataNext: Data ) => boolean, dependencies: ReadonlyArray<any> = [] ): Data;

// Multiple stores, with selector, re-render only after changes that cause the value returned by the selector to change
function useStore ( stores: Store[], selector: ( ...args: Store[] ) => Data, dependencies: ReadonlyArray<any> = [] ): Data;

// Multiple stores, with selector, with comparator, re-render only after changes that cause the value returned by the selector to change and the comparator to return true
function useStore ( stores: Store[], selector: ( ...args: Store[] ) => Data, comparator: ( dataPrev: Data, dataNext: Data ) => boolean, dependencies: ReadonlyArray<any> = [] ): Data;
  • The store/stores argument is either a single proxied object retuned by the store function or an array of those.
  • The selector optional argument if a function that computes some value that will be the return value of the hook. It's called with all the passed stores as its arguments.
  • The comparator optional argument is a function that checks for equality between the previous value returned by the selector and the current one.
  • The dependencies optional argument is an array of dependencies used to inform React about any objects your selector function will reference from outside of its innermost scope, ensuring the selector gets called again if any of those change.
  • The return value is whatever selector returns, if a selector was provided, or the entire store if only one store was provided, or the entire array of stores otherwise.

Example usage:

import areShallowEqual from 'are-shallow-equal';
import {store, onChange} from 'store';
import {useStore} from 'store/x/react';

const CounterApp = {
  store: store ({ value: 0 }),
  increment: () => CounterApp.store.value += 1,
  decrement: () => CounterApp.store.value -= 1
};

// No selector

const CounterComponent1 = () => {
  const {value} = useStore ( ConunterApp.store );
  return (
    <div>
      <div>{value}</div>
      <button onClick={CounterApp.increment}>Increment</button>
      <button onClick={CounterApp.decrement}>Decrement</button>
    </div>
  )
};

// With selector

const CounterComponent2 = () => {
  const isEven = useStore ( ConunterApp.store, store => store.value % 2 === 0 );
  return (
    <div>
      <div>Is the value even? {isEven}</div>
      <button onClick={CounterApp.increment}>Increment</button>
      <button onClick={CounterApp.decrement}>Decrement</button>
    </div>
  )
};

// With selector, with comparator

const CounterComponent3 = () => {
  const {sqrt} = useStore ( ConunterApp.store, store => ({ sqrt: Math.sqrt ( store.value ) }), areShallowEqual );
  return (
    <div>
      <div>The square root is: {sqrt}</div>
      <button onClick={CounterApp.increment}>Increment</button>
      <button onClick={CounterApp.decrement}>Decrement</button>
    </div>
  )
};
  • ℹ️ You basically just need to wrap the parts of your component that access any value from any store in a useStore hook, in order to make the component re-render whenever any of the retireved values change.
  • ℹ️ You don't need to use useStore for accessing methods that mutate the store, you can just reference them directly.
  • ℹ️ Using a selector that retrieves only parts of the store will improve performance.
  • ℹ️ It's possible that the component will be re-rendered even if the object returned by the selector, or the entire store, didn't actually change.
  • ℹ️ Re-renders are automatically coalesced and batched together for performance, so if synchronously, i.e. within a single event loop tick, the stores you're listening to are mutated multiple times the related components will only be re-rendered once.
  • ℹ️ Using a comparator can improve performance if your selector only selects a small part of a large object.
    • ℹ️ The comparator is not called if the library is certain that the value returned by the selector did or didn't change.
      • ℹ️ As a consequence of this the comparator is never called with primitive values.
    • ℹ️ When using a comparator the selector should return a new object, not one that might get mutated, or the comparator will effectively get called with the same objects.

useStores

useStores is just an alias for useStore, this alias is provided in case passing multiple stores to an hook called useStore doesn't feel quite right to you.

Example import:

import {useStores} from 'store/x/react';

FAQ

Why not using Redux, Unstated, Overstated, react-easy-state etc.?

I'll personally use this library over more popular ones for a few reasons:

  • Simpler APIs: almost all other state management libraries I've encountered have APIs that don't resonate with me, often they feel unnecessarily bloated. I don't want to write "actions", I don't want to write "reducers", I don't want to litter my code with decorators or unnecessary boilerplate.
  • Fewer footguns: many other libraries I've encountered have multiple footguns to be aware of, some which may cause hard-to-debug bugs. With Store you won't update your stores incorrectly once you have wrapped them with store, you won't have to specially handle asynchronicity, and you won't have to carefully update your stores in an immutable fashion.
  • Fewer restrictions: most other libraries require you to structure your stores in a specific way, update them with library-specific APIs, perhaps require the usage of classes, and/or are tied to a specific UI framework. Store is more flexible in this regard: your stores are just proxied objects, you can manipulate them however you like, adopt a more functional coding style if you prefer, and the library isn't tied to any specific UI framework, in fact you can use it to manage your purely server-side state too.
  • Easy type-safety: some libraries don't play very well with TypeScript and/or require you to manually write some types, Store just works with no extra effort.

Why not using Store?

You might not want to use Store if: the design choices I made don't resonate with you, you need something more battle-tested, you need to support some of the ~5% of the outdated browsers where Proxy isn't available, or you need the absolute maximum performance from your state management library since you know that will be your bottleneck, which is very unlikely.

License

MIT © Fabio Spampinato

More Repositories

1

cash

An absurdly small jQuery alternative for modern browsers.
JavaScript
6,410
star
2

cliflix

Watch anything instantaneously, just write its name.
TypeScript
1,492
star
3

vscode-todo-plus

Manage todo lists with ease. Powerful, easy to use and customizable.
TypeScript
843
star
4

autogit

Define commands, using plugins, to execute across all your repositories.
TypeScript
471
star
5

phoenix

My Phoenix setup. Powerful, easy to customize, tuned for web development, adds a space switcher.
JavaScript
397
star
6

bump

Bump updates the project's version, updates/creates the changelog, makes the bump commit, tags the bump commit and makes the release to GitHub. Opinionated but configurable.
TypeScript
393
star
7

noty

Autosaving sticky note with support for multiple notes without needing multiple windows.
TypeScript
337
star
8

tiny-bin

A library for building tiny and beautiful command line apps.
TypeScript
175
star
9

atomically

Write files atomically and reliably.
JavaScript
146
star
10

template

A super-simple way to create new projects based on templates.
TypeScript
131
star
11

flimsy

A single-file <1kb min+gzip simplified implementation of the reactive core of Solid, optimized for clean code.
TypeScript
130
star
12

vscode-highlight

Advanced text highlighter based on regexes. Useful for todos, annotations etc.
TypeScript
126
star
13

vscode-terminals

An extension for setting-up multiple terminals at once, or just running some commands.
TypeScript
110
star
14

shosho

A modern and powerful shortcuts management library.
TypeScript
87
star
15

picorpc

A tiny RPC library and spec, inspired by JSON-RPC 2.0 and tRPC.
TypeScript
84
star
16

overstated

React state management library that's delightful to use, without sacrificing performance or scalability.
TypeScript
82
star
17

vscode-monokai-night

A complete, dark and minimalistic Monokai-inspired theme.
HTML
74
star
18

vscode-open-in-github

Open the current project or file in github.com.
TypeScript
72
star
19

enex-dump

Dump the content of .enex files, preserving attachements, some metadata and optionally converting notes to Markdown.
JavaScript
71
star
20

shortcuts

Super performant and feature rich shortcuts management library.
TypeScript
66
star
21

watcher

The file system watcher that strives for perfection, with no native dependencies and optional rename detection support.
JavaScript
65
star
22

vscode-projects-plus

An extension for managing projects. Feature rich, customizable, automatically finds your projects.
TypeScript
64
star
23

svelto

Modular front end framework for modern browsers, with battery included: 100+ widgets and tools.
JavaScript
60
star
24

icon-font-buildr

Build custom icon fonts, it supports remote and local icons sources.
TypeScript
51
star
25

pastebin-monitor

A simple Pastebin monitor which looks for interesting things and saves them to disk.
Python
50
star
26

vscode-commands

Trigger arbitrary commands from the statusbar. Supports passing arguments!
TypeScript
50
star
27

monorepo

The homepage for all my repositories.
49
star
28

rssa

RSS-Anything, get updates about anything you can reach with an url. Like RSS, but for anything.
TypeScript
49
star
29

proxy-watcher

A library that recursively watches an object for mutations via Proxies and tells you which paths changed.
JavaScript
46
star
30

banal

On-demand bundle analyzer, powered by esbuild.
HTML
42
star
31

template-vscode-extension

A template for starting a new vscode extension quickly.
TypeScript
37
star
32

khroma

A collection of functions for manipulating CSS colors, inspired by SASS.
JavaScript
36
star
33

lande

A tiny neural network for natural language detection.
TypeScript
33
star
34

awesome-autogit

Curated list of resources for autogit.
27
star
35

vscode-projects-plus-todo-plus

Bird's-eye view over your projects, view all your todo files aggregated into one.
TypeScript
27
star
36

vscode-diff

Diff 2 opened files with ease. Because running `code --diff path1 path2` is too slow.
TypeScript
26
star
37

termux-env

My super-quick-to-setup Termux environment.
Lua
26
star
38

zeptomatch

An absurdly small glob matcher that packs a punch.
JavaScript
24
star
39

worktank

A simple isomorphic library for executing functions inside WebWorkers or Node Threads pools.
TypeScript
23
star
40

alfred-spaces-workflow

Alfred workflow that, used in conjunction with my Phoenix setup, gives you a spaces switcher.
23
star
41

vscode-markdown-todo

Manage todo lists inside markdown files with ease.
TypeScript
22
star
42

noren

A minimal HTTP server with good developer-experience and performance, for Node and beyond.
TypeScript
21
star
43

pollex

A tiny polling-based filesystem watcher that tries to be efficient.
TypeScript
21
star
44

vscode-debug-launcher

Start debugging, without having to define any tasks or launch configurations, even from the terminal.
TypeScript
20
star
45

gitman

A simple yet powerful opinionated tool for managing GitHub repositories.
TypeScript
19
star
46

tiny-sqlite3

A tiny cross-platform client for SQLite3, with precompiled binaries as the only third-party dependencies.
JavaScript
19
star
47

vscode-statusbar-debugger

Adds a debugger to the statusbar, less intrusive than the default floating one.
TypeScript
19
star
48

pacco

A bundler for modular and extensible web projects.
JavaScript
18
star
49

vscode-github-notifications-bell

A secure, customizable, statusbar bell that notifies you about notifications on github.
TypeScript
18
star
50

vscode-bump

Bump your project's version and update the changelog. Opinionated but configurable.
TypeScript
16
star
51

monex

Execute a script and restart it whenever it crashes or a watched file changes.
TypeScript
15
star
52

vscode-open-in-application

Open an arbitrary file in its default app, or the app you want.
TypeScript
15
star
53

tiny-encryptor

A tiny opinionated isomorphic library for encrypting and decrypting with ease.
JavaScript
14
star
54

awesome-template

Curated list of templates for Template.
14
star
55

jsonc-simple-parser

A simple JSON parser that supports comments and optional trailing commas.
JavaScript
14
star
56

secret

The simplest command to encrypt/decrypt a file, useful for committing encrypted ".env" files to version control, among other things.
TypeScript
14
star
57

dettle

A tiny fully-featured debounce and throttle implementation.
TypeScript
13
star
58

specialist

A library that helps you write tiny, fast, bundled and beautiful CLI apps that can automatically check for updates.
JavaScript
13
star
59

zstandard-wasm

A fast and small port of Zstandard to WASM. (Decompress-only for now).
C
13
star
60

is

The definitive collection of is* functions for runtime type checking. Lodash-compatible, tree-shakable, with types.
JavaScript
12
star
61

base256-encoding

Base256 encoding, the most memory-efficient encoding possible in JavaScript.
JavaScript
12
star
62

zeptoid

A tiny isomorphic fast function for generating a cryptographically random hex string.
TypeScript
11
star
63

vscode-browser-refresh

Refresh the browser with a ⌘R, right from Code. No need to switch focus to it.
TypeScript
10
star
64

tiny-levenshtein

A tiny implementation of the Levenshtein edit distance algorithm.
TypeScript
10
star
65

json-sorted-stringify

Alternative JSON.stringify function with sorted keys, so the output is stable.
JavaScript
10
star
66

huffy

A tiny compression library based on Huffman coding.
TypeScript
10
star
67

amuchina

A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.
TypeScript
10
star
68

scex

A simple runner for npm scripts that can execute multiple scripts, in serial or in parallel.
TypeScript
10
star
69

toygrad

A toy library for building simple neural networks which can be serialized to compact JSON.
TypeScript
10
star
70

vscode-optimize-images

Optimize one or all the images in your project using your favorite app.
TypeScript
9
star
71

crypto-puzzle

Basically a proof-of-work generator, this library makes cryptographic puzzles that are arbitrarily expensive to solve.
TypeScript
9
star
72

vscode-open-in-terminal

Adds a few commands for opening the current project in Terminal.
TypeScript
9
star
73

strid

Get a unique string identifier for any input value.
JavaScript
9
star
74

paketo

A tiny library for importing your package.json, with proper types!
TypeScript
9
star
75

grammex

A tiny PEG-like system for building language grammars with regexes.
JavaScript
9
star
76

tsex

A little CLI for making TypeScript packages, cleanly and effortlessly.
TypeScript
9
star
77

tiny-parse-argv

A tiny function for parsing process.argv, a modern rewrite of a sensible subset of minimist.
JavaScript
9
star
78

css-simple-minifier

A CSS minifier that's tiny and very fast.
JavaScript
8
star
79

vscode-open-multiple-files

Open all files in a folder at once, optionally filtering by a glob.
TypeScript
8
star
80

path-prop

Fast library for manipulating plain objects using paths.
JavaScript
8
star
81

react-router-static

A dead simple static router for React. Useful for multi-window Electron applications.
TypeScript
8
star
82

base128-encoding

Base128 encoding, the intersection of latin1 and utf-8, which is basically ASCII, the most memory-efficient string encoding that can be written to disk as utf-8 without ballooning in size.
TypeScript
8
star
83

noop-tag

A noop template literal tag, useful for syntax highlighting hints.
JavaScript
7
star
84

vscode-no-unsupported

An extension for removing [Unsupported] from the titlebar
TypeScript
7
star
85

tiny-webcrypto

A tiny isomorphic WebCrypto object, it just gives you the native one the current platform provides.
TypeScript
7
star
86

csv-simple-parser

A simple, fast and configurable CSV parser.
JavaScript
7
star
87

performance-interval

A precise implementation of setInterval that supports sub-millisecond intervals.
TypeScript
7
star
88

json-archive

Simple archive format based on JSON.
TypeScript
7
star
89

alfred-eject-workflow

Alfred workflow for ejecting mounted drives.
7
star
90

tiny-jsonc

An absurdly small JSONC parser.
JavaScript
7
star
91

chrome-window-session

Save each window as a separate session, automatically.
TypeScript
6
star
92

template-electron

A template for starting a new electron app quickly.
TypeScript
6
star
93

electron-about

Simple standalone about window for Electron.
TypeScript
6
star
94

bob-wasm

A port of Svgbob to WASM.
TypeScript
6
star
95

benchloop

Simple benchmarking library with a pretty output.
TypeScript
6
star
96

worktank-loader

WebPack plugin for WorkTank which enables you to execute whole files in a worker pool, transparently.
TypeScript
6
star
97

html-segmentator

A small library for splitting an HTML string into its top-level sections. Based on html5parser.
TypeScript
6
star
98

vscode-git-history

View or diff against previous versions of the current file.
TypeScript
6
star
99

uint8-concat

Concatenate mutiple Uint8Arrays super efficiently.
JavaScript
6
star
100

svelto-demo

Demo website used during the development of Svelto for testing all the available components.
JavaScript
6
star