react-native-couchbase-lite
Couchbase Lite binding for react-native on both iOS and Android. It works by exposing some functionality to the native Couchcase Lite and the remaining actions are peformed via the REST API.
Using rnpm
Create a new React Native project:
react-native init UntitledApp
cd UntitledApp
Install the React Native Couchbase Lite module:
npm install --save react-native-couchbase-lite
Link the module using rnpm:
rnpm link react-native-couchbase-lite
Follow the steps below to finish the installation.
iOS
- Download the Couchbase Lite iOS SDK from here and drag CouchbaseLite.framework, CouchbaseLiteListener.framework in the Xcode project:
Android
Add the following in android/app/build.gradle
under the android
section:
packagingOptions {
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
Install manually
iOS (react-native init)
$ react-init RNTestProj
$ cd RNTestProj
$ npm install react-native-couchbase-lite --save
- Drag the ReactCBLite Xcode project in your React Native Xcode project:
- Add ReactCBLite.a (from Workspace location) to the required Libraries and Frameworks.
-
From the Link Binary With Libraries
section in the Build Phases
of the top-level project, add the following frameworks in your Xcode project (Couchbase Lite dependencies):
- libsqlite3.0.tbd
- libz.tbd
- Security.framework
- CFNetwork.framework
- SystemConfiguration.framework
-
Download the Couchbase Lite iOS SDK from here and drag CouchbaseLite.framework, CouchbaseLiteListener.framework in the Xcode project:
iOS (Cocoapods)
- Install both npm modules:
$ npm install react-native
$ npm install react-native-couchbase-lite
- In the
Podfile
, add dependencies:
pod 'React', :path => './node_modules/react-native'
pod 'ReactNativeCouchbaseLite', :path => './node_modules/react-native-couchbase-lite'
- Install the Cocoapods dependencies:
$ pod install
- So far so good! Next, you must install CBLRegisterJSViewCompiler.h and libCBLJSViewCompiler.a. You can download both components from here. Drag CBLRegisterJSViewCompiler.h into the couchbase-lite-ios Pod:
- Add the libCBLJSViewCompiler.a static library:
Android
-
Add the react-native-couchbase-lite
project to your existing React Native project in android/settings.gradle
...
include ':react-native-couchbase-lite'
project(':react-native-couchbase-lite').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-couchbase-lite/android')
-
Add the Couchbase Maven repository to android/build.gradle
allprojects {
repositories {
mavenLocal()
jcenter()
// add couchbase url
maven {
url "http://files.couchbase.com/maven2/"
}
}
}
-
Add android/app/build.gradle
apply plugin: 'com.android.application'
android {
...
packagingOptions {
exclude 'META-INF/ASL2.0'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.facebook.react:react-native:0.12.+'
// Add this line:
compile project(':react-native-couchbase-lite')
}
-
Register the module in getPackages
of MainActivity.java
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactCBLiteManager() <----- Register the module
);
}
Usage
In your app entry, init and start the Couchbase Lite Listener
import {manager, ReactCBLite} from 'react-native-couchbase-lite'
ReactCBLite.init((url) => {
var database = new manager(url, 'myapp');
database.createDatabase()
.then(() => database.getAllDocuments())
.then(res => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(res.rows)
});
});
});
A username/password pair is automatically generated to protect access to the database endpoint.
See the example project for a more in-depth use case.
Examples
The full api is here
createDatabase
Example: Create a local Couchbase Lite database named 'dbname'
let localDbPort = 5984;
let localDbAppName = 'dbname';
let localDbUserId = 'local_user';
let localDbPassword = 'password';
let localDatabaseUrl = `http://${localDbUserId}:${localDbPassword}@localhost:${localDbPort}`;
this.database = new manager(localDatabaseUrl + "/", localDbAppName);
this.database.createDatabase()
.then((res) => {
if(res.status == 412) {
console.log('database already exists', res);
} else {
console.log('created database!', res);
}
}
deleteDatabase
this.database.deleteDatabase()
.then((res) => {
console.log('deleted database!', res);
}
createDocument(jsonDocument)
Example: Create a person document
this.database.createDocument({
type: 'person',
age: 26,
gender: 'female',
firstname: 'Linda',
lastname: 'McCartney'
}).then((res) => {
let documentId = res.id;
console.log("created document!", documentId);
});
getDocument(documentId, options)
Example: get specific revision of a document
var options = {rev: "1234"}
this.database.getDocument(documentId, options)
.then((personDocument) => {
let docId = personDocument._id;
let documentRevision = personDocument._rev;
console.log("Get document", docId, documentRevision, personDocument);
});
Example: get the latest revision of a document along with it's conflicts
var options = {conflicts: true}
this.database.getDocument(documentId, options)
.then((personDocument) => {
let docId = personDocument._id;
let documentRevision = personDocument._rev;
console.log("Get document", docId, documentRevision, personDocument);
});
updateDocument(jsonDocument, documentId, documentRevision)
Example: Update a person document, change the gender field
personDocument.gender = 'male';
this.database.updateDocument(personDocument, documentId, documentRevision)
then((res) => {
console.log("Updated document", res);
});
deleteDocument(documentId, documentRevision)
Example: delete a document revision
this.database.deleteDocument(documentId, documentRevision)
then((res) => {
console.log("Updated document", res);
});
modifyDocuments(jsonDocuments)
let docs = [docA, docB, docC];
this.database.modifyDocuments(docs)
then((res) => {
console.log("Updated documents", res);
});
getAllDocuments()
Example: just run the _all_docs query
this.database.getAllDocuments()
.then((res) => {
console.log("all-docs", res);
});
getChanges(options)
Example: request changes since the start of time, and subsequently only get changes since the last request
if(this.since) {
let options = {
since: this.since
};
}
let self = this;
this.database.getChanges(options)
.then((res) => {
self.since = res.last_seq;
res.results.forEach((row) => {
console.log(row);
});
}
createDesignDocument(name, views)
Example: create a design document called my_design_doc containing 2 views, one that indexes person documents by firstname and lastname and the other by age coupled with gender
let designDoc = {
"views": {
person_name_view: {
"map": function (doc) {
if(doc.type === 'person') {
emit(doc.firstname.toLowerCase(), null);
emit(doc.lastname.toLowerCase(), null);
}
}.toString()
},
person_age_view: {
"map": function (doc) {
if(doc.type === 'person') {
emit([doc.gender, doc.age], null);
}
}.toString(),
}
}
}
this.database.createDesignDocument('my_design_doc', designDocument)
.then((res) => {
console.log("created design doc", res);
});
getDesignDocument(name)
Example: this will return the views of the the design document called my_design_doc (created above)
this.database.getDesignDocument('my_design_doc')
then((res) => {
console.log("retreived a design document", res);
});
deleteDesignDocument(name, revision)
Example: this will delete revision 1 of the the design document called my_design_doc (created above)
let rev = 1;
this.database.getDesignDocument('my_design_doc', rev)
then((res) => {
console.log("deleted design document", res);
});
queryView(designDocumentName, viewName, queryStringParameters)
queryView is a wrapper for the Couchbase Lite REST interface as such it's parametes are more limited than the native QueryView. A full list of supported parameters can be found here:
http://developer.couchbase.com/documentation/mobile/1.2/develop/references/couchbase-lite/rest-api/design-document/get---db--design--design-doc--view--view-name-/index.html
Example: find all person documents who have a firstname or lastname field that match any of 'john', 'paul', 'ringo' or 'george'
let options = {
keys: ['john', 'paul', 'ringo', 'george']
};
this.database.queryView('my_design_doc', 'person_name_view', options)
then((res) => {
res.rows.forEach((row) => {
console.log("docId", row.id);
});
});
Example: find all person documents that have gender 'male' and age under 25
let options = {
descending: true,
startkey: ['male', 25],
endkey: ['male', {}]
};
this.database.queryView('my_design_doc', 'person_age_view', options)
then((res) => {
res.rows.forEach((row) => {
console.log("docId", row.id);
});
});
getAllDocumentConflicts()
this.database.getAllDocumentConflicts()
.then((res) => {
console.log('documents in conflict', res);
}
listen
Register for changes:
db.getInfo()
.then((res) => {
db.listen({since: res.update_seq - 1, feed: 'longpoll'});
});
Receiving change notifications:
db.changesEventEmitter.on('changes', function (e) {
console.log(e);
}.bind(this));
replicate(source, target, continuous)
Example: set continuous up bi-directional sync using a session cookie acquired from the sync gateway
let userId = 'user1';
let passowrd = 'password1';
let dbName = 'dbname';
let remoteDatabaseUrl = 'http://localhost:4984';
let remoteBucketName = 'sync_gateway_bucket';
let url = `${remoteDatabaseUrl}/${remoteBucketName}/_session`;
let self = this;
let settings = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: userId, password: password})
};
return fetch(url, settings)
.then((res) => {
switch (res.status) {
case 200: {
let sessionCookie = res.headers.map['set-cookie'][0];
this.database.replicate(
dbName,
{headers: {Cookie: sessionCookie}, url: remoteDbUrl},
true
);
this.database.replicate(
{headers: {Cookie: sessionCookie}, url: remoteDbUrl},
dbName,
true
);
}
default: {
console.log("Bad user", res);
}
}
});
Example: Save a thumbnail
image from the Internet on the movie
document given a URI or file path
var sourceUri = 'http://resizing.flixster.com/DeLpPTAwX3O2LszOpeaMHjbzuAw=/53x77/dkpu1ddg7pbsk.cloudfront.net/movie/11/16/47/11164719_ori.jpg';
database.createDocument({"_id": "movie"})
.then(doc => database.saveAttachment(doc.id, doc.rev, 'thumbnail', sourceUri, 'image/jpg'))
.then((res) => {
console.log(res);
});
getAttachmentUri(documentId, name, documentRevision)
Example: Get URI of attachment named thumbnail
on the movie
document
var uri = database.getAttachmentUri('movie', 'thumbnail', '2-c0cdd75b2b6871995a10eb3f8ce904d6');
console.log(uri);
makeRequest(method, url, queryStringParameters, data)
Can be used to make any query to the Couchbase lite rest api.
SwaggerJS (WIP)
SwaggerJS is a library that generates a JavaScript wrapper based on the Swagger Spec (http://docs.couchbasemobile.com/couchbase-lite). ReactNativeCouchbaseLiteExample/index.ios.js
uses SwaggerJS for
example. You can use the SwaggerJS library to perform all operations listed in the Swagger spec.
LICENSE
MIT