Skip to content

Commit

Permalink
Add everything plus some docs
Browse files Browse the repository at this point in the history
  • Loading branch information
0x80 committed Jul 20, 2019
1 parent 658f028 commit accec4a
Show file tree
Hide file tree
Showing 12 changed files with 2,573 additions and 5 deletions.
24 changes: 24 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json" // required for rules that need type information
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
],
rules: {
"no-console": ["error", { allow: ["error", "log"] }],
"no-empty": "off",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/explicit-function-return-type": "off"
}
};
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*.log
node_modules/
dist/
build/
.env
.env.*
.next
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,63 @@
- [Firestore MobX](#Firestore-MobX)
- [Features](#Features)
- [Install](#Install)
- [Usage](#Usage)
- [Restrictions on Dynamic Data Sourcing](#Restrictions-on-Dynamic-Data-Sourcing)
- [Document](#Document)
- [Collection](#Collection)

# Firestore MobX

This library was inspired by Firestorter. Read the [migration docs](/docs/migration) if you are
interested in the motivation and differences.

You should be able to use this in any Javascript application including
React, React-Native and Node.js.

**DISCLAIMER** This library is still very new and based on my personal
experience using Firestorter. If there are any features that you miss and deem
essential, please let me know. It is well possible that I have overlooked some
use-cases.

## Features

- A flexible and un-opinionated API surface
- Written in Typescript with strict typings
- Minimal dependencies (only Firebase and MobX really)

## Install

`yarn add firestore-mobx` or `npm install firestore-mobx`

## Usage

## API
## Restrictions on Dynamic Data Sourcing

Observable documents and collections are flexible because they can change their
data source and query dynamically at any time. In order to reduce complexity and
offer strong typing some restrictions are enforced.

### Document

1. An observable document can change its ref after it was created, but the new
ref needs to be from the same collection. This is required because with
Typescript we get compile-time type checks based on what you pass into the
constructor. If the ref would be allowed to switch to a different collection,
this type would have no practical meaning. Also I have to yet encounter a
situation that requires this in a real-life application.

### Collection

### ObservableDocument
1. An observable collection always links to the Firestore collection passed into
the constructor. The query can be changed after the object was created,
influencing the number of documents in the collection, but it can not switch
to a different collection dynamically. The motivation for this is similar to
restriction 1 on observable documents.

### ObservableCollection
2. A collection without a query produces no documents. Retrieving all documents
from a collection is not typically something you would do in a client-side
application. By placing this restriction on collections it not only
simplifies the logic but we avoid fetching a large collection by accident. If
you have a relatively small collection and you do want to fetch all of it,
you can simply pass in a Firestore query that would include everything, for
example `.orderBy("updatedAt", "desc")`, `.limit(999)` or `.after("0")`
Empty file added docs/api.md
Empty file.
68 changes: 68 additions & 0 deletions docs/migrate-from-firestorter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Migrate from Firestorter

## Origin

This library was inspired by Firestorter. Huge thanks to @Ijzerenhein for that.

After finding myself using only a small portion of its API and missing strict
Typescript typings, I decided to create a leaner more focussed alternative based
on the same core idea.

By questioning every feature and only implementing the bare essentials I was
able to discard a lot of the complexity and code. To give you an idea,
firestore-mobx is implemented in less then one-third of the code; 362 vs 1267
lines.

## What was Removed / Changed

Below is a summary of the most important features from Firestorter that were
removed or implemented differently.

### Real-time update modes

The "manual" and "on" updates modes are gone. The only mode is "auto", removing
the need for active reference counting.

### Run-time schema checks

The optional Firestorter run-time schema type checks were removed in favor of
strong compile-time checks. These checks were made possible by placing some
[restrictions](/README.md#Restrictions-on-Dynamic-Data-Sourcing) on the way you
use collections and documents.

### Context and Initialization

There is no (global) context and initialization. You create documents and
collections by passing in a Firestore reference to the constructor. Those
references could be from different Firestore instances. Setting a source via
string paths is therefor not allowed.

### Observable Documents as part of Collections

In firestorter a collection class generates document class instances for each
document in the query snapshot. It needs to keep track of these instances and
this results in a lot of complexity and overhead.

In firestore-mobx the `collection.docs` property is an array of plain objects.
If you would like to pass on any of the collection items as an observable
document you can simply pass its data into the `ObservableDocument` constructor.
This will instantly give you a document without making an extra round-trip to
the database. I think this API gives maximum control and flexibility, because
you decide when you need this and there is no additional overhead.

### Reactive Paths

> Reactive paths are functions that depend on Documents (or other observables)
> and return a path. This makes it very easy to change the path of a Collection
> or Document, based on the path or even data of another Document.
I have needed them and doubt they are essential, but if you disagree please let
me know why.

### Reactive Query Functions

> When the Query Function accesses an observable, it will automatically be
> re-evaluated whenever that observable changes.
I have needed them and doubt they are essential, but if you disagree please let
me know why.
22 changes: 22 additions & 0 deletions docs/todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# TODO

## Must Have

- Figure out what to do with refs of sub-collections
- Limit document ref changes to same collection, otherwise T doesn't make any
sense anymore.
- Add tests

## Should Have

- Add global setOptions function

## Could Have

- Create a base class ObservableThing and use that as basis for Document and
Collection
- Figure out why using `this.isLoadingObservable;` (without `.get()`) breaks
updates in autorun function.
- Collection.add() is misleading maybe, because the added document might not
fall under the query and is therefor added to firestore but does not become
part of the observable collection.
27 changes: 25 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@
"version": "0.0.1-1",
"description": "Observable Firestore documents and collections using MobX",
"main": "dist/index.js",
"np": {
"contents": "dist"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 0"
"deploy": "np",
"test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc",
"build:watch": "tsc --watch",
"lint": "eslint 'src/**/*.{js,ts,tsx}' --quiet --fix",
"format": "prettier --write \"src/**/*.{ts,tsx,md,json,yml}\" \"*.{js,json,md,yml}\""
},
"repository": {
"type": "git",
Expand All @@ -15,5 +23,20 @@
"bugs": {
"url": "https://github.com/0x80/firestore-mobx/issues"
},
"homepage": "https://github.com/0x80/firestore-mobx#readme"
"homepage": "https://github.com/0x80/firestore-mobx#readme",
"dependencies": {
"firebase": "^6.3.0",
"mobx": "^5.11.0"
},
"devDependencies": {
"@firebase/firestore-types": "^1.4.2",
"@typescript-eslint/eslint-plugin": "^1.12.0",
"@typescript-eslint/parser": "^1.12.0",
"eslint": "^6.0.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-react": "^7.14.2",
"prettier": "^1.18.2",
"typescript": "^3.5.3"
}
}
Loading

0 comments on commit accec4a

Please sign in to comment.