Accessing the Local Database

There are two databases in local and on remote and they sync via HTTP(S). The Inkdrop client app is built on top of a PouchDB for storing data in local and syncing with the remote database. For many parts of the application, the database is the source of truth. Data is written to the local database first, then synced with the remote database, and changes to the database trigger Actions, Stores and components to refresh their contents. The illustration below shows this flow of data:

Data flow

There is a class called InkdropDatabase which wraps PouchDB and provides a bunch of useful methods that help you access the local database for managing notes, notebooks, tags and images.

For example, below code gets data directly from the local database:

const db = inkdrop.main.dataStore.getLocalDB()

// Get a note data by note ID
const note = await db.notes.get("note:F8xUp-23G")

// Get all notebooks
const books = await db.books.all()

// Get notes in a notebook
const notesInBook = await db.notes.findInBook(books[0]._id)

// Search notes with keywords
const result = await db.utils.search("Foobar")
const { docs } = result
console.log("Search result:", docs)
NOTE: Returned objects from the database represent Remote Objects.

Accessing the PouchDB instance (Advanced)

There is a global variables named inkdrop which allows you to access the internal objects of Inkdrop. It has main property, which is a reference to the inkdrop instance in the main process. To access the local PouchDB instance in the main process:

async function getDatabaseInfo() {
  const db = inkdrop.main.dataStore.localPouch
  const info = await db.info()
  console.log(info.db_name)
}

In this code, localPouch is the instance of PouchDB. Be careful, you could break your database by accessing it with PouchDB since its API does not protect you from breaking it. Use it only if InkdropDatabase does not provide what you would do.

NOTE: Returned objects from the database represent Remote Objects.

Accessing via HTTP (Advanced)

Local REST API endpoint

The Inkdrop client app can open a simple HTTP server so that you can access the data from an external program easily, which gives you a flexible ability to import/export your notes.

You can configure the HTTP server settings by editing config.cson in the user data directory.

Quit Inkdrop, then edit it like so:

"*":
  core:
    server:
      enabled: true
      port: 19840
      bindAddress: "127.0.0.1"
      auth:
        username: "foo"
        password: "bar"

Now, launch the app.

Configurations

  • core.server.enabled - Specify true to enable the HTTP server. Default is false.
  • core.server.port - Defines the port number to listen. Default is 19840.
  • core.server.bindAddress - Defines the IP address to listen. Default is 127.0.0.1.
  • core.server.auth.{username,password} - Defines Basic auth credentials.

API reference

GET /

Accessing the root of a HTTP server returns meta information about the app.

GET /notes

Returns a list of all the Notes in the local database.

Query parameters

All parameters are optional.

  • keyword (string) – The search keyword to filter notes. You can use the same qualifiers for searching notes.
  • limit (number) – Limit the number of the returned documents to the specified number.
  • skip (number) – Skip this number of documents before starting to return the results. Default is 0.
  • sort (string) – Sort the documents by the specified field. One of: 'updatedAt' | 'createdAt' | 'title'.
  • descending (boolean) - Reverse the order of the output documents.
Example

Request:

GET /notes/?limit=1 HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

[
  {
    "doctype": "markdown",
    "bookId": "book:tjnPbJakw",
    "createdAt": 1589165355584,
    "updatedAt": 1592532006000,
    "status": "active",
    "share": "private",
    "numOfTasks": 0,
    "numOfCheckedTasks": 0,
    "pinned": true,
    "title": "hello",
    "body": "example note",
    "tags": ["tag:HyBgJ94gx", "tag:h11OMPbSs"],
    "_id": "note:BKzzd8iGK",
    "_rev": "19-d882f96ee27f7b9f71f6183b0cab9193"
  }
]

POST /notes

The POST method creates a new Note document, or creates a new revision of the existing document. The document ID _id is optional and will be automatically generated.

Response JSON Object
  • id (string) – Document ID
  • ok (boolean) – Operation status
  • rev (string) – Revision MVCC token
Example

Request:

