Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

@fedify/nestjs: Integrate Fedify with NestJS

npm Matrix Follow @fedify@hollo.social

Important

In a CommonJS-based NestJS project, this ESM-only module requires setting NODE_OPTIONS=--experimental-require-module at runtime

This package provides a simple way to integrate Fedify with NestJS.

The integration code looks like this:

// --- modules/federation/federation.service ---

import { Injectable, Inject, OnModuleInit } from '@nestjs/common';
import {
  FEDIFY_FEDERATION,
} from '@fedify/nestjs';
import { Federation } from '@fedify/fedify';

@Injectable()
export class FederationService implements OnModuleInit {
  private initialized = false;

  constructor(
    @Inject(FEDIFY_FEDERATION) private federation: Federation<unknown>,
  ) { }

  async onModuleInit() {
    if (!this.initialized) {
      await this.initialize();
      this.initialized = true;
    }
  }

  async initialize() {
    this.federation.setNodeInfoDispatcher(async (context) => {
      return {
        software: {
          name: "Fedify NestJS sample",
          version: "0.0.1"
        }
      }
    });
  }
}


// --- modules/federation/federation.module.ts ---

import { Module } from '@nestjs/common';
import { FederationService } from './federation.service';

@Module({
  providers: [FederationService],
  exports: [FederationService],
})
export class FederationModule {}


// --- main.module.ts ---
import {
  Inject,
  MiddlewareConsumer,
  Module,
  NestModule,
  RequestMethod,
} from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as express from 'express';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
import { FederationModule } from './modules/federation/federation.module';
import { InProcessMessageQueue, MemoryKvStore, Federation } from '@fedify/fedify';

import {
  FEDIFY_FEDERATION,
  FedifyModule,
  integrateFederation,
} from '@fedify/nestjs';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    DatabaseModule,
    FedifyModule.forRoot({
      kv: new MemoryKvStore(),
      queue: new InProcessMessageQueue(),
      origin: process.env.FEDERATION_ORIGIN || 'http://localhost:3000',
    }),
    FederationModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})

export class AppModule implements NestModule {
  constructor(
    @Inject(FEDIFY_FEDERATION) private federation: Federation<unknown>,
  ) { }

  configure(consumer: MiddlewareConsumer) {
    const fedifyMiddleware = integrateFederation(
      this.federation,
      async (req, res) => {
        return {
          request: req,
          response: res,
          url: new URL(req.url, `${req.protocol}://${req.get('host')}`),
        };
      },
    );

    // Fedify middleware requires the raw request body for HTTP signature verification
    // so we apply `express.raw()` before `fedifyMiddleware` to preserve the body.
    consumer.apply(
      express.raw({ type: '*/*' }),
      fedifyMiddleware,
    ).forRoutes({ path: '*', method: RequestMethod.ALL
  }
}