Giter Site home page Giter Site logo

pubkey / rxdb Goto Github PK

View Code? Open in Web Editor NEW
20.6K 211.0 1.0K 267.05 MB

A fast, local first, reactive Database for JavaScript Applications https://rxdb.info/

Home Page: https://rxdb.info/

License: Apache License 2.0

JavaScript 4.21% HTML 0.08% TypeScript 93.46% CSS 1.87% Shell 0.02% Dart 0.35%
database nosql rxjs nodejs couchdb react-native pouchdb realtime-database realtime graphql

rxdb's Introduction


JavaScript Database

A fast, local-first, reactive Database for JavaScript Applications

       

     


  What is RxDB?

RxDB (short for Reactive Database) is a local-first, NoSQL-database for JavaScript Applications like Websites, hybrid Apps, Electron-Apps, Progressive Web Apps, Deno and Node.js. Reactive means that you can not only query the current state, but subscribe to all state changes like the result of a query or even a single field of a document. This is great for UI-based realtime applications in a way that makes it easy to develop and also has great performance benefits but can also be used to create fast backends in Node.js.
RxDB provides an easy to implement protocol for realtime replication with your existing infrastructure or one of the plugins for HTTP, GraphQL, CouchDB, Websocket, WebRTC, Supabase, Firestore, NATS.
RxDB is based on a storage interface that enables you to swap out the underlying storage engine. This increases code reuse because you can use the same database code for different JavaScript environments by just switching out the storage settings.

Use the quickstart, read the documentation or explore the example projects.

  Multiplayer realtime applications

realtime.gif

  Replicate with your existing infrastructure

RxDB provides an easy to implement, battle-tested replication protocol for realtime sync with your existing infrastructure.
There are also plugins to easily replicate with GraphQL, CouchDB, Websocket, WebRTC,Supabase, Firestore or NATS.

  Flexible storage layer

RxDB is based on a storage interface that enables you to swap out the underlying storage engine. This increases code reuse because the same database code can be used in different JavaScript environments by just switching out the storage settings.

You can use RxDB on top of IndexedDB, OPFS, LokiJS, Dexie.js, in-memory, SQLite, in a WebWorker thread and even on top of FoundationDB and DenoKV.

No matter what kind of runtime you have, as long as it runs JavaScript, it can run RxDB:

  Quick start

Install

npm install rxdb rxjs --save

Store data

import { 
  createRxDatabase
} from 'rxdb/plugins/core';

/**
 * For browsers, we use the dexie.js based storage
 * which stores data in IndexedDB in the browser.
 * In other JavaScript runtimes, we can use different storages:
 * @link https://rxdb.info/rx-storage.html
 */
import { getRxStorageDexie } from 'rxdb/plugins/storage-dexie';

// create a database
const db = await createRxDatabase({
    name: 'heroesdb', // the name of the database
    storage: getRxStorageDexie()
});

// add collections
await db.addCollections({
  heroes: {
    schema: mySchema
  }
});

// insert a document
await db.heroes.insert({
  name: 'Bob',
  healthpoints: 100
});

Query data once

const aliveHeroes = await db.heroes.find({
  selector: {
    healthpoints: {
      $gt: 0
    }
  }
}).exec(); // the exec() returns the result once

Observe a Query

await db.heroes.find({
  selector: {
    healthpoints: {
      $gt: 0
    }
  }
})
.$ // the $ returns an observable that emits each time the result set of the query changes
.subscribe(aliveHeroes => console.dir(aliveHeroes));

Continue with the quickstart here.

  More Features (click to toggle)

Subscribe to events, query results, documents and event single fields of a document

RxDB implements rxjs to make your data reactive. This makes it easy to always show the real-time database-state in the dom without manually re-submitting your queries. You can also add custom reactiveness libraries like signals or other state management.

db.heroes
  .find()
  .sort('name')
  .$ // <- returns observable of query
  .subscribe( docs => {
    myDomElement.innerHTML = docs
      .map(doc => '<li>' + doc.name + '</li>')
      .join();
  });

reactive.gif

MultiWindow/Tab

RxDB supports multi tab/window usage out of the box. When data is changed at one browser tab/window or Node.js process, the change will automatically be broadcasted to all other tabs so that they can update the UI properly.

multiwindow.gif

EventReduce

One big benefit of having a realtime database is that big performance optimizations can be done when the database knows a query is observed and the updated results are needed continuously. RxDB internally uses the Event-Reduce algorithm. This makes sure that when you update/insert/remove documents, the query does not have to re-run over the whole database but the new results will be calculated from the events. This creates a huge performance-gain with zero cost.

Use-Case-Example

Imagine you have a very big collection with many user-documents. At your page you want to display a toplist with users which have the most points and are currently logged in. You create a query and subscribe to it.

const query = usersCollection.find().where('loggedIn').eq(true).sort('points');
query.$.subscribe(users => {
    document.querySelector('body').innerHTML = users
        .reduce((prev, cur) => prev + cur.username+ '<br/>', '');
});

As you may detect, the query can take very long time to run, because you have thousands of users in the collection. When a user now logs off, the whole query will re-run over the database which takes again very long.

