• Stars
    star
    149
  • Rank 239,751 (Top 5 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

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

Repository Details

Storex Core - A modular and portable database abstraction ecosystem for JavaScript

Storex is a minimal storage layer as a foundation for easing common problems around storing and moving data around. Allowing you to describe your data layout as a graph and providing different plugins, it helps you interact with (No)SQL databases, data migration, offline first applications architecture, creating and consuming REST/GraphQL APIs, permission management, finding optimization opportunaties and more. The aim is to provide a minimalistic common ground/language for working with your data, providing packages for solving the most common problems around data, while giving you easy access to the underlying machinery to do the things that are specific to your application. Everything together that means that every problem you encounter while rapidly iterating towards a serious product, from choosing a suitable DB to suddenly realizing you need to migrate your data model, or even switch DBs, will get a ton easier because you don't have to solve them for the 109th time yourself.

This project started as the storage layer for Memex, a tool to organize your web-research for yourself and collaboratively. The design of this storage layer was done by Vincent den Boer and you can read about the original thoughts behind it here.

Status: This has been powering Memex in production for over 3 years, facilitating our experiments with peer-to-peer sync and our eventual transition to the cloud. It allows us to share a lot of infrastructure and business logic across the browser, our React Native app and our Firestore backend. However, we don't have the resources to properly launch this as a quality open source project with awesome docs and fixes for some of the design issues we discovered over the years. The recommended way to use it for now is to fork it and include it as submodules in your own project. It's easy to understand, so it's encouraged that you take the time to understand what's happening so you can modify it to fit your exact needs. With this in mind, the instructions below are outdated because we don't actively publish new versions to NPM. That being said, the API is stable and will be until Storex 1.0 in which we can finally fix a bunch of small things!

Installation

Storex is a collection of Node.js modules (written in TypeScript) meant to be used both client- and server-side. To start, you need the core and a backend:

$ npm install @worldbrain/storex --save

$ # For a client-side DB
$ npm install @worldbrain/storex-backend-dexie --save # IndexedDB through Dexie library

$ # For a server-side SQL DB
$ npm install @worldbrain/storex-backend-sequelize --save # MySQL, PostgreSQL, SQLite, MSSQL through Sequelize

$ # For a Firestore mBaaS DB
$ npm install @worldbrain/storex-backend-firestore --save

Basic usage

First, configure a StorageBackend and set up the StorageManager, which will be the main point of access to define, query and manipulate your data. For more in-depth information on how to do all of this, please refer to the docs.

import StorageManager from 'storex'
import { DexieStorageBackend } from 'storex-backend-dexie'

const storageBackend = new DexieStorageBackend({dbName: 'my-awesome-product'})
const storageManager = new StorageManager({ backend: storageBackend })
storageManager.registry.registerCollections({
    user: {
        version: new Date(2018, 11, 11),
        fields: {
            identifier: { type: 'string' },
            isActive: { type: 'boolean' },
        },
        indices: [
            { field: 'identifier' },
        ]
    },
    todoList: {
        version: new Date(2018, 7, 11),
        fields: {
            title: { type: 'string' },
        },
        relationships: [
            {childOf: 'user'} # creates one-to-many relationship
        ],
        indices: []
    },
    todoListEntry: {
        version: new Date(2018, 7, 11),
        fields: {
            content: {type: 'text'},
            done: {type: 'boolean'}
        },
        relationships: [
            {childOf: 'todoList', reverseAlias: 'entries'}
        ]
    }
})
await storageManager.finishInitialization()

const user = await storageManager.collection('user').createObject({
    identifier: 'email:[email protected]',
    isActive: true,
    todoLists: [{
        title: 'Procrastinate this as much as possible',
        entries: [
            {content: 'Write intro article', done: true},
            {content: 'Write docs', done: false},
            {content: 'Publish article', done: false},
        ]
    }]
})
# user now contains things generated by underlying backend, like ids and random keys if you have such fields
console.log(user.id)

await storageManager.collection('todoList').findObjects({user: user.id}) # You can also use MongoDB-like queries

Further documentation

You can find the docs here. Also, we'll be writing more and more automated tests which also serve as documentation.

Storex ecosystem

The power of Storex comes from having modular packages that can be recombined in different contexts based on the core 'language' or patterns Storex provides to talk about data. Officially supported packages will be included in the @worldbrain npm namespace. This helps us to endorse patterns that emerge throughout the ecosystem in a controlled, collectively governed way. These are the currently supported packages:

  • Storage modules: An pattern of organizing your storage logic modules so other parts of your application and tooling can have more meta-information about the application. This includes standard ways of defining your data structure and schema changes, describing how you access your data, describing higher-level methods, and describing access rules. This allows for really cool stuff like automatically detecting operations on fields that are not indexed, automatically generating client-server APIs for moving your data around, generating rules for other systems (like Firebase) to manage user rights, and a lot more.
  • Schema migrations: The functionality you need, provided in a modular and adaptable way, to describe and execute schema migration as your application evolves. Written with a diverse context in mind, like generating SQL scripts for DBAs, running migration in Serverless environments, converting exported data on import, etc.
  • Client-server communication usign GraphQL: This allows you to move your storage layer, expressed in storage modules, server-side transparently by using GraphQL as the transport layer with your back-end. You consume this API with the client so the business logic consuming your storage logic can stay exactly the same, making GraphQL an implementation detail, not something running throughout your code.
  • Data tools: A collection of data tools allowing you to apply schema migration on live data (coming in through the network or read from files), generate large sets of fake, complex data for testing purposes, and tools for dumping and loading test fixtures.
  • Schema visualization using Graphviz: Still in its infancy, this creates a GraphViz DOT files showing you the relationships between your collections.

Also, current officially supported back-ends are:

  • Dexie: Manages interaction with IndexedDB for you, so your application can run fully client-side. Use for your daily development workflow, for fully client-side applications, or offline-first applications.
  • Sequelize: Interact with any SQL database supported by Sequelize, such as MySQL or PostgreSQL. Meant to be used server-side.
  • Firestore: Store your data in Firestore, so you don't have to build a whole back-end yourself. Can be used directly from the client-side, or inside Cloud Functions. Includes a Security Rule generator that removes a lot of the pain of writing secure and maintainable security rules.

Status and future development

In addtion to the functionality described above, these are some features to highlight that are implemented and used in production:

  • One DB abstraction layer for client-side, server-side and mBaaS code: Use the Dexie backend for IndexedDB client-side applications, the Sequelize backend for server-side SQL-based databases, or the Firestore backend for mBaaS-based applications. This allows you to write storage-related business logic portable between front- and back-end, while easily switching to non-SQL storage back-ends later if you so desire, so you can flexible adjust your architecture as your application evolves.
  • Defining data in a DB-agnostic way as a graph of collections: By registering your data collections with the StorageManager, you can have an easily introspectable representation of your data model
  • Automatic creation of relationships in DB-agnostic way: One-to-one, one-to-many and many-to-many relationships declared in DB-agnostic ways are automatically being taken care of by the underlying StorageBackend on creation.
  • MongoDB-style querying: Basic CRUD operations take MongoDB-style queries, which will then be translated by the underlying StorageBackend.
  • Client-side full-text search using Dexie backend: By passing a stemmer into the Dexie storage backend, you can full-text search text fields using the fastest client-side full-text search engine yet!
  • Run automated storage-related tests in memory: Using the Dexie back-end, you can pass in a fake IndexedDB implementation to run your storage in-memory for faster automated and manual testing.
  • Version management of data models: For each collection, you can pass in an array of different date-versioned collection versions, and you'll be able to iterate over your data model versions through time.

The following items are on the roadmap in no particular order:

  • Synching functionality for offline-first and p2p applications (in development)
  • Relationship fetching & filtering: This would allow passing in an extra option to find(One)Object(s) signalling the back-end to also fetch relationship, which would translate to JOINs in SQL databases and use other configurable methods in other kinds of databases. Also, you could filter by relationships, like collection('user').findObjects({'email.active': true}).
  • Field types for handling user uploads: Allowing you to reference user uploads in your data-model, while choosing your own back-end to host them.
  • A caching layer: Allows you to cache certain explicitly-configured queries in stores like Memcache and Redis
  • Composite back-end writing to multiple back-ends at once: When you're switching databases or cloud providers, there may be period where your application needs to the exact same data to multiple database systems at once.
  • Assisting migrations from one database to another: Creating standard procedures allowing copying data from one database to another with any paradigm translations that might be needed.
  • Server-side full-text search server integration": Allow for example to store your data in MondoDB, but your full-text index in ElasticSearch.
  • Query analytics: Report query performance and production usage patterns to your anaylics backend to give you insight into possible optimization opportunities (such as what kind of indices to create.)

Also, Storex was built with decentralization in mind. The first available backends are Dexie allowing you to user data client side, Sequelize for storing data server-side in relational databases (MySQL, PostgreSQL, AWS Aurora), and Firestore for quickly buiding cloud-based MVPs that can be relatively easily be migrated to other solutions. In the future, we see it possible to create backends for decentralized systems like DAT to ease the transition and integration between centralized and decentralized back-ends as easy as possible.

Contributing

There are different ways you can contribute:

  • Report bugs: The most simple way. Scream at us :) If you can find the time though, we'd really appreciate it if you could attach a PR with a failing unit test.
  • Tackle outstanding bugs: Great way to dip your toes in the water. Some of the reported bugs may already have failing unit tests attached to them!
  • Propose new features: Open an issue to describe a new feature you'd like to see. Please take the time to explain your reasoning behind the request, how it would benefit the Storex ecosystem and things like use-cases if relevant.
  • Implement new features: We try our best to make extensive descriptions of how features should work, and a clear decision process if the features are yet to be designed. Features to be implemented can be found here with help how to pick up those features.