POST /notes/ HTTP/1.1
Host: localhost:19840
Content-Type: application/json
Authorization: Basic Zm9vOmJhcg==

{
  "doctype": "markdown",
  "bookId": "book:tjnPbJakw",
  "status": "active",
  "share": "private",
  "title": "hello",
  "body": "example note",
  "tags": ["tag:HyBgJ94gx", "tag:h11OMPbSs"]
}

Response:

{
  "ok": true,
  "id": "note:BKzzd8iGK",
  "rev": "1-d882f96ee27f7b9f71f6183b0cab9193"
}

GET /books

Returns a list of all the Books in the local database.

Query parameters
  • limit (number) – Limit the number of the returned documents to the specified number.
  • skip (number) – Skip this number of documents before starting to return the results. Default is 0.
Example

Request:

GET /books HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

[
  {
    "parentBookId": "book:Bk5Ivk0T",
    "updatedAt": 1598593031080,
    "createdAt": 1598593007103,
    "name": "Desktop app",
    "_id": "book:0cFae6lCc",
    "_rev": "2-7f29bee428d16b6f5a05ece8abf7f571"
  },
  ...
]

POST /books

The POST method creates a new Book document, or creates a new revision of the existing document. The document ID _id is optional and will be automatically generated.

Response JSON Object
  • id (string) – Document ID
  • ok (boolean) – Operation status
  • rev (string) – Revision MVCC token
Example

Request:

POST /books/ HTTP/1.1
Host: localhost:19840
Content-Type: application/json
Authorization: Basic Zm9vOmJhcg==

{
  "name": "New notebook"
}

Response:

{
  "ok": true,
  "id": "book:Bk5Ivk0T",
  "rev": "1-7f29bee428d16b6f5a05ece8abf7f571"
}

GET /tags

Returns a list of all the Tags in the local database.

Query parameters
  • limit (number) – Limit the number of the returned documents to the specified number.
  • skip (number) – Skip this number of documents before starting to return the results. Default is 0.
Example

Request:

GET /tags HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

[
  {
    "count": 4,
    "color": "orange",
    "createdAt": 1489212448648,
    "updatedAt": 1607068381327,
    "name": "Lifehack",
    "_id": "tag:h11OMPbSs",
    "_rev": "3-bceb5835af6be6ae277762a877b884d1"
  },
  ...
]

POST /tags

The POST method creates a new Tag document, or creates a new revision of the existing document. The document ID _id is optional and will be automatically generated.

Response JSON Object
  • id (string) – Document ID
  • ok (boolean) – Operation status
  • rev (string) – Revision MVCC token
Example

Request:

POST /tags/ HTTP/1.1
Host: localhost:19840
Content-Type: application/json
Authorization: Basic Zm9vOmJhcg==

{
  "color": "red",
  "name": "Important"
}

Response:

{
  "ok": true,
  "id": "tag:HyBgJ94gx",
  "rev": "1-e5ad1c150a30e1ad5a781755466b19a1"
}

GET /files

Returns a list of all the Files in the local database.

Query parameters
  • limit (number) – Limit the number of the returned documents to the specified number.
  • skip (number) – Skip this number of documents before starting to return the results. Default is 0.
Example

Request:

GET /files?limit=1 HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

[
  {
    "name": "dog.png",
    "createdAt": 1613887605720,
    "contentType": "image/png",
    "contentLength": 10389,
    "publicIn": [],
    "_attachments": {
      "index": {
        "digest": "md5-if+yj7slT2E8u2JG7ee3yw==",
        "content_type": "image/png",
        "revpos": 5,
        "data": "iVBORw0K...AElFTkSuQmCC"
      }
    },
    "_id": "file:-dKJeWShi",
    "_rev": "5-541c58ffdbec966840709683c658c7dc"
  }
]

POST /files

The POST method creates a new File document, or creates a new revision of the existing document. The document ID _id is optional and will be automatically generated.

Response JSON Object
  • id (string) – Document ID
  • ok (boolean) – Operation status
  • rev (string) – Revision MVCC token
Example

Request:

