An attempt to build a spec-compliant ActivityPub core library.
Go to file
Michael Puckett cd604527c6 return instead of error in replyto create sideffect 2023-01-10 12:07:17 -05:00
packages return instead of error in replyto create sideffect 2023-01-10 12:07:17 -05:00
.env Rework activitypub-core-types src 2022-10-11 08:26:07 -04:00
.gitignore Remove lerna-debug 2022-10-24 11:28:50 -04:00
CHECKLIST.md update checklist 2022-10-26 19:20:32 -04:00
CONTRIBUTING.md -- 2022-11-27 09:28:53 -05:00
LICENSE fix sharedInbox 2022-10-14 21:47:00 -04:00
README.md readme 2022-11-29 15:18:25 -05:00
TODO.md TODO 2023-01-05 10:11:16 -05:00
lerna.json v0.1.6 2023-01-10 09:54:05 -05:00
package-lock.json v0.1.6 2023-01-10 09:54:05 -05:00
package.json add eslint 2022-10-14 22:32:58 -04:00

README.md

activitypub-core

This is a Lerna monorepo that holds packages related to an implementation of the ActivityPub protocol specification.

ActivityPub is a standardized method of exchanging social data.

Current Status

This project is still incomplete at the moment. Much of the core functionality is complete, but refer to:

Running in a Project

Canonical example using Express, MongoDB, Firebase Auth, JSX:

(async () => {
  const app = express();

  // Firebase Authentication adapter.
  const firebaseServiceAccount: ServiceAccount = JSON.parse(decodeURIComponent(process.env.AP_SERVICE_ACCOUNT));
  const firebaseAuthAdapter =
    new FirebaseAuthAdapter(
      firebaseServiceAccount,
      'firebase-project-id'
    );

  // Mongo DB adapter.
  const mongoClient = new MongoClient(process.env.AP_MONGO_CLIENT_URL);
  await mongoClient.connect();
  const mongoDb = mongoClient.db(process.env.AP_MONGO_DB_NAME);
  const mongoDbAdapter = new MongoDbAdapter(mongoDb);

  // Server-to-Server Delivery adapter.
  const defaultDeliveryAdapter =
    new DeliveryAdapter({
      adapters: {
        db: mongoDbAdapter,
      },
    });

  // FTP Storage adapter.
  const ftpStorageAdapter =
    new FtpStorageAdapter(
      JSON.parse(decodeURIComponent(process.env.AP_FTP_CONFIG)),
      '/uploads'
    );

  const renderLoginPage = async () => {
    return `
      <!doctype html>
      ${renderToString(
        <LoginPage />
      )}`;
  };

  const renderHomePage = async ({ actor }) => {
    return `
      <!doctype html>
      ${renderToString(
        <DashboardPage actor={actor} />
      )}
    `;
  };

  const renderEntityPage = async ({ entity, actor }) => {
    return `
      <!doctype html>
      ${renderToString(
        <EntityPage
          entity={entity}
          actor={actor}
        />
      )}
    `;
  };

  app.use(
    activityPub({
      pages: {
        login: renderLoginPage,
        home: renderHomePage,
        entity: renderEntityPage,
      },

      adapters: {
        auth: firebaseAuthAdapter,
        db: mongoDbAdapter,
        delivery: defaultDeliveryAdapter,
        storage: ftpStorageAdapter,
      }
    }),
  );

  app.get('/', (req: IncomingMessage, res: ServerResponse) => {
    const indexPage = `
      <!doctype html>
      ${renderToString(
        <IndexPage />
      )}
    `;

    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/html')
    res.write(indexPage);
    res.end();
  });

  app.listen(process.env.PORT ?? 3000, () => {
    console.log('Running...');
  });
})();

General Philosophy

This project aims to be spec-compliant.

This project aims to be an non-opinionated as possible, providing abstracted layers that can hopefully work with any Node.js project.

This project is MIT-licensed, with the hope it will be forked, reused, or wholly included in other projects due to this permissive license. There may be similiar software that exists, but inclusion would be inviable due to licensing restrictions.

Use Cases

There are a few use cases this project attempts to fulfill. Ideally this project papers over some of the complexity of JSON-LD, Activity Streams collections, etc. to make getting started easy.

Connecting a Blog to the Fediverse

Someone already has an HTML blog and a domain name and wants their posts to be read by others and get replies. Instead of setting up a CMS, they decide to set up an ActivityPub server.

Single-Server Social Feeds

An exercise app wants to build in social features to make their users feel proud of their achievements. This would probably include something like a notification bell and a feed where updates about their friends appear. Users might have with the option to react with an emoji or sticker.

All these exchanges would stay local to the server.

Private Group Chat

A small group of people who communicate online become dissatisfied with their existing app's policies and decide to communicate privately. They would like to develop their own system for communication.

Although ActivityPub does not define an encryption layer, messages could stay local to a single server or could be exchanged between all parties in an ephermeral way. Encryption could be a good addition, however.

Federated Social Network

Ideally this project could be used to build an entire social network that interfaces with the rest of the Fediverse.

Architecture

This project aims to be agnostic as to how the data is stored, which server is used, etc. Adapters that conform to a specific interface can be mixed and matched.

Additionally, plugins can modify the endpoints.

Logic Layer

The logic layer that get included in all projects include these packages:

  • activitypub-core-types
    • The Activity vocabularies converted to TypeScript types.
  • activitypub-core-endpoints
    • The logic for carrying out the bulk of the ActivityPub protocol.
  • activitypub-core-delivery
    • The logic specific to the Server-to-Server delivery (federation).
  • activitypub-core-utilities
    • Common functions with no dependencies on packages from upper layers.

Adapaters

Database Adapaters

There is a large amount of data related to profiles and interactions that must be persisted over time.

Currently this project comes with:

  • activitypub-core-db-mongo
  • TODO: SQLite, PostreSQL

Authentication Adapters

Users can sign up and log in to their account.

Current this project comes with:

  • activitypub-core-auth-firebase
  • TODO: Passport.js

Storage Adapters

Allows for users to upload media, such as profile pictures or attachments.

Currently this project comes with:

  • activitypub-core-storage-ftp
  • TODO: AWS S3, Firebase Storage

Server Adapters

The server must handle the core endpoint requests.

Currently this project comes with:

  • activitypub-core-server-express
  • TODO: Fastify, Next.js

Plugins

In progress.

Injectables that can modify core functionality.

Currently this project comes with:

  • activitypub-core-plugin-foaf

Client/Rendering Layer

TBD. Currently using JSX (React) server-side.