Building for development

Storex is written in Typescript. As such, there's a lot of type information serving as documentation for the reader of the code. To start writing code, do the following:

  1. Check out the Storex workspace repo: git clone --recursive [email protected]:WorldBrain/storex-workspace.git.
  2. Run yarn bootstrap inside the checked out repo.
  3. cd to any package you'd like to work on, like cd packages/@worldbrain/storex-backend-dexie
  4. Create your own feature branch if necessay: git checkout -b feature/my-awesome-feature
  5. Run yarn test:watch

More info on https://github.com/WorldBrain/storex-workspace

Getting in touch

For guidance on how to contribute, providing insight into your use cases, partnerships or any other collaboration opportunities, don't hesitate to get in touch here.

More Repositories

1

Memex

Browser extension to curate, annotate, and discuss the most valuable content and ideas on the web. As individuals, teams and communities.
TypeScript
4,283
star
2

Legacy-Research-Engine

WorldBrain's Chrome Extension to full-text search through your browser history & bookmarks.
JavaScript
279
star
3

storex-hub

Server application managing user data through Storex
TypeScript
55
star
4

Memex-Mobile

Mobile app for Memex
TypeScript
41
star
5

remove-stopwords

A simple repository to remove 'irrelevant for search' words, support for 51 languages
JavaScript
26
star
6

