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.
Or you can provide your own username/password pair:
ReactCBLite.initWithAuth('admin', 'pass', (url) => {
var database = new manager(url, 'myapp');
});
CouchbaseLite iOS has a custom NSURLProtocol that is accessible even after moving the app to the background. It's also more secure as this internal URL is only accessible inside the application's process.
ReactCBLite.initWithAuth('admin', 'pass', (url) => {
console.log("couchbase lite started at", url);
if(Platform.OS === 'ios') {
url = "http://lite.couchbase./";
console.log("Using couchbase lite internal url", url);
}
var database = new manager(url, 'myapp');
});
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);
});
getDocuments()
Example: runs the _all_docs query
this.database.getDocuments({include_docs: false})
.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, options)
Valid options listed here: http://developer.couchbase.com/documentation/mobile/1.2/develop/references/couchbase-lite/rest-api/server/post-replicate/index.html
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},
{continuous: true}
);
this.database.replicate(
{headers: {Cookie: sessionCookie}, url: remoteDbUrl},
dbName,
{continuous: 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