npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@garbados/pouchdb-mastodon

v1.0.1

Published

A plugin for PouchDB to interact with Mastodon.

Downloads

6

Readme

pouchdb-mastodon

Stability NPM Version JS Standard Style

A plugin for PouchDB that interacts with the Mastodon API.

Why?

When you build an application for the Fediverse, the first thing you have to do is authenticate with Oauth. This means saving some credentials, which means using a database. This plugin makes PouchDB that database, and provides a minimal API for requesting and storing data from an instance as well as for posting to it, as well as to make queries against it like "Show me all the posts in this timeline," or "Show me all the posts from this user."

The goal of this plugin is to make it easy to maintain copies of your Fediverse data and to make it easy to write your own Fediverse clients, without needing to operate an ActivityPub server. In fact, you can use pouchdb-mastodon in the browser to create offline-first serverless clients.

pouchdb-mastodon organizes data around the domain, assuming that one has only one account per domain. To get around this limitation, you can use a separate database for other accounts, and then replicate the two into a third. Clunky, I know. Patches welcome.

Install

Use NPM:

$ npm i -S @garbados/pouchdb-mastodon

Usage

This plugin adds the following methods to a PouchDB instance:

async auth(domain, name, scopes = 'read') -> Promise(<string>)

This method returns the URL a user must go to in order to retrieve the code used in the second step, .access. In a later version this will accept redirect URLs.

async access(domain, code, scopes = 'read') -> Promise(<null>)

Given an authentication code, acquires an access token and associates it with the given domain. Subsequent requests will utilize this access token in the Authorization header.

async setupMastodon() -> Promise(<null>)

Load the built-in design document, _design/queries.

async request(domain, url, body = null, headers = {}) -> Promise(<object>)

Make an authenticated request of domain at the full or partial url, optionally setting the request body to body and using any specified headers. An Authorization header is automatically set, as well as a JSON response type. Returns { body, headers, next, prev }.

  • body: The JSON contents of the response body.
  • headers: Response headers as an object.
  • next: A string URL indicating the next (earlier) page of results.
  • prev: A string URL indicating the prior (later) page of the results.

A common pattern is to feed next or prev back into db.request in order to page through a collection. An example of this can be found in examples/sync.js.

async mastoPost(domain, url, body, headers = {}) -> Promise(<object>)

Make a POST request, such as to post a status or an attachment. Returns the server response as from db.request.

const result = await this.db.mastoPost(DOMAIN, 'statuses', {
	status: 'hello world'
})
console.log(result.body.content)
>>> '<p>hello world</p>'

async postStatus(domain, body) -> Promise(<object>)

A shortcut method to posting a status, as per POST /api/v1/statuses. A similar shortcut for media is forthcoming.

async getAccount(domain) -> Promise(<object>)

Returns the account associated with the given domain. The returns object's item property is a Mastodon Account.

async downloadMastoCollection(domain, path, ...args) -> Promise(<object>)

Fetches a page from a collection of items and stores each item in the database with an _id of item.id, usually an integer of some kind. If this process encounters collisions it will be altered.

Usage, queries

This plugin adds a _design/queries design document during the execution of setupMastodon which PouchDB uses to index the information it downloads. You can query these indexes using db.query.

Many of these queries operate on the concept of a prop which is short for a boolean property named for the URL fragment used to download the item. If an item is found multiple times over multiple requests, each fragment used to find it will be flagged on the item as a prop.

So, if you db.downloadMastoCollection('toot.cat', 'timelines/home'), items found this way will have { 'timelines/home': true }.

props

Find or count objects sorted by key. For example:

const result = await db.query('queries/props', {
	key: 'timelines/home',
	reduce: false,
	include_docs: true
})
console.log(result)
>>> { "total_rows": 2, "offset": 1, "rows": [{...}] }
console.log(result.rows[0].doc)
>>> { "_id": "...", "_rev": "...", "timelines/home": true, item: {...} }

You can get a count of documents with a certain prop using the reduce function:

const result = await db.query('queries/props', {
	key: 'timelines/home'
})
console.log(result)
>>> { "rows": [{ key: null, value: 42069 }] }

This index is useful for retrieving lists of things that do not need to be otherwise sorted, such as blocks or followers.

propByTime

Find objects sorted by key and post time. For example:

const result = await db.query('queries/propByTime', {
	startkey: ['timelines/home'],
	endkey: ['timelines/home\uffff']
})

This gives you results like querying queries/props without a reduce function, but sorts the results from earliest to latest. To get the most recent posts instead, use descending=true:

const result = await db.query('queries/propByTime', {
	startkey: ['timelines/home\uffff'],
	endkey: ['timelines/home'],
	descending: true
})

This index is useful for information that should be sorted by time, such as timelines or moderation reports.

byAccount

Find items associated with an account by their URL, sorted by post time. You can use this to build up a history of someone's activities from your perspective, or to simply find someone's latest post.

const result = await db.query('queries/byAccount', {
	startkey: ['https://botsin.space/@animorphs'],
	endkey: ['https://botsin.space/@animorphs\uffff']
})

This retrieves all items associated with @[email protected] sorted by time, like propByTime.

Development

If you'd like to build with pouchdb-mastodon, I recommend you look at the examples/ folder. It contains scripts for syncing timelines, and determining a list of "mufos".

License

AGPL-3.0