πŸ‰ Reactive & asynchronous database for powerful React and React Native apps ⚑️

Last update: May 15, 2022

WatermelonDB

A reactive database framework

Build powerful React and React Native apps that scale from hundreds to tens of thousands of records and remain fast ⚑️

MIT License npm

WatermelonDB
⚑️ Launch your app instantly no matter how much data you have
πŸ“ˆ Highly scalable from hundreds to tens of thousands of records
😎 Lazy loaded. Only load data when you need it
πŸ”„ Offline-first. Sync with your own backend
πŸ“± Multiplatform. iOS, Android, web, and Node.js
βš›οΈ Works with React. Easily plug data into components
⏱ Fast. And getting faster with every release!
βœ… Proven. Powers Nozbe Teams since 2017 (and many others)
✨ Reactive. (Optional) RxJS API
πŸ”— Relational. Built on rock-solid SQLite foundation
⚠️ Static typing with Flow or TypeScript

Why Watermelon?

WatermelonDB is a new way of dealing with user data in React Native and React web apps.

It's optimized for building complex applications in React Native, and the number one goal is real-world performance. In simple words, your app must launch fast.

For simple apps, using Redux or MobX with a persistence adapter is the easiest way to go. But when you start scaling to thousands or tens of thousands of database records, your app will now be slow to launch (especially on slower Android devices). Loading a full database into JavaScript is expensive!

Watermelon fixes it by being lazy. Nothing is loaded until it's requested. And since all querying is performed directly on the rock-solid SQLite database on a separate native thread, most queries resolve in an instant.

But unlike using SQLite directly, Watermelon is fully observable. So whenever you change a record, all UI that depends on it will automatically re-render. For example, completing a task in a to-do app will re-render the task component, the list (to reorder), and all relevant task counters. Learn more.

React Native EU: Next-generation React Databases WatermelonDB Demo

πŸ“Ί Next-generation React databases
(a talk about WatermelonDB)

✨ Check out web Demo

Usage

Quick (over-simplified) example: an app with posts and comments.

First, you define Models:

class Post extends Model {
  @field('name') name
  @field('body') body
  @children('comments') comments
}

class Comment extends Model {
  @field('body') body
  @field('author') author
}

Then, you connect components to the data:

const Comment = ({ comment }) => (
  <View style={styles.commentBox}>
    <Text>{comment.body} β€” by {comment.author}</Text>
  </View>
)

// This is how you make your app reactive! ✨
const enhance = withObservables(['comment'], ({ comment }) => ({
  comment,
}))
const EnhancedComment = enhance(Comment)

And now you can render the whole Post:

const Post = ({ post, comments }) => (
  <View>
    <Text>{post.name}</Text>
    <Text>Comments:</Text>
    {comments.map(comment =>
      <EnhancedComment key={comment.id} comment={comment} />
    )}
  </View>
)

const enhance = withObservables(['post'], ({ post }) => ({
  post,
  comments: post.comments
}))

The result is fully reactive! Whenever a post or comment is added, changed, or removed, the right components will automatically re-render on screen. Doesn't matter if a change occurred in a totally different part of the app, it all just works out of the box!

➑️ Learn more: see full documentation

Who uses WatermelonDB

Nozbe Teams
CAPMO
Steady
Aerobotics
Smash Appz
Rocket Chat
HaloGo
SportsRecruits

Does your company or app use πŸ‰ ? Open a pull request and add your logo/icon with link here!

Contributing

We need you

WatermelonDB is an open-source project and it needs your help to thrive!

If there's a missing feature, a bug, or other improvement you'd like, we encourage you to contribute! Feel free to open an issue to get some guidance and see Contributing guide for details about project setup, testing, etc.

If you're just getting started, see good first issues that are easy to contribute to. If you make a non-trivial contribution, email me, and I'll send you a nice πŸ‰ sticker!

If you make or are considering making an app using WatermelonDB, please let us know!

Author and license

WatermelonDB was created by @Nozbe. Main author and maintainer is Radek Pietruszewski.

Contributors: @mobily, @kokusGr, @rozPierog, @rkrajewski, @domeknn, @Tereszkiewicz and more.

WatermelonDB is available under the MIT license. See the LICENSE file for more info.