local-backup-server

Nodejs server for local backups of memex.
CSS
22
star
7

storex-sync

Sync & conflict resolution for peer-to-peer and offline-first applcations using Storex
TypeScript
17
star
8

storex-docs

Documentation website for Storex
TypeScript
17
star
9

Memex-Social

The web UI for the social part of Memex
TypeScript
9
star
10

firebase-backend

Firebase backend for Memex
TypeScript
6
star
11

memex-storage

Shared Storex storage definitions for Memex extension and mobile apps.
TypeScript
4
star
12

memex-url-utils

Shared URL processing utilities for Memex extension and mobile apps.
TypeScript
4
star
13

storex-backend-dexie

IndexedDB in-browser storage engine for Storex using Dexie
TypeScript
4
star
14

storex-hub-ipfs-textile

Textile integration for Storex Hub
TypeScript
3
star
15

storex-hub-integration-memex-arweave

Arweave integration with Memex through Storex Hub
TypeScript
3
star
16

storex-hub-demo-memex-gist-sharer

Demo app for Storex Hub that shares pages saved in Memex to a Gist
TypeScript
3
star
17

storex-backend-firestore

Firestore backend for Storex
TypeScript
3
star
18

analytics-backend

API Server for Custom Analytics
TypeScript
2
star
19

simple-signalling

Library for WebRTC signalling through different transports
TypeScript
2
star
20

storex-activitity-streams

Activity streams using Storex allowing users to follow things
TypeScript
2
star
21

Notifications

JavaScript
2
star
22

WorldBrain-Engineering

This repository hosts the website documenting all our engineering pratices.
2
star
23

storex-frontend-boilerplate

Boilerplate React application using Storex and Sync
TypeScript
2
star
24

storex-hub-boilerplate

Boilerplate for Storex Hub plugins and external apps
TypeScript
2
star
25

storex-data-tools

Storex tools for data generation, import/export and migration
TypeScript
2
star
26

storex-backend-sql

Storex SQL backend
TypeScript
1
star
27

storex-backend-sequelize

Sequelize SQL back-end for Storex
TypeScript
1
star
28

storex-visualize-graphviz

Storex schema visualization through Graphviz
TypeScript
1
star
29

portable-crypto

Simple encryption library that can encrypt data meant to be shared across multiple JS-based environments
TypeScript
1
star
30

storex-schema-migrations

Storex schema migrations
TypeScript
1
star
31

storex-pattern-modules

Interfaces and tools for laying out storage logic in modules building on Storex
TypeScript
1
star
32

storex-graphql-schema

Automatic GraphQL schema for Storex modules
TypeScript
1
star
33

Server

Analytics server for the WorldBrain Memex web extension
1
star
34

Website

All data related to our website
JavaScript
1
star
35

storex-workspace

Lerna workspace to work on all officially supported Storex packages together
Shell
1
star
36

memex-root-server

TypeScript
1
star