ejmvar / localbase

A Firebase-Style Database ... Offline!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Localbase

A Firebase-Style Database ... Offline!

Localbase gives you an offline database with the simplicity & power of Firebase, all stored in the user's browser (in an IndexedDB database).

You can create as many databases as you like.

Databases are organised into Collections and Documents (just like Firebase Cloud Firestore).

  • Databases contain Collections (e.g. users)
  • Collections contain Documents (e.g. { id: 1, name: 'Bill', age: 47 }

Localbase is built on top of LocalForage.

Contents

Getting Started

Installation & Initialisation

With a Script Tag

<script src="https://unpkg.com/localbase/dist/localbase.dev.js"></script>

<script>
  let db = new Localbase('db')
</script>

Or, use the minified, production version:

<script src="https://unpkg.com/localbase/dist/localbase.min.js"></script>

<script>
  let db = new Localbase('db')
</script>

With NPM

npm install localbase --save
import Localbase from 'localbase'

let db = new Localbase('db')

With NuxtJS

npm install localbase
// plugins/localbase.js

import Localbase from 'localbase'
let db = new Localbase('db')
export default (context,inject) => {
  inject('db', db)
}
// nuxt.config.js

export default {
  ...
  plugins: [
    { src: "~/plugins/localbase", mode: "client" }
  ],
  ...
}
<!-- pages/index.vue -->

<script>
export default {
  head: {
    title: 'Nuxt Blog - Home'
  },
  mounted() {
    this.$db.collection('users').add({
      id: 1,
      name: 'Bill',
      age: 47
    })
  }
}
</script>

Video Introduction

Watch my Video Introduction to Localbase, including how to get started:

Quick Start

Get started by adding a document to a collection. Just specify the collection name with the collection method (the collection will be created automatically) then specify the document you want to add with the add method:

db.collection('users').add({
  id: 1,
  name: 'Bill',
  age: 47
})

Simples!

Once you've added some data to a collection, you can get the whole collection with the get method:

db.collection('users').get().then(users => {
  console.log(users)
})

//  [
//    { id: 1, name: 'Bill', age: 47 },
//    { id: 2, name: 'Paul', age: 34 }
//  ]

Adding Data

Add a document to a collection

Add a new document to a collection.

db.collection('users').add({
  id: 1,
  name: 'Bill',
  age: 47
})

Update a document

Update an existing document. Just pass an object with a field and value (usually id) to match the document. Then pass in only the fields you want to update with the update method.

db.collection('users').doc({ id: 1 }).update({
  name: 'William'
})

//  [
//    { id: 1, name: 'William', age: 47 },
//    { id: 2, name: 'Paul', age: 34 }
//  ]

Note: if more than one document is matched by your criteria e.g .doc({ gender: 'male' }) then all matched documents will be updated.

Set a document (overwrite)

Overwrite an existing document. This will completely overwrite the selected document, so all required fields should be passed into the set method.

db.collection('users').doc({ id: 2 }).set({
  id: 4, 
  name: 'Pauline',
  age: 27
})

//  [
//    { id: 1, name: 'William', age: 47 },
//    { id: 4, name: 'Pauline', age: 27 }
//  ]

Note: if more than one document is matched by your criteria e.g .doc({ gender: 'male' }) then all matched documents will be overwritten.

Set a collection (overwrite)

Overwrite an entire collection with an array of documents. This will completely overwrite the selected collection.

db.collection('users')
  .set([
    {
      id: 1,
      name: 'Bill',
      age: 48
    },
    {
      id: 2, 
      name: 'Paul',
      age: 28
    }
  ])

//  [
//    { id: 1, name: 'Bill', age: 48 },
//    { id: 2, name: 'Paul', age: 28 }
//  ]

Getting Data

Get a collection

Get all items from a collection. The collection will be returned in an array.

db.collection('users').get().then(users => {
  console.log(users)
})

//  [
//    { id: 1, name: 'Bill', age: 47 },
//    { id: 2, name: 'Paul', age: 34 }
//  ]

Order a collection

Get a collection and order it by a particular field (ascending).

db.collection('users').orderBy('age').get().then(users => {
  console.log('users: ', users)
})

//  [
//    { id: 2, name: 'Paul', age: 34 },
//    { id: 1, name: 'Bill', age: 47 }
//  ]

Get a collection and order it by a particular field (descending).

db.collection('users').orderBy('name', 'desc').get().then(users => {
  console.log('users: ', users)
})

//  [
//    { id: 2, name: 'Paul', age: 34 },
//    { id: 1, name: 'Bill', age: 47 }
//  ]

Limit a collection

Order a collection & limit it to a particular number of documents.

db.collection('users').orderBy('name', 'desc').limit(1).get().then(users => {
  console.log('users: ', users)
})

//  [
//    { id: 2, name: 'Paul', age: 34 }
//  ]

Get a document

Get an individual document from a collection

db.collection('users').doc({ id: 1 }).get().then(document => {
  console.log(document)
})

// { id: 1, name: 'Bill', age: 47 }

Deleting Data

Delete a document

Delete a document from a collection.

db.collection('users').doc({ id: 1 }).delete()

//  [
//    { id: 2, name: 'Paul', age: 34 }
//  ]

Note: if more than one document is matched by your criteria e.g .doc({ gender: 'male' }) then all matched documents will be deleted.

Delete a collection

Delete a collection and all documents contained in it.

db.collection('users').delete()

Delete a database

Delete a database and all collections contained in it.

db.delete()

Advanced Usage with Keys

Your documents are stored in an IndexedDB store with keys:

IndexedDB Store - Keys

By default, Localbase generates random, ordered, unique IDs for these keys.

But you might want to take control of these keys. For example, you might want to:

  • Specify your own key when you add a document
  • Use the key for selecting a document (when getting, updating, setting or deleting a document) instead of using some document criteria
  • Return all of the keys as well as the document fields, when getting a collection, e.g.
[
  {
    key: 'mykey-2',
    data: {
      { id: 2, name: 'Paul', age: 34 }
    }
  },
  {
    key: 'mykey-1',
    data: {
      { id: 1, name: 'Bill', age: 47 }
    }
  }
]

You can do all this with Localbase:

Add a document & specify your own key

After specifying your document data, pass in a key (to be used by the IndexedDB store) as a second parameter:

db.collection('users').add({
  id: 1,
  name: 'Bill',
  age: 47
}, 'mykey-1')

Or, you can just use the set method:

db.collection('users').doc('mykey-1').set({
  id: 1, 
  name: 'Bill',
  age: 47
})

Which would look like this in the IndexedDB:

IndexedDB Store - Own Keys

Set a collection (overwrite) including keys

Overwrite an entire collection with an array of documents, and specify a key for each document. Make sure you pass in the { keys: true } option. This will completely overwrite the selected collection.

db.collection('users')
  .set([
    {
      id: 1,
      name: 'Bill',
      age: 48,
      _key: 'mykey-1'
    },
    {
      id: 2, 
      name: 'Paul',
      age: 28,
      _key: 'mykey-2'
    }
  ], { keys: true })

Get, Update, Set or Delete a Document by key (instead of by document criteria)

When selecting a document with the doc method, instead of passing in an object with a field name and value, just pass in a string (or integer) with your key:

// get document by key
db.collection('users').doc('mykey-1').get().then(document => {
  console.log(document)
})

// update document by key
db.collection('users').doc('mykey-1').update({
  name: 'William'
})

// set document by key
db.collection('users').doc('mykey-2').set({
  id: 4, 
  name: 'Pauline',
  age: 27
})

// delete a document by key
db.collection('users').doc('mykey-1').delete()

Get a Collection and return the keys along with the data.

When getting a collection, just pass { keys: true } into the get method:

db.collection('users').orderBy('name', 'desc').get({ keys: true }).then(users => {
  console.log('users: ', users)
})

//  [
//    {
//      key: 'mykey-2',
//      data: {
//        { id: 2, name: 'Paul', age: 34 }
//      }
//    },
//    {
//      key: 'mykey-1',
//      data: {
//        { id: 1, name: 'Bill', age: 47 }
//      }
//    }
//  ]

Promises

You can add promises to all operations and do something when it's successful, or when there's an error.

Add Document then do something

db.collection('users')
  .add({
    id: 1,
    name: 'Bill',
    age: 47
  }, 'mykey-1')
  .then(response => {
    console.log('Add successful, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else.')
  })

// you can test the error by passing a 
// string, number or boolean into the 
// .add() method, instead of an object

Update Document then do something

db.collection('users')
  .doc({ id: 1 })
  .update({
    name: 'William'
  })
  .then(response => {
    console.log('Update successful, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else.')
  })
  
// you can test the error by passing nothing
// into the update() method

Set Document then do something

db.collection('users')
  .doc({ id: 1 })
  .set({
    id: 1, 
    name: 'Pauline',
    age: 27
  })
  .then(response => {
    console.log('Set successful, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else.')
  })

// you can test the error by passing nothing
// into the set() method

Delete Document then do something

db.collection('users')
  .doc({ id: 1 })
  .delete()
  .then(response => {
    console.log('Delete successful, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else.')
  })

  // you can test the error by passing nothing
  // into the doc() method

Delete Collection then do something

db.collection('users')
  .delete()
  .then(response => {
    console.log('Collection deleted, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else')
  })
  
// you can test the error by passing nothing
// into the collection() method

Delete Database then do something

db.delete()
  .then(response => {
    console.log('Database deleted, now do something.')
  })
  .catch(error => {
    console.log('There was an error, do something else.')
  })
  
// note: sometimes when you delete a
// database, the change won't show up
// in Chrome Dev tools til you reload
// the page

Async / Await

You can also use Async / Await with all operations

Add Documents (with Async Await)

async function addUsers() {
  await db.collection('users').add({
    id: 1,
    name: 'Bill',
    age: 47
  })
  console.log('first user added')
  await db.collection('users').add({
    id: 2,
    name: 'Paul',
    age: 34
  })
  console.log('second user added')
}
addUsers()

Update Document (with Async Await)

async function updateUser() {
  let result = await db.collection('users')
    .doc({ id: 1 })
    .update({
      name: 'William'
    })
  console.log(result)
}
updateUser()

Set Document (with Async Await)

async function setUser() {
  let result = await db.collection('users')
    .doc({ id: 2 })
    .set({
      id: 4, 
      name: 'Pauline',
      age: 27
    })
    console.log(result)
}
setUser()

Get Collection & Catch Errors (with Async Await)

async function getUsers() {
  try {
    let users = await db.collection('users')
      .orderBy('age')
      .get()
    console.log('users: ', users)
  }
  catch(error) {
    console.log('error: ', error)
  }
}
getUsers()

// test the error by passing nothing into collection()

Configuration

Disable the Gorgeous Logs

By default, when in development, Localbase will fire out gorgeously labelled debug logs like this:

Gorgeous, Labelled Logs

You can disable these logs by setting db.config.debug to false.

It's best to do this after you initialize the database, and before you do anything else:

import Localbase from 'localbase'
let db = new Localbase('db')

db.config.debug = false

// now do some stuff with the motherflipping db yo

Localbase Playground

Localbase Playground is an app for playing around with Localbase and all the available methods.

It contains a bunch of different code snippets (for adding, updating, setting and getting) data to/from a Localbase database.

You can launch these code snippets (and edit them if you like) in the browser and observe the result in the IndexedDB database and in the console.

IndexedDB Store - Own Keys

Localbase Playground and launch instructions

About

A Firebase-Style Database ... Offline!


Languages

Language:JavaScript 100.0%