GitHub

https://github.com/Nozbe/WatermelonDB
Comments
  • 1. Override entity IDs

    Hey,

    we are currently evaluating this for our app. Since we try to implement our own sync engine on top, I'd be curious if it's possible to specify entity IDs whenever you create one.

    Right now, if I try to set an ID in the builder function, I get the following error:

    Diagnostic error: Attempt to set new value on a property Model.prototype.id marked as @readonly

    Great work by the way, this looks very promising!

    Reviewed by sebastian-schlecht at 2018-09-06 16:59
  • 2. Initial Sync Download

    I see in the docs the Sync API function pullChanges uses a fetch request to get the change in records

    My question is how does this fetch request handle large amounts of data, for example if an existing users, gets a new device and has to download 500,000+ records linked to their profile? Is there a way of initialising the watermelon db from the remote DB and guarantee all the data is there?

    Reviewed by PatrickLambert1101 at 2020-03-18 08:00
  • 3. Adds rawQuery functionality

    Adds rawQuery functionaility, but needs Flow coverage.

    Usage:

    const tableNameCollection = database.collections.get('table_name')
    tableNameCollection.unsafeFetchRecordsWithSQL('select * from ...')
    
    database.adapter.unsafeSqlQuery('select * from ...', 'table_name')
    

    Issue: #103

    Reviewed by zobeirhamid at 2019-01-09 11:56
  • 4. Database failed to load error

    After some time spent to set up this package in react native, got this error:

    [DB] Uh-oh. Database failed to load, we're in big trouble, [TypeError: undefined is not an object (evaluating 'Native.setUp')]

    I am using expo for development.

    Reviewed by theixbass at 2018-09-18 08:43
  • 5. Request for TypeScript support

    This project looks fantastic and it would be great to get TypeScript support as well. TypeScript has quite a big community but with this being quite a new project there doesn't appear to be a community definition yet. I'd be happy to have a crack at helping with this, but I have not written an index.d.ts definition before. Microsoft have a guide over at https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html.

    Reviewed by c-kirkeby at 2018-09-14 08:38
  • 6. Batch Seeding Performance

    I'm currently running into issues while trying to use batch to seed my database. I have collections of around 50K records, which caused me to run into memory issues I assume are mentioned in #308.

    Since I'm using batch and not sync I added my own limit of around 1000 to get around the memory issue. This however has lead to very slow initial seeding performance (taking minutes to populate fully).

    #403 mentions using the new flag to achieve the 5K batch size, but I'm not sure if they've run into the slow seeding performance or not.

    Anybody had to deal with this case, or the general case of populating watermelon with many records?

    Reviewed by bzvikler at 2019-07-08 20:06
  • 7. NodeJS client

    Fix #721

    note: I wanted to have the js files in the ./native folder, but as it is out of the ./src folder, I decided to change.

    pending tests, suggestions welcome cc @radex

    Reviewed by sidferreira at 2020-06-17 14:36
  • 8. [Bug][iOS] 'jsi/jsi.h' file not found

    Hi!

    After update from 0.16.0 to 0.16.1 I get this error:

    In file included from /node_modules/@nozbe/watermelondb/native/ios/WatermelonDB/JSLockPerfHack.mm:1:
    
    /node_modules/@nozbe/watermelondb/native/ios/WatermelonDB/JSLockPerfHack.h:3:10: fatal error: 'jsi/jsi.h' file not found
    #include <jsi/jsi.h>
             ^~~~~~~~~~~
    1 error generated.
    
    Screenshot 2020-05-19 at 13 03 05
    Reviewed by kesha-antonov at 2020-05-19 10:05
  • 9. An in-range update of eslint-plugin-jest is breaking the build 🚨

    The devDependency eslint-plugin-jest was updated from 22.9.0 to 22.10.0.

    🚨 View failing branch.

    This version is covered by your current version range and after updating it in your project the build failed.

    eslint-plugin-jest is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

    Status Details

    Release Notes for v22.10.0

    22.10.0 (2019-07-17)

    Features

    Commits

    The new version differs by 7 commits.

    • 28bd1dc feat(rules): adds no-if rule (#293)
    • 7ebdc0e chore: enforce import destructure order
    • 31c7cef chore: convert to import/export (#302)
    • 9f858cb chore: delete tests instead of ignoring them with babel
    • c595ba0 chore: do not include tests in published tarball
    • 4b4eb78 chore: fix lint error in md file
    • d3ea720 chore(docs): fix typo (#304)

    See the full diff

    FAQ and help

    There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


    Your Greenkeeper Bot :palm_tree:

    Reviewed by greenkeeper[bot] at 2019-07-17 13:30
  • 10. TypeError: from.from is not a function. (In 'from.from(observables[0])', 'from.from' is undefined)

    Here is my component

    const PlaylistItem = ({playlist}) => {
      console.log(playlist);
        return (
        <List.Item
          title={playlist.title}
          description="by you"
          left={props => <List.Icon {...props} icon="audiotrack" />}
        />
      );
    };
    
    const enhance = withObservables(['playlist'], ({playlist}) => ({
      playlist
    }));
    
    export default enhance(PlaylistItem);
    

    Here is how I call the component

    <FlatList
              data={this.state.playlists}
              renderItem={(item) => <PlaylistItem playlist={item} />}
            />
    

    This is my query

    async componentDidMount(){
        const playlists = database.collections.get('playlists');
        const allPlaylists = await playlists.query().fetch();
        console.log("playlist ", allPlaylists);
        this.setState({
          playlists: allPlaylists
        })
      }
    

    Please help me. I am not able to understand the problem. If I remove withObservables and export as it is, it is working fine.

    Reviewed by YajanaRao at 2019-09-26 09:50
  • 11. Sync error handling

    Are there any good examples of error handling for sync in both the frontend and backend that I can reference? I'm having trouble with the pullChanges & pushChanges changing records to synced even though some records failed to be pushed or pulled.

    EDIT: I added try catch to throw 503 error if any error occurs and it works but something about it feels off

    Reviewed by KrisLau at 2021-12-10 15:12
  • 12. Failed to apply plugin [id 'kotlin-android']

    each time i run my code i get the same message which is

    FAILURE: Build failed with an exception.

    • Where: Build file 'D:\ya rab\PetApp-main\PetApp-main\android\app\build.gradle' line: 25

    • What went wrong: A problem occurred evaluating project ':app'.

    Failed to apply plugin [id 'kotlin-android'] The current Gradle version 5.6.2 is not compatible with the Kotlin Gradle plugin. Please use Gradle 6.1.1 or newer, or the previous version of the Kotlin plugin.

    • Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

    • Get more help at https://help.gradle.org


    the code which is in line 25 is as following

    apply plugin: 'kotlin-android'

    Reviewed by shawki99 at 2022-05-16 00:54
  • 13. Sync fails with error Invalid comparisonRight.

    Hi,

    We are getting following sync error some times, Invalid comparisonRight We could not find the correct reason because the issue occurring is in production. if Once this error has occurred, following all sync's are getting failed.

    Reviewed by nijeeshvayalassery at 2022-05-08 16:21
  • 14. Pass parameters from context provider to `withObservables`

    So currently I'm storing my global state in async provider and sending that to each individual screen using react navigations params, however I was told that it would be better to store this using Context API similar to how firebase auth is setup. I setup my context API with this global state now but I'm unsure how to send this to the compose() so that I can use it in the observable database queries?

    EDIT (Adding more context)

    Code

    Context Provider:

    import React, {createContext, useContext, useState} from 'react';
    
    const ExampleContext= createContext();
    function useExample() {
      return useContext(ExampleContext);
    }
    
    function ExampleProvider({children}) {
      const [exampleState, setExampleState] = useState(null);
    
      const value = {
        exampleState,
        setExampleState
      };
    
      return (
        <ExampleContext.Provider value={value}>
          {children}
        </ExampleContext.Provider>
      );
    }
    
    export {ExampleContext, ExampleProvider, useExample};
    

    Component:

    export default compose(
      withDatabase,
      withObservables([], ({database}) => ({
        variableName: database
          .get('table_name')
          .query()
          .observe(),
      })),
    )(Component)
    

    What I'm trying to do

    export default compose(
      withDatabase,
      withObservables([], ({database}) => {
        const example = useExample;
        return {
            variableName: database
              .get('table_name')
              .query()
              .observe(),
        };
      }),
    )(Component)
    

    but I get an invalid hook call so I'm wondering if there is a way to use RxJS/recompose to do so or if there is a different approach I can use pass this global state to all my screens without redux. I have also tried passing my HOC to the withObservables using withContext from recompose to no avail but I likely messed something up there so any help would be appreciated

    Reviewed by KrisLau at 2022-05-06 13:39
  • 15. Typescript Bump

    There's a big gap between Flow and Typescript typings and this PR is trying to fix this difference.

    Instead of using the current modules approach for TS, (almost) every JS file has its own .d.ts file.

    From now on, .d.ts files needs to be updated only if a signature changes and it is easier to non TS engineers guess how to update it.

    Reviewed by sidferreira at 2022-05-02 22:24
  • 16. sql.js adapter?

    My app uses quit some relatively complex SQL queries in order to work appropriately. As a result extending to the web using WatermelonDB would currently be very challenging using the LokiJS adapter. It would therefore be great to have SQL capabilities in the browser, something like an adapter for sql.js.

    Before diving deeper into this, I'd like to know the following:

    • Would this be a desirable extension for WatermelonDB? If not, why not?
    • Where would be the main technical difficulties in creating such adapter?
    Reviewed by nmeibergen at 2022-05-02 06:21
  • 17. build(deps): bump cross-fetch from 3.0.6 to 3.1.5 in /examples/native

    Bumps cross-fetch from 3.0.6 to 3.1.5.

    Release notes

    Sourced from cross-fetch's releases.

    v3.1.5

    What's Changed

    New Contributors

    Full Changelog: https://github.com/lquixada/cross-fetch/compare/v3.1.4...v3.1.5

    v3.1.4

    🐞 fixed typescript errors.

    v3.1.3

    🐞 fixed typescript compilation error causing #95, #101, #102.

    v3.1.2

    🐞 added missing Headers interface augmentation from lib.dom.iterable.d.ts (#97)

    v3.1.1

    🐞 fixed missing fetch api types from constructor signatures #96 (thanks @​jstewmon)

    v3.1.0

    ⚑️ improved TypeScript support with own fetch API type definitions (thanks @​jstewmon) ⚑️ set fetch.ponyfill to true when custom ponyfill implementation is used. πŸ’‘ set the same fetch API test suite to run against node-fetch, whatwg-fetch and native fetch.

    Commits
    • c6089df chore(release): 3.1.5
    • a3b3a94 chore: updated node-fetch version to 2.6.7 (#124)
    • efed703 chore: updated node-fetch version to 2.6.5
    • 694ff77 refactor: removed ora from dependencies
    • efc5956 refactor: added .vscode to .gitignore
    • da605d5 refactor: renamed test/fetch/ to test/fetch-api/ and test/module/ to test/mod...
    • 0f0d51d chore: updated minor and patch versions of dev dependencies
    • c6e34ea refactor: removed sinon.js
    • f524a52 fix: yargs was incompatible with node 10
    • 7906fcf chore: updated dev dependencies
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    Reviewed by dependabot[bot] at 2022-04-28 22:27
πŸ”„ A realtime Database for JavaScript Applications
πŸ”„ A realtime Database for JavaScript Applications

Announcement              Version 10.0.0 is now released, read the ANNOUNCEMENT                RxDB A realtime Database for JavaScript Applications Rx

May 15, 2022
Realm is a mobile database: an alternative to SQLite & key-value stores

Realm is a mobile database that runs directly inside phones, tablets or wearables. This project hosts the JavaScript versions of Realm. Currently we s

May 13, 2022
Full featured SQLite3 Native Plugin for React Native (Android and iOS)
Full featured SQLite3 Native Plugin for React Native (Android and iOS)

react-native-sqlite-storage SQLite3 Native Plugin for React Native for both Android (Classic and Native), iOS and Windows Foundation of this library i

May 11, 2022
SQLite3 Native Plugin for React Native for iOS, Android, Windows and macOS.
SQLite3 Native Plugin for React Native for iOS, Android, Windows and macOS.

SQLite3 Native Plugin for React Native for Android, iOS, Windows and macOS. This plugin provides a WebSQL-compatible API to store data in a react nati

May 9, 2022
Native bindings to LevelDB for React Native, exposed as leveldown-compatible interface

react-native-leveldown This library implements an abstract-leveldown compatible interface to LevelDB for React Native. The implementation is a thin Na

Dec 14, 2021
local storage wrapper for both react-native and browser. Support size controlling, auto expiring, remote data auto syncing and getting batch data in one query.

react-native-storage This is a local storage wrapper for both react native apps (using AsyncStorage) and web apps (using localStorage). ES6 syntax, pr

May 16, 2022
A minimalistic wrapper around React Native's AsyncStorage.

React Native Simple Store A minimalistic wrapper around React Native's AsyncStorage. The react-native-simple-store is a good match for apps that are n

Apr 29, 2022
React native Library for creating Local DB models
React native Library for creating Local DB models

React Native DB Models This wrapper is built on top of React Native Store and provides a better and improved Database layer for asynchronous DB transa

Dec 29, 2021
Couchbase Lite binding for React Native Android & iOS
Couchbase Lite binding for React Native Android & iOS

react-native-couchbase-lite NOTE: This plugin works for Couchbase Lite 1.x only. For new projects, we recommend to use the Couchbase Lite 2.0 Native A

Apr 12, 2022
Hacky way to run pouchdb in react-native

react-native-pouchdb Hacky and mostly untested way to run pouchdb in react-native! I haven't encountered any glaring problems during development, but

Dec 22, 2019
A AsyncStorage based mongoose like storage for react-native

React Native mongoose (remobile) A AsyncStorage based mongoose like storage for react-native Installation npm install @remobile/react-native-mongoose

May 15, 2022
fs for the browser using level-filesystem and browserify

react-native-level-fs fs in react-native using level-filesystem and asyncstorage-down npm install react-native-level-fs Usage To use simply require i

Oct 29, 2021
πŸ‰ Reactive & asynchronous database for powerful React and React Native apps ⚑️
πŸ‰ Reactive & asynchronous database for powerful React and React Native apps ⚑️

A reactive database framework Build powerful React and React Native apps that scale from hundreds to tens of thousands of records and remain fast ⚑️ W

May 15, 2022
This application contains end to end non blocking reactive flow. From Bankend( Database, Spring) and FrontEnd Angular

SpringReactiveApp This application has following projects Spring boot reactive with Mongo Database Angular with EventSource for reactive(non-blocking

Oct 26, 2021
βš›οΈ Hooks for fetching, caching and updating asynchronous data in React
βš›οΈ Hooks for fetching, caching and updating asynchronous data in React

Hooks for fetching, caching and updating asynchronous data in React Enjoy this library? Try the entire TanStack! React Table, React Form, React Charts

May 16, 2022
🧭 Declarative, asynchronous routing for React.
🧭 Declarative, asynchronous routing for React.

Navi Declarative, asynchronous routing for React. Navi is a JavaScript library for declaratively mapping URLs to asynchronous content. It comes with:

May 11, 2022
Use-tasker - A react task runner for asynchronous things

useTasker A React Hook to schedule asynchronous things. Install yarn add use-tas

Feb 23, 2022
A simple asynchronous React message popup utility
A simple asynchronous React message popup utility

React Message A simple asynchronous React message popup utility, no needed React Context. So you can use it in anywhere. You just need to install Reac

Apr 15, 2022
Implement Mini-React in 400 lines of code, a minimal model with asynchronous interruptible updates.
Implement Mini-React in 400 lines of code, a minimal model with asynchronous interruptible updates.

Mini-React Implement Mini-React in 400 lines of code, a minimal model with asynchronous interruptible updates. Demos A simple running screenshot: Intr

May 7, 2022
RRForms is a simple utility that adds reactive conditional disabling/enabling & addition/removal of validators to Angular 2+ Reactive Forms.
RRForms is a simple utility that adds reactive conditional disabling/enabling & addition/removal of validators to Angular 2+ Reactive Forms.

ngx-rrforms Reactive Reactive Forms for Angular 2+. Self-reactivity and more (soon). CONTENT TABLE Usage examples conditional disabling conditional va

Jan 18, 2022