await anyUser.incrementalPatch({loggedIn: false});

But not with the EventReduce. Now, when one user logs off, it will calculate the new results from the current results plus the RxChangeEvent. This often can be done in-memory without making IO-requests to the storage-engine. EventReduce not only works on subscribed queries, but also when you do multiple .exec()'s on the same query.

Schema

Schemas are defined via jsonschema and are used to describe your data.

const mySchema = {
    title: "hero schema",
    version: 0,                 // <- incremental version-number
    description: "describes a simple hero",
    primaryKey: 'name',         // <- 'name' is the primary key for the collection, it must be unique, required and of the type string 
    type: "object",
    properties: {
        name: {
            type: "string",
            maxLength: 30
        },
        secret: {
            type: "string",
        },
        skills: {
            type: "array",
            maxItems: 5,
            uniqueItems: true,
            item: {
                type: "object",
                properties: {
                    name: {
                        type: "string"
                    },
                    damage: {
                        type: "number"
                    }
                }
            }
        }
    },
    required: ["color"],
    encrypted: ["secret"] // <- this means that the value of this field is stored encrypted
};
Mango / Chained queries

RxDB can be queried by standard NoSQL mango queries like you maybe know from other NoSQL Databases like mongoDB.

Also you can use the query-builder plugin to create chained mango-queries.

// normal query
myCollection.find({
  selector: {
    name: {
      $ne: 'Alice'
    },
    age: {
      $gt: 67
    }
  },
  sort: [{ age: 'desc' }],
  limit: 10
})

// chained query
myCollection
  .find()
  .where('name').ne('Alice')
  .where('age').gt(18).lt(67)
  .limit(10)
  .sort('-age')
  .exec().then( docs => {
    console.dir(docs);
  });
Encryption

By setting a schema-field to encrypted, the value of this field will be stored in encryption-mode and can't be read without the password. Of course you can also encrypt nested objects. Example:

{
  "title": "my schema",
  "properties": {
    "secret": {
      "type": "string",
      "encrypted": true
    }
  },
  "encrypted": [
    "secret"
  ]
}
Import / Export

RxDB lets you import and export the whole database or single collections into json-objects. This is helpful to trace bugs in your application or to move to a given state in your tests.

// export a single collection
const jsonCol = await myCollection.dump();

// export the whole database
const jsonDB = await myDatabase.dump();

// import the dump to the collection
await emptyCollection.importDump(json);


// import the dump to the database
await emptyDatabase.importDump(json);
Key-Compression

Depending on which adapter and in which environment you use RxDB, client-side storage is limited in some way or the other. To save disc-space, RxDB uses a schema based keycompression to minimize the size of saved documents. This saves about 40% of used storage.

Example:

// when you save an object with big keys
await myCollection.insert({
  firstName: 'foo'
  lastName:  'bar'
  stupidLongKey: 5
});

// key compression will internally transform it to
{
  '|a': 'foo'
  '|b':  'bar'
  '|c': 5
}

// so instead of 46 chars, the compressed-version has only 28
// the compression works internally, so you can of course still access values via the original key.names and run normal queries.
console.log(myDoc.firstName);
// 'foo'

And for any other use case, there are many more plugins and addons.

  Get started

Get started now by reading the docs or exploring the example-projects.

  Support and Contribute

More content

Angular Database, Frontend Database, localStorage, React Database, Browser Database, React Native Database, PWA Database, In-memory NoSQL database, JSON database

rxdb's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxdb's Issues

Incorrect data returned in find functions

There appears to be an issue with the data being returned in the Find. What is returned does not match what comes out of the PouchDB Find functions.

It would appear that the issue stems from RxCollection _createDocument

My issue is this.
I have the following document in PouchDB

{ _id: 'abc', _rev:'1' }

Call RxDocument.remove() and the data would become this.
{ _id: 'abc', _rev:'1', _deleted: true}

Now add a new document with the same Primary
{ _id: 'abc', _rev:'2'}

Run a Find query and you will see that the data will probably as in my case have this entry
{ _id: 'abc', _rev:'1', _deleted: true}

Which is not what the PouchDB Find returned.

As I said I think the issue stems from RxCollection _createDocument

In here _rev 1 is stored in _docCache for Primary abc
When the code checks the cache for the primary from the PouchDB find it matches and returns the entry in _docCache being _rev 1 and not _rev 2 which was returned from PouchDB.

I think there needs to be a check on the _rev key and not just the Primary.

Perhaps something like this is enough.
if (cacheDoc && cacheDoc._rev == json["_rev"]) return cacheDoc;

Does that make any sense?

RxDBSchemas array of string

Hi everyone,

When we are using an array of string, RXDB's collection return a wrong array.

Example:

['abc','8'] => [{0:'a',1:'b',2:'c'},{0:'8'}]

while we are expecting the same array.

example of schema:

