-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f63aba9
Showing
15 changed files
with
11,415 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
node_modules/ | ||
dist/ | ||
.cache | ||
.rpt2_cache | ||
build/ | ||
coverage/ | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
## Mobx Firebase Database | ||
|
||
## The Problem | ||
|
||
While Firebase's Realtime Database enables you to build almost anything. Manipulating realtime data in your app can lead to quite difficult code to read. | ||
|
||
## This Solution | ||
|
||
Enter MobX. MobX is a powerful state management library that works with all front-end frameworks. | ||
|
||
mobx-firebase-database allows you to map your Firebase data to MobX observables and interact with it using MobX | ||
|
||
## Install | ||
|
||
```sh | ||
yarn add mobx-firebase-database | ||
# If you're using firebase web | ||
yarn add firebase | ||
# If you're using firebase-admin | ||
yarn add firebase-admin | ||
# If you're using react-native-firebase | ||
yarn add react-native-firebase | ||
``` | ||
|
||
## Peer Dependencies | ||
|
||
mobx-firebase-database works with : [`firebase`](https://www.npmjs.com/package/firebase), [`firebase-admin`](https://www.npmjs.com/package/firebase) and [`react-native-firebase`](https://www.npmjs.com/package/react-native-firebase) | ||
|
||
Depending on which one you're using you will need to have it installed. | ||
|
||
## Usage | ||
|
||
### Web | ||
|
||
Before starting to code, you need to get your Firebase Credentials : | ||
|
||
Follow the steps [here](https://firebase.google.com/docs/web/setup#add_firebase_to_your_app) to get your config. | ||
|
||
```typescript | ||
import getMobxFire from "mobx-firebase-database"; | ||
import firebase from "firebase/app"; | ||
import "firebase/database"; | ||
|
||
// Don't worry about calling it more than once. | ||
const { toBox, toArray, toMap, getFirebaseRef, destroy } = getMobxFire({ | ||
config, | ||
firebase | ||
}); | ||
|
||
// toBox | ||
const postId = `my_post_id`; | ||
const postRef = getFirebaseRef({ path: `posts/${postId}` }); | ||
const { value, unsub, update, set } = toBox(postRef); | ||
|
||
const post = value.get(); // always contains the latest value of posts/${postId} | ||
await update({ last_seen_at: firebase.database.ServerValue.TIMESTAMP }); | ||
value.get(); // {...post, last_seen_at: number} | ||
await set(null); | ||
value.get(); // null | ||
|
||
// toMap | ||
const postId = `my_post_id`; | ||
const postsRef = getFirebaseRef({ path: `posts`, orderByKeys: true }); | ||
const { value, unsub, update, set } = toMap(postRef); | ||
const allPostsIds = value.keys(); | ||
const post = value.get(`${postId}`); | ||
/* const posts = value.get(); // always contains the latest value of posts/${postId} | ||
await update({ last_seen_at: firebase.database.ServerValue.TIMESTAMP }); | ||
value.get(); // {...post, last_seen_at: number} | ||
await set(null); | ||
value.get(); // null */ | ||
``` | ||
|
||
## API | ||
|
||
### `observable.box` | ||
|
||
#### Input : | ||
|
||
getMobxFire requires as input an object with shape : | ||
|
||
- config: | ||
|
||
```typescript | ||
{ | ||
apiKey: string, | ||
authDomain: string, | ||
databaseURL: string, | ||
storageBucket: string | ||
} | ||
``` | ||
|
||
- firebase : Firebase web client from `firebase` package | ||
|
||
#### Output : | ||
|
||
Object with shape : | ||
|
||
```typescript | ||
type Output<T> = { | ||
value: IObservableValue<T>; | ||
unsub: () => void; | ||
update: (value: any) => Promise<void>; | ||
set: (value: any) => Promise<void>; | ||
}; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
{ | ||
"name": "mobx-firebase-database", | ||
"version": "0.1.0", | ||
"main": "dist/index.cjs.js", | ||
"module": "dist/index.esm.js", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
"start": "npm run test:i", | ||
"build": "rm -rf ./dist/ && rollup -c", | ||
"test:i": "jest --watch --coverage", | ||
"test": "jest --coverage", | ||
"prepublish": "npm run test && npm run build", | ||
"commit": "git-cz", | ||
"setup:semantic-release": "npx semantic-release-cli setup" | ||
}, | ||
"husky": { | ||
"pre-commit": "prettier src/* --write", | ||
"pre-push": "npm run test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/rakannimer/mobx-firebase-database" | ||
}, | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@types/jest": "^23.3.3", | ||
"comment-json": "^1.1.3", | ||
"firebase": "^5.5.3", | ||
"git-cz": "^1.7.1", | ||
"husky": "^1.1.1", | ||
"jest": "^23.6.0", | ||
"mobx": "^5.5.0", | ||
"parcel-bundler": "^1.10.1", | ||
"prettier": "^1.14.3", | ||
"rollup": "^0.66.4", | ||
"rollup-plugin-typescript2": "^0.17.1", | ||
"semantic-release": "^15.9.17", | ||
"ts-jest": "^23.10.3", | ||
"typescript": "^3.1.1" | ||
}, | ||
"jest": { | ||
"preset": "ts-jest", | ||
"collectCoverageFrom": [ | ||
"src/*.{ts,tsx}" | ||
], | ||
"testPathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/build/", | ||
"/dist/" | ||
] | ||
}, | ||
"files": [ | ||
"dist/" | ||
], | ||
"description": "Tame your firebase database with MobX", | ||
"dependencies": { | ||
"get-firebase-ref": "^1.1.1", | ||
"initialize-firebase-app": "^1.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import typescript from "rollup-plugin-typescript2"; | ||
|
||
export default { | ||
input: "src/index.ts", | ||
output: [ | ||
{ | ||
file: "dist/index.cjs.js", | ||
format: "cjs" | ||
}, | ||
{ | ||
file: "dist/index.umd.js", | ||
format: "umd", | ||
name: "TEMP_UMD_MODULE_NAME_CHANGE_ME" | ||
}, | ||
{ | ||
file: "dist/index.esm.js", | ||
format: "esm" | ||
} | ||
], | ||
plugins: [ | ||
typescript({ | ||
typescript: require("typescript"), | ||
abortOnError: false, | ||
tsconfigOverride: { | ||
compilerOptions: { | ||
module: "ES2015" | ||
} | ||
} | ||
}) | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import * as firebase from "firebase"; | ||
import { toJS } from "mobx"; | ||
import getMobxFire from "../"; | ||
import { config } from "../test-config"; | ||
|
||
describe("toArray", () => { | ||
const testPath = `mobx-fire/tests/${Date.now()}/`; | ||
const ARRAY_LENGTH = 2; | ||
const listAsObject = Array.from({ length: ARRAY_LENGTH }, (v, i) => { | ||
return { | ||
data: i | ||
}; | ||
}).reduce((acc, cur, i) => { | ||
return { | ||
...acc, | ||
[`id_${i}`]: cur | ||
}; | ||
}, {}) as any; | ||
const TIMEOUT = 20000; | ||
|
||
let { toArray, getFirebaseRef, destroy } = getMobxFire({ | ||
firebase, | ||
config: config.client | ||
}); | ||
afterAll(async () => { | ||
const ref = getFirebaseRef({ path: `${testPath}` }); | ||
await ref.set(null); | ||
destroy(); | ||
}); | ||
test("exists", () => { | ||
expect(toArray).toBeTruthy(); | ||
}); | ||
test("works", async () => { | ||
const ref = getFirebaseRef({ path: testPath }); | ||
const { value: array, unsub } = toArray(ref); | ||
await ref.set(listAsObject); | ||
expect(toJS(array)).toMatchInlineSnapshot(` | ||
Array [ | ||
Object { | ||
"key": "id_0", | ||
"value": Object { | ||
"data": 0, | ||
}, | ||
}, | ||
Object { | ||
"key": "id_1", | ||
"value": Object { | ||
"data": 1, | ||
}, | ||
}, | ||
] | ||
`); | ||
await ref.set(null); | ||
expect(toJS(array)).toMatchInlineSnapshot(`Array []`); | ||
unsub(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import * as firebase from "firebase"; | ||
import { config } from "../test-config"; | ||
import getMobxFire from "../"; | ||
import { waitUntilBox } from "../test-utils"; | ||
import { observable } from "mobx"; | ||
|
||
describe("toBox", () => { | ||
const testPath = `mobx-fire/tests/${Date.now()}/`; | ||
const firstValue = { | ||
val_1: { | ||
i_am_an: "object" | ||
} | ||
}; | ||
const firstKey = `1`; | ||
const TIMEOUT = 20000; | ||
const { toBox, getFirebaseRef } = getMobxFire({ | ||
firebase, | ||
config: config.client | ||
}); | ||
// initializeFirebaseApp({ firebase, ...config.client }); | ||
afterAll(async () => { | ||
const ref = getFirebaseRef({ path: `${testPath}` }); | ||
await ref.set(null); | ||
}); | ||
test("exists", () => { | ||
expect(toBox).toBeTruthy(); | ||
}); | ||
test("returns the right data", () => { | ||
let ref = getFirebaseRef({ path: `${testPath}/${firstKey}` }); | ||
const returnVal = toBox(ref); | ||
expect(returnVal.value.get).toBeTruthy(); | ||
expect(returnVal.value.set).toBeTruthy(); | ||
expect(returnVal.unsub).toBeInstanceOf(Function); | ||
expect(returnVal.update).toBeInstanceOf(Function); | ||
expect(returnVal.set).toBeInstanceOf(Function); | ||
}); | ||
|
||
test( | ||
"works with object", | ||
async () => { | ||
let ref = getFirebaseRef({ path: `${testPath}/${firstKey}` }); | ||
const { value: box, update } = toBox(ref); | ||
await Promise.all([ | ||
update(firstValue), | ||
waitUntilBox(box, ({ oldValue, newValue }) => { | ||
return oldValue !== newValue; | ||
}) | ||
]); | ||
expect(box.get()).toEqual(firstValue); | ||
}, | ||
TIMEOUT | ||
); | ||
test( | ||
"works with string", | ||
async () => { | ||
const STRING_VALUE = "string"; | ||
let ref = getFirebaseRef({ path: `${testPath}/str` }); | ||
const { value: box, set } = toBox(ref); | ||
if (box.get() !== null) { | ||
expect(box.get()).toEqual(STRING_VALUE); | ||
} | ||
await Promise.all([ | ||
set(STRING_VALUE), | ||
waitUntilBox(box, ({ oldValue, newValue }) => { | ||
// throw newValue; | ||
return oldValue !== newValue; | ||
}) | ||
]); | ||
expect(box.get()).toEqual(STRING_VALUE); | ||
}, | ||
TIMEOUT | ||
); | ||
test( | ||
"works with custom map", | ||
async () => { | ||
let ref = getFirebaseRef({ path: `${testPath}/asd` }); | ||
const { value: box, update } = toBox<{ a: any }>(ref, { | ||
map: value => { | ||
if (!value) return value; | ||
return value.a.toUpperCase(); | ||
} | ||
}); | ||
if (box.get() !== null) { | ||
expect(box.get()).toEqual({ a: "firstValue" }); | ||
return; | ||
} | ||
await Promise.all([ | ||
update({ a: "firstValue" }), | ||
waitUntilBox(box, ({ oldValue, newValue }) => { | ||
return oldValue !== newValue; | ||
}) | ||
]); | ||
expect(box.get()).toEqual("FIRSTVALUE"); | ||
}, | ||
TIMEOUT | ||
); | ||
}); |
Oops, something went wrong.