POST /tags/ HTTP/1.1
Host: localhost:19840
Content-Type: application/json
Authorization: Basic Zm9vOmJhcg==

{
  "name": "dog.png",
  "contentType": "image/png",
  "contentLength": 10389,
  "publicIn": [],
  "_attachments": {
    "index": {
      "content_type": "image/png",
      "data": "iVBORw0K...AElFTkSuQmCC"
    }
  }
}

Response:

{
  "ok": true,
  "id": "file:HyBgJ94gx",
  "rev": "1-e5ad1c150a30e1ad5a781755466b19a1"
}

GET /{docid}

Returns document by the specified docid of Note, Book, Tag, or File.

Query parameters

All parameters are optional.

  • rev (string) – Fetch specific revision of a document. Defailts to the latest revision.
  • attachments (boolean) – Include attachment data. It should be true if you fetch a content of the file document.
Example

Request:

GET /note:BKzzd8iGK HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

{
  "doctype": "markdown",
  "bookId": "book:tjnPbJakw",
  "createdAt": 1589165355584,
  "updatedAt": 1592532006000,
  "status": "active",
  "share": "private",
  "numOfTasks": 0,
  "numOfCheckedTasks": 0,
  "pinned": true,
  "title": "hello",
  "body": "example note",
  "tags": ["tag:HyBgJ94gx", "tag:h11OMPbSs"],
  "_id": "note:BKzzd8iGK",
  "_rev": "19-d882f96ee27f7b9f71f6183b0cab9193"
}

DELETE /{docid}

Deletes document by the specified docid of Note, Book, Tag, or File.

Example

Request:

DELETE /note:BKzzd8iGK HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

{
  "ok": true,
  "id": "note:BKzzd8iGK",
  "rev": "2-e5ad1c150a30e1ad5a781755466b19a1"
}

GET /_changes

Returns a list of changes made to documents in the database, in the order they were made.

Query parameters
  • descending (boolean) - Reverse the order of the output documents.
  • since (number) - Start the results from the change immediately after the given sequence number.
  • limit (number) - Limit the number of results to this number.
  • include_docs (boolean) - Include the associated document with each change. Default is true.
  • conflicts (boolean) - Include conflicts.
  • attachments (boolean) - Include attachments.
Example

Request:

GET /_changes?limit=1&since=306 HTTP/1.1
Host: localhost:19840
Authorization: Basic Zm9vOmJhcg==

Response:

{
  "results": [
    {
      "id": "note:BkS41x0T",
      "changes": [
        {
          "rev": "2-4cd3d27dbda7cbd98cf8474970353460"
        }
      ],
      "doc": {
        "doctype": "markdown",
        "updatedAt": 1475375009783,
        "createdAt": 1475374892611,
        "bookId": "book:Bk5Ivk0T:HJu6tyRT",
        "status": "none",
        "migratedBy": "migrateAddingNumOfTasks",
        "numOfTasks": 0,
        "numOfCheckedTasks": 0,
        "title": "code diff",
        "body": "```\nhello\n```",
        "tags": [],
        "_id": "note:BkS41x0T",
        "_rev": "2-4cd3d27dbda7cbd98cf8474970353460"
      },
      "seq": 307
    }
  ],
  "last_seq": 307
}

Example response when a doc was deleted:

{
  "results": [
    {
      "id": "note:coPJ4TB7u",
      "changes": [
        {
          "rev": "3-2396b4e8542389a6c464826fba8b9ef2"
        }
      ],
      "doc": {
        "_id": "note:coPJ4TB7u",
        "_rev": "3-2396b4e8542389a6c464826fba8b9ef2",
        "_deleted": true
      },
      "deleted": true,
      "seq": 200
    }
  ],
  "last_seq": 200
}

seq and last_seq correspond to the overall sequence number of the entire database, and it’s what is passed in when using since. It is the primary key for the changes feed, and is also used as a checkpointer by the replication algorithm. Note that live option is not supported.

Can you help us improve these docs?

The source of these docs is here on GitHub. If you see a way these docs can be improved, please fork us!