{
  "type": "object",
  "properties": {
    "likes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  }
}

Make storage backend pluggable

We've tried to solve a lot of the same problems in rethinkdb/horizon, but the approach you've taken in rxdb is simpler in a lot of ways. I'd love to work with you a bit on this to see if we can make your client compatible with Horizon server and/or RethinkDB. Given that RethinkDB (and thus Horizon) supports changefeeds, I think it would be as great fit as a storage backend for this project (reactive, replication, offline-first).

@pubkey let me know what your thoughts are!

Omitting JSON Schema on RxDatabase#collection creates runtime exception

I recently ran dbInstance.collection("my_collection") and got the following error:

main.bundle.js:37243 Uncaught (in promise) TypeError: Cannot read property 'hash' of undefined
    at RxDatabase._callee5$ (http://localhost:3002/js/main.bundle.js:37243:53)
    at tryCatch (http://localhost:3002/js/main.bundle.js:28199:41)

Link to source code raising exception

I was able to fix the issue by calling dbInstance.collection("my_collection", MY_JSON_SCHEMA).

Possible Solutions:

  1. Mark field as required in Typescript typing
  2. Perform a nil check at runtime describing the issue.

Wanted to post this up here incase anyone is googling the same errorr.

@pubkey Are my assumptions here correct? I can get a fix in the coming days if so.

Avoid monkey-patching localstorage-down?

Hi! 👋 I just read through the README and love this concept!

Anyway, I noticed you're monkey-patching localstorage-down here. I can see how the in-memory keys would cause problems for multi-tab; I think this is just a bug in localstorage-down that should probably be fixed in that library. Most likely it should also be applied to fruitdown and fsdown as well since they're based on localstorage-down. Would you be so kind as to open up a PR? :D

Demonstrate Population in the current examples

Case

Request.

Issue

The current examples do not demonstrate Population also the current documentation a little hard to follow (I am working on a PR but I am need to get my head around it more first) hence why an example may be productive.

Conditionally allow inserts to bypass schema validation

I have the case where I want to have a "singleton" document within my collection - something that is different from the other documents in the collection, but ought to (for authentication reasons) be closely associated with the collection.
In normal pouch/couch, I would just insert the document with a fixed ID, say settings or something. I'd love to be able to do that in rxdb as well.
Without this functionality, I'll be forced to just define an essentially empty schema, which loses a lot of the benefits :/

ANNOUNCEMENT: version 3.0.0

Hello users.
There are plenty of things I want to add to RxDB which will be breaking features.
Therefore I have the big goal to finish version 3.0.0 which will contain all of them at once so that the dev will not have to migrate all the time.
The goal is to finish it until March2017.

You can see the milestone here.
If you have an additional feature you want to see at v3.0.0, please write it down here.

Any help is appreciated! If you have the time to help with one of the features, please tell me so I can coordinate the work.

Is RxDB the better option? - RxDB as redux-store

I'm entirely new to RxDB but from the onset it does look like it may be a good fit, especially since I'm also a big fan of RxJS and Offline First solutions.

While I work with the excellent VueJS framework I am finding the Vuex side limiting for my scenario. Vuex is essentially a store with modules and has a nice way of mapping state between Vue and Vuex. Firebase is the other service I'd like to work with but it also has it's limitations. For now I'll just list the things that are most important to me below, maybe RxDB is their solution?

• Offline First and the ability to run a local instance of RxDB, seems these are already included.

• A DB that has the essential CRUD functions onboard that can be applied to any store module. I have no interest in writing a bunch of actions, mutations and getters for Vuex modules. Just give me universal operations that take params so that they can perform on nodes in any collection without having to reinvent the basics.

• Full RxJS support where I can map/inject the observables to/from any nodes in my documents into Vue components. No GraphQL or special mapping, just simple RxJS IO please.

• Some way to sync to realtime services like Firebase. Not every document needs to be collaborated on, so all I require is to place a given document on Firebase during a session and then for RxDB changes to be synced to the realtime document. So all the changes would still only be made on the RxDB side and the sync would be automatic.

That's about it, hope the answers are just as simple as my requirements.

given leveldown is no valid adapter

I'm upgrading to the newest version of RxDB for a localstorage project and hit this error:

Uncaught (in promise) Error: given leveldown is no valid adapter
    at Object.isLevelDown (http://localhost:3002/js/main.bundle.js:30906:107)
    at Object._callee9$ (http://localhost:3002/js/main.bundle.js:29691:31)
    at tryCatch (http://localhost:3002/js/main.bundle.js:28246:41)
    at Generator.invoke [as _invoke] (http://localhost:3002/js/main.bundle.js:28481:23)
    at Generator.prototype.(anonymous function) [as next] (http://localhost:3002/js/main.bundle.js:28298:22)
    at step (http://localhost:3002/js/main.bundle.js:28929:31)
    at http://localhost:3002/js/main.bundle.js:28947:15
    at F (http://localhost:3002/js/main.bundle.js:27075:29)
    at Object.<anonymous> (http://localhost:3002/js/main.bundle.js:28926:13)
    at Object.create (http://localhost:3002/js/main.bundle.js:29733:23)

within this function:

	/**
	 * check if the given module is a leveldown-adapter
	 * throws if not
	 */
	function isLevelDown(adapter) {
	    if (!adapter || typeof adapter.super_ !== 'function' || typeof adapter.destroy !== 'function') throw new Error('given leveldown is no valid adapter');
	}function fastUnsecureHash(obj) {
	    if (typeof obj !== 'string') obj = JSON.stringify(obj);
	    var hash = 0,
	        i = void 0,
	        chr = void 0,
	        len = void 0;
	    if (obj.length === 0) return hash;
	    for (i = 0, len = obj.length; i < len; i++) {
	        chr = obj.charCodeAt(i);
	        hash = (hash << 5) - hash + chr;
	        hash |= 0; // Convert to 32bit integer
	    }
	    if (hash < 0) hash = hash * -1;
	    return hash;
	}

I'm not using LevelDB anywhere in my app, so I was surprised to see this come up. Is it a bug, or is it possible that I have misconfigured a setting somewhere?

find not working

Can't get rxdb to find data in a collection. I have tried numerous variations of the find.

CACHEDB.collections.documents.find()
.where('cache.name').eq(pathData.base)
.where('cache.path').eq(pathData.dir)
.exec()
.then( (document) => {
resolve(document);
});

I have created an index on the database collection

  col.pouch.createIndex({
    index: {
      fields: ['cache.name', 'cache.path'],
      name: 'cachenamepath',
      ddoc: 'cachenamepath',
      type: 'json'
    }

I know there is data that matches the query.

RxDocument to offer a proxy object?

Hi there. Great job on this project.

One thing that might be helpful:

Right now you need to called person.get('name') to get the name property off of a person RxDocument. Is there a way to have RxDocument be a proxy object so that we could call person.name instead?

Currently I am doing this with:

// Proxy simple properties get calls to an rxdocument's get method
const p = function(proxyObj) {
  return new Proxy({}, {
    get: (target, name) => {
      return proxyObj.get(name);
    },
  });
};

// Example:
const person = p(rxPerson);
console.log(person.name);

My use case is pretty much getting a lot of properties off of a single model so I don't know how well this scales.

regex MongoDB expressions supported?

I'm a beginner to PouchDB and Mongo so I could be consuming this library incorrectly.

When I run the following query I return the correct number of results.

        collection.find()
          .where({ name: { $eq: 'Bob' } })
          .$
          .filter(docs => docs !== null)
          .subscribe(docs => {
            docs.map(doc => console.log(doc.get('name')));
          });

If I modify the where clause to use a regex all results are returned.

 .where({ name: { $regex: /Bob/ig } })

I'm referencing this documentation for the query syntax.

Thank you.

'primary' of undefined

when i try to add to my project always give me this error.
I just add script tag;

Uncaught TypeError: Cannot read property 'primary' of undefined
    at checkField (http://localhost:4200/rxdb.js:2370:26)
    at traverse (http://localhost:4200/rxdb.js:2384:17)
    at traverse (http://localhost:4200/rxdb.js:2388:13)
    at traverse (http://localhost:4200/rxdb.js:2388:13)
    at validateFieldsDeep (http://localhost:4200/rxdb.js:2391:5)
    at checkSchema (http://localhost:4200/rxdb.js:2406:5)
    at Object.create (http://localhost:4200/rxdb.js:2461:5)
    at Object.1../RxSchema (http://localhost:4200/rxdb.js:15:56)
    at s (http://localhost:4200/rxdb.js:1:254)
    at http://localhost:4200/rxdb.js:1:305checkField @ rxdb.js:2370traverse @ rxdb.js:2384traverse @ rxdb.js:2388traverse @ rxdb.js:2388validateFieldsDeep @ rxdb.js:2391checkSchema @ rxdb.js:2406create @ rxdb.js:24611../RxSchema @ rxdb.js:15s @ rxdb.js:1(anonymous function) @ rxdb.js:15../Database.schemas @ rxdb.js:917s @ rxdb.js:1(anonymous function) @ rxdb.js:110../PouchDB @ rxdb.js:2529s @ rxdb.js:1(anonymous function) @ rxdb.js:19../index.js @ rxdb.js:2467s @ rxdb.js:1e @ rxdb.js:1(anonymous function) @ rxdb.js:1

How do we secure the frontend?

Hey there! Sorry if this is answered somewhere, I didn't see it when I looked around.
As we all know, you can't trust the client. However, this library appears to allow the client to directly insert to its local database, that is then sync'd back to the server.

Is there a way on the server to control what the client is allowed to do?
If so, does the client automatically recover from that (i.e. I change someone's username in my local database, then the server rejects so my app redraws with the corrected username from the server).

It's of course possible that I'm thinking about the use of this package all wrong. If so please let me know 😄

React native

If it's good for working on the react-native - maybe it's worth adding it to the README among others other frameworks?

ANNOUNCEMENT: - The logo of RxDB

Hello guys.
As you may have noticed, I created a logo for RxDB.
My plan is that we now further improve the logo to get a final version.
Everything, the colors, the shapes, the format is changeable by you.

Thoughts on the current version:

  • It displays the shapes of the "official" database-logo
  • The main color is the one from rxjs
  • The logo follows the FFF concept and should be recognized as made by open-source-developers, not by a big company.
  • The logo should be recognizeable very big and even as favicon-size.

Current version:

logo

I will later print some stickers and distribute them to RxDB-users. So give your best and you get one. 😉

How to contribute:

I made the logo with plain javascript + d3.js. So feel free to create pull-requests to this file.

Problems with the current version:

  • We need a version which optional displays the name "RxDB"
  • The colors are not perfect (just my opinion)
  • The proportions of the 3 big blocks, do not give the impression of the "offical"-database-logo.
  • The pattern of the small blocks is not "random enough"

Firebase offline database

Good Day all,

I was wondering if this library can work with firebase as backend as offline storage.

Compound Index not being created

Case

BUG

Issue

I have a schema that defines a Compound Index.

The normal indexes are being created but the compound indexes are not created. I can't find any code that actually creates the compound indexes.

I assume there should be something in RxCollection in the prepare function where the normal indexes are created.

Info

  • Environment: Node.js, electron
  • Adapter: LevelDB

Code

Compound Index is being defined like this.

 {
  "$schema": "http://json-schema.org/draft-04/schema#",
  "version": 1,
  "disableKeyCompression": true,
  "type": "object",
  "properties": {
    "cacheKey": {
      "type": "string",
      "primary": true
    },
    "status": {
      "type": "number"  
    },
    "cloud": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "auth": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "path": {
          "type": "string",
        },
        "size": {
          "type": "integer"
        },
        "createdDate": {
          "type": "string",
          "format": "date-time"
        },
        "modifiedDate": {
          "type": "string",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "auth",
        "name",
        "path",
        "size",
        "createdDate",
        "modifiedDate"
      ]
    },
    "cache": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "path": {
          "type": "string"
        },
        "addedDate": {
          "type": "string",
          "format": "date-time",
          "index": true
        },
        "lastModifiedDate": {
          "type": "string",
          "format": "date-time",
          "index": true
        },
        "size": {
          "type": "integer"
        }
      },
      "required": [
        "name",
        "path",
        "addedDate",
        "lastModifiedDate",
        "size"
      ]
    }
  },
  "required": [
    "status",
    "cloud",
    "cache"
  ],
  "compoundIndexes": [
    ["cache.name", "cache.path"]
  ]
}  

EDIT by pubkey: formated json

Changes to Schemas

I had a first version of my database. It worked great. The problem is when I modified my schema (by adding a new field to my schema). I get an error on Rxdb.create. My collection is called (audio):

Error: collection(audio): another instance created this collection with a different schema.

I figured I might try to handle the error and just drop the existing databases, but I don't see a way to destroy the databases or do any kind of migration. Do you have any insight into how one could deal with this kind of thing in Rxdb?

401 Unauthorized access to CouchDB

Case

401 Unauthorized access to CouchDB

Issue

Working with the Vue example I have updated:

const syncURL = 'http://' + window.location.hostname + ':10101/';

To

const syncURL = 'http://' + window.location.hostname + ':5984/';

Now when I open it up in the browser I get the following error:

PUT http://localhost:5984/heroes/ 401 (Unauthorized)
Uncaught (in promise) Error: [object Object]
    at Sync.eval (eval at <anonymous> (build.js:2054), <anonymous>:1043:43)
    at Sync.EventEmitter.emit (eval at <anonymous> (build.js:1247), <anonymous>:81:17)
    at eval (eval at <anonymous> (build.js:4013), <anonymous>:943:12)

Info

  • Environment: Google Chrome
  • Adapter: idb (As per Vue example)

Code

Forked repo here: https://github.com/CrashyBang/rxdb

Have scoured docs/code for password/username config for CouchDB but had no luck.

Cheers.

what's the pattern for "connecting" components?

It seems a redux-style connect API will soon come about so you don't have to manually call subscribe in componentDidMount etc. Are there any thoughts on this already so the wheel doesn't have to be re-invented? I.e. a strategy that you have in mind.

What about possibly a "transparent reactive programming" interface similar to what Meteor was originally doing and what MobX does. I.e. that you can can do this:

render() {
  return (
   <ul>
     {heroCollection
       .find()
       .sort('name')
       .$.map( docs => <li>{doc.name}</li)
      }
   </ul>
 )
}

A year ago I built https://github.com/ultimatejs/tracker-react to allow you to transparently reactive functions within your render method and made it so Meteor's Tracker tools were aware of any reactive calls within your render method and then called forceUpdate any time new data come through. An interface like that might also be attractive. I'm not sure how render in this case would be aware of any observable subscription updates. Actually, at least for a react class component it could be as simple and explicit as this:

render() {
  return (
   <ul>
     {heroCollection
       .find()
       .sort('name')
       .$
       .notifyComponent(this) //here's where the magic happens obviously
       .map( docs => <li>{doc.name}</li)
      }
   </ul>
 )
}

So essentially you're passing rxdb an instance of the component which it can intelligently call forceUpdate on when the subscription updates.

Having been a long-time Meteor advocate, i spent the last year completely getting off of it and using Redux instead. I'm not sure I personally would go back to transparent reactive programming as easy as it was. But that's mainly because for my projects I need the supreme testability of pureer functions. The above obviously has major side-effects. However, that depends on how you look at it. Right now we live in a world where because connections and getting data is so slow, we can't really think of our functions and components as a function of a global database--it's why Redux makes us jump through so many hoops to make your component tree a function of a local database, and then goes farther to impose on you that your components are pure through connect. However, you technically could in a reliable/testable way use data from your store in your components in a non-pure way (e.g. with the hypothetical api: store.get('key')), so long as the subscriptions notified the component to update similar to above. And then with fixtures for your client-side database you can easily test functions with the above side-effects in a reliable way, allowing you to think of your data as just constants. You won't be dealing with technically correct pure referentially transparent functions, but perhaps it doesn't matter--at least for testing where you can instantly mock your database, especially with rxdb.

So that's a case for a "referentially transparent reactive API" for rxdb. The major benefit of it all is that it definitely is way faster to at least prototype this code. I loved Meteor's Tracker + Blaze. I now love React + Redux. But I love the latter because of the reliability it gives me, certainly not for the speed of initially building things. It is at least 2x slower, even after mastering the tools. Basically the only case against a referentially transparent reactive interface is that it's not technically pure. There likely will be various testing tools you can't use (which rely on true pure functions), and leaks to the abstraction. I simply didn't want to invest the time to find out. I.e. do a complete comparison of testing essentially meteor's transparent reactive interface for React which I built with tracker-react vs. testing pure functions and redux. At the time i decided the best use of my time was just to get going with Redux et al. The ecosystem will definitely benefit the latter. However if I was newer to programming I'd definitely be far better off with the transparent reactive style. It's way way easier to grasp and get off to a running start with. So if you guys wanted to target that audience--which no doubt is large, perhaps larger than more senior programmers--you may have a first class solution. Because you're using observables, you may have already overcome some of the various problems Meteor's Tracker had. Here are 2 articles I wrote a year ago highlighting those problems:

https://medium.com/@faceyspacey/the-evolution-of-tracker-solutions-to-its-core-problems-4b9cb90d479a#.1yvdndyq5

https://medium.com/@faceyspacey/tracker-vs-redux-implicit-vs-explicit-df847abcc230#.syas78lpz

Observables may in fact be the way transparent reactive programming should be done. Basically Tracker re-runs your code too much and you have very little control over it. So it's inefficient in how it guarantees your views/subscriptions stay up to date. Observables likely re-runs way less. On the other hand, MobX is known for less component updates compared to Redux (at least prior to the latest react-redux 5.0) because of its spreadsheet-style computations where various dependencies between reactive functions/data is graphed and granularly updates leaves if one of its dependencies update. MobX's depdency graph is also what makes it way better than Tracker, solving many of the problems I highlighted about Tracker in the above articles. So, perhaps MobX is even more suited for the problem than Observables. At least more optimized for react than standalone observables, as MobX can take your entire app into consideration, not just ad-hoc observables used throughout your components, which may trigger a child update when the parent already updated. That's a problem that the recent 5.0 update to react-redux solves/improves.

The react-redux package just released some major changes in their 5.0 release. Basically it makes your connected components aware of its parents, and if it's parent updates, the children won't, whereas before each component was individually subscribe/connected to the redux store and might update even if it's parent was also subscribed and handled the update for both already. I assume that's still probably not as good as MobX, but in reality for 90% of most case is 90% as efficient. So that's one less point for MobX these days.

Anyway, just thought it might be useful to drop this information for you guys as it could be some good marketing opportunities for you.

Here's the original article on how MobX works:

https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254#.fgu8gpysi

Uncaught (in promise) TypeError: given schema is no Schema-object

Case

Bug.

Issue

I am getting the following error when using RxDB with electron, HOWEVER this is only happen when I build the app not when I run it in dev mode.

selection_002

Info

  • Environment: Electron
  • Adapter: (ndexedDB

Code

console.group('Initialize database.');
console.info('Creating user database.');
const database = await RxDB.create({
	name: 'moderator',
	adapter: 'idb'
});
console.info('Created user database.');

database.waitForLeadership().then(() => {
	console.info('leader.');
});

console.info('Creating collections.');
await Promise.all(collections.map(colData => database.collection(colData)));
console.info('Created collections.');

console.log('Start sync.');
collections.filter(col => col.sync).map(col => col.name).map(colName => database[colName].sync(url + colName + '/'));

console.groupEnd();

return database;

es5 and es6

ES6:

import * as RxDB from 'rxdb';
RxDB.create('heroesDB', 'websql', 'myLongAndStupidPassword', true) // create database
.then(db => db.collection('mycollection', mySchema)) // create collection
.then(collection => collection.insert({name: 'Bob'})) // insert document

ES5:

var RxDB = require('rxdb');
RxDB.create('heroesDB', 'websql', 'myLongAndStupidPassword', true) // create database
.then(function(db) {return db.collection('mycollection', mySchema);}) // create collection
.then(function(collection) {collection.insert({name: 'Bob'});}) // insert document

where i suppose to put this code ,

The babel-polyfill causes typescript build errors

The babel-polyfill causes build errors when used with Ionic2.

Error: Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.
	Most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.) in /path/to/my/project/node_modules/zone.js/dist/zone.js (line 42)

Adpater Idb not added

i want to user RxDb idb adapter in an ionic project but when i use this

import * as RxDB from 'rxdb';

RxDB.plugin(require('pouchdb-adapter-idb'))
RxDB.plugin(require('pouchdb-replication'))  //enable syncing
RxDB.plugin(require('pouchdb-adapter-http'))

After that i want to create the database by doing this
RxDB.create('nikoDb', 'idb', 'myLongAndStupidPassword', true) but then i get this error Adapter idb not added. Use RxDB.plugin(require('pouchdb-adapter-idb');
But i added the plugin. Do you know what i do wrong?

RxDB observers emit data when results are not affected

I tried RxDB with the localstorage adapter. If I create an observer for a query and subscribe and then edit a document which do not come under the query's result. The observer will emit the result data again. Is this something RxDB wishes to solve? If interested, I can start a pull-request for this.

Uncaught (in promise) Error: cannot populate because path has no ref (name)

Case

Bug

Issue

Receiving the following error when trying to add to retrieve collection:
selection_001

Info

  • Environment: Electron
  • Adapter: IndexedDB

Code

I have the following listing component in vue (derived from example code):

import * as Storage from '../storage';
import Banner from '../components/Banner';
import Preview from '../components/Preview';

export default {
    name: 'Listing',
    components: {
        Banner,
        Preview
    },
    data() {
        return {
            title: 'Please select Assignment',
            assignments: []
        };
    },
    mounted: async function() {
        const db = await Storage.get();
        let filter = [];
        filter.push(
            db.assignments
                .find().$
                .filter(x => x != null)
                .subscribe(assignments => {
                    console.log('results:');
                    this.assignments = assignments;
                })
        );
    },
    beforeDestroy() {
        this.assignments.forEach(sub => sub.unsubscribe());
    },
    methods: {
        // removeHero(hero) {
        //     hero.remove();
        // },
        // editHero(hero) {
        //     this.$emit('edit', hero);
        // }
    },
    template: require('./Listing.html')
}

Cannot sort on field(s) "|d,|c" when using the default index

Hello, i'm trying to sort by using more than one property but it's not working for me. It is working good when i'm only sorting by using one column whether it's name or just isPrimary property.

Step to reproduce the error:

The schema object:

{
    "title": "Print Setting Schema",
    "description": "Store print settings",
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "index": true
      },
      "isPrimary": {
        "type": "string",
        "index": true
      }
    }
}

The query code:

settingPrintCollection.find().sort({ name: 1, isPrimary: 1 }).exec();

//or

settingPrintCollection.find().sort('name').sort('isPrimary').exec();

Am i missing something?

Collection Sync

Could you provide me with clarification on collection sync.
In your implementation you have one database with multiple collections, these collections can sync with couch...

Now can I sync multiple collections with one server side couchdb? Is this what you are already doing? What if I have one collection that I want to sync, and one that I don't , is this possible?

Btw great library, excited to learn and use it.

Mike

event on remove document

Hi everyone,

While I am trying to remove a document from a collection, Rxdb don't emit any change.
Example :

var col;
RxDB.create('heroesDB', 'memory')      // create database
	.then(function (db) { return db.collection('mycollection', mySchema); }) // create collection
	.then(function (collection) {
		col = collection;
		collection
			.find()
			.$ // <- returns observable of query
			.subscribe(docs => {
				if (docs) {
					console.dir(docs); // change
				}
			});
		collection.insert({users: [{name: 'one'}, {name: 'two'}]});
		return collection;
	}).then((collection) => {
		collection.findOne({users: {$eq: [{name: 'one'}, {name: 'two'}]}}).exec()
			.then(documents => {
				if (documents) {
					console.log('remove');
					documents.remove();
				};
			});
		return collection;
	}).then((collection) => {
		setTimeout(function () {
			col.insert({users: [{name: 'three'}, {name: 'four'}]});
		}, 1000);
	});

output :

Array[1] // change
remove
Array[1] // change

I was expecting a change on remove, with a 0 lenght document.

Stay CouchDB-compliant

Currently, when creating a collection the following logic determines the name of the database:

database.prefix + ':RxDB:' + name

This causes a problem when trying to use RxDB with CouchDB, since both uppercase letters and colons are illegal characters for a CouchDB database name.

An example of my use case, when trying to connect to a CouchDB host:

RxDB.create('http://127.0.0.1:5984/db_name', 'http')
    .then(db => db.collection('col_name', schema))

Receives the following response:

{
  "error": "illegal_database_name",
  "reason": "Name: 'db_name:RxDB:col_name'. Only lowercase characters (a-z), digits (0-9), and any of the characters _, $, (, ), +, -, and / are allowed. Must begin with a letter."
}

The solution here is simple, we can change :RxDB: to -rxdb-, but this will probably cause much damage to those who are already using the library.

Or am I misusing the library? :)

Some ideas and suggestions

Case

Request

Issue

Currently everything is stored in one place and all issues are going to be logged against the main repo.

I think it would be a good idea to split the main repo, the docs, and the examples into 3 individual repo's and possibly create a public RxDB organisation.

I would also like to move the docs over to a dedicated documentation platform a couple of good options are:

Personally I would recommend Gitbook as it has been around a long time and matured really nicely, I would be happy to move the docs over I just want your thoughts before I start :).

Cheers.

Angular 2 cli build not able to integrate

So I have been trying to make the build work for the past 5 days I have spent more than 30 hours trying to figure what I am doing wrong there seems to be Nothing that works for I have the lastest Node and NPM installed. The example of angular2 does not work the preinstall command seems to go on and on downloading same packages over and over again.

I started a new project with ng new command I installed rxdb then made a service following the example of rxdb but I am getting this error in visual studio code webpack is failing to compile with the same error

ERROR in ./src/app/services/database.service.ts (28,62): Argument of type 'Promise<vo id>' is not assignable to parameter of type 'Promise<any>'. Property '[Symbol.toStringTag]' is missing in type 'Promise<void>'.)

if someone is able to make a git repo with the angular cli project and make this work using

npm install rxdb

that would be much helpful

Ionic App

how do you add a plugin to rxdb? because in ionic/angular you dont have access to require. what you use in al the examples? like you do here RxDB.plugin(require('rxdb-adapter-localstorage'));

Support for couch/pouch linked documents

Thanks for herding all those js packages into one coherent database solution!

Since rxdb is based on PouchDB, I'm wondering if it supports linked documents or any way to load referenced documents alongside their referrer. In other words, is there a support for any kind of Joins?

es6-proimise module causes typescript build errors

When using with Typescript, the "es6-promise" module causes build errors. For an example, when calling doc.save() we get this error.

[ts]
Type 'Promise<boolean>' is not assignable to type 'Promise<boolean>'. Two different types with this name exist, but they are unrelated.
  Types of property 'then' are incompatible.
    Type '{ <U>(onFulfilled?: (value: boolean) => U | Thenable<U>, onRejected?: (error: any) => U | Thenabl...' is not assignable to type '{ (onfulfilled?: (value: boolean) => boolean | PromiseLike<boolean>, onrejected?: (reason: any) =...'.
      Type 'Promise<any>' is not assignable to type 'Promise<boolean>'.
        Types of property 'then' are incompatible.
          Type '{ <U>(onFulfilled?: (value: any) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>...' is not assignable to type '{ (onfulfilled?: (value: boolean) => boolean | PromiseLike<boolean>, onrejected?: (reason: any) =...'.
            Type 'Promise<any>' is not assignable to type 'Promise<any>'. Two different types with this name exist, but they are unrelated.
              Property '[Symbol.toStringTag]' is missing in type 'Promise<any>'.

As a temporary solution, we can avoid the error with type assertions. I was wondering whether there's a better way to fix this.

Export database related classes

Hi,
Can you export RxDatabase, RxCollection, RxDocument, RxQuery and other classes so they can be extended. It'll also be useful when we need to create mocks for tests.

Does not allow full core spec of jsonSchema

Case

This is a bug.

Issue

I am trying to use the full features of Json Schema, but rxSchema does it's own checks and throws errors on a valid schema, because of the "fieldName"s.

Info

  • Environment: (browser)
  • Adapter: (IndexedDB)

Code

The schema looks like this (you can also see it in the JSON Schema Linter here):

{
  "title": "Transaction Schema",
  "version": 0,
  "description": "Structure of Transaction Data",
  "type": "object",
  "properties": {
    "date": {
      "type": "string",
      "format": "date-time"
    }
  },
  "patternProperties": {
    "^credit|debit$": {
      "type": "number",
      "multipleOf": 0.01
    }
  },
  "oneOf": [
    { "required": [ "date", "credit" ] },
    { "required": [ "date", "debit" ] }
  ],
  "additionalProperties": false
}

The problems arise with both the ^credit|debit$ property in the patternProperties object, but also within the oneOf property because it's an array, and the "fieldName" of 0 does not match the "valid regex".

I feel like you should be using a 3rd party library to validate the schema to avoid problems like this, unless you only allow part of the spec, which then you should specify that in the docs.

Thanks!

`isDeepEqual` does not work correctly for Arrays

Case

This is a Bug.

Issue

I was trying to update an array and save the document, but it was not saving.

The culprit is within the isDeepEqual function: https://github.com/pubkey/rxdb/blob/master/src/RxDocument.js#L324
The isDeepEqual function only works if the arrays are the same length, or the original array is longer then the new array. A simple way to fix this would be to add a check for the array lengths before comparing the items in the array.

Info

  • Environment: (browser)
  • Adapter: (IndexedDB)

Code

This repl.it will demonstrate the root of the problem: https://repl.it/GRHE/0

Here is a snippet of what I was trying to do

 const accounts = await db.accountsCollection.findOne().exec();
 accounts.set('data', accounts.data.concat(newAccount));
 accounts.save().then((saved) => console.log('saved? ', saved)); // -> saved? false
 const updatedCollection = await db.accountsCollection.dump(true);
 console.dir(updatedCollection); // hasn't changed

Several collections in one PouchDB

As I understand currently each collection resides in a separate PouchDB on the client. Does this imply that when syncing data, each collection needs an own replication connection to the central server?

If so, would it be possible to merge collections into one db? Prefixing _id's is how I currently do, and works like a charm.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.