AGENTS.md 6.5 KB

GROWI Slackbot Proxy (apps/slackbot-proxy)

A proxy service that enables Slack integration for GROWI instances, handling OAuth flows, event subscriptions, and message relay between Slack and GROWI.

Technology Stack

Component Technology
Framework Ts.ED 6.x (Express-based TypeScript framework)
Database MySQL with TypeORM 0.2.x
Slack SDK @slack/oauth, @slack/web-api
Views EJS templates
Health Checks @godaddy/terminus

Quick Reference

Essential Commands

# Development
pnpm run dev                        # Start dev server with nodemon

# Quality Checks
pnpm run lint:typecheck             # TypeScript type check
pnpm run lint:biome                 # Biome linter
pnpm run lint                       # Run all linters

# Build & Production
pnpm run build                      # Build for production
pnpm run start:prod                 # Start production server

Directory Structure

src/
├── index.ts                  # Application entry point
├── Server.ts                 # Ts.ED server configuration
├── entities/                 # TypeORM entities
│   ├── installation.ts       # Slack app installation data
│   ├── relation.ts           # GROWI-Slack relation mapping
│   ├── order.ts              # Command order tracking
│   └── system-information.ts # System metadata
├── repositories/             # TypeORM repositories
├── controllers/              # Ts.ED controllers
│   ├── slack.ts              # Slack event handlers
│   ├── growi-to-slack.ts     # GROWI → Slack message relay
│   ├── top.ts                # Landing page
│   ├── term.ts               # Terms of service
│   └── privacy.ts            # Privacy policy
├── services/                 # Business logic
│   ├── InstallerService.ts   # Slack app installation
│   ├── RegisterService.ts    # GROWI registration
│   ├── RelationsService.ts   # GROWI-Slack relations
│   └── growi-uri-injector/   # URI injection for Slack messages
├── middlewares/              # Express middlewares
│   ├── slack-to-growi/       # Slack → GROWI direction
│   └── growi-to-slack/       # GROWI → Slack direction
├── interfaces/               # TypeScript interfaces
├── filters/                  # Error filters
├── config/                   # Configuration files
│   ├── logger/               # Logging configuration
│   └── swagger/              # Swagger configuration
└── views/                    # EJS templates

Architecture

Message Flow

┌─────────┐     ┌────────────────┐     ┌───────┐
│  Slack  │ ←→  │ Slackbot Proxy │ ←→  │ GROWI │
└─────────┘     └────────────────┘     └───────┘
  1. Slack → GROWI: Slack events/commands are received, validated, and forwarded to registered GROWI instances
  2. GROWI → Slack: GROWI sends notifications/responses through the proxy to Slack

Key Entities

Entity Description
Installation Slack app installation data (tokens, team info)
Relation Maps GROWI instances to Slack workspaces
Order Tracks command execution order
SystemInformation System metadata

Development Guidelines

1. Ts.ED Controller Pattern

import { Controller, Post, Req, Res } from '@tsed/common';
import { SlackEventMiddleware } from '../middlewares/slack-to-growi/authorizer';

@Controller('/slack')
export class SlackController {
  @Post('/events')
  @UseBefore(SlackEventMiddleware)
  async handleEvent(@Req() req: Request, @Res() res: Response) {
    // Handle Slack event
  }
}

2. TypeORM Entity Pattern

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()
export class Installation {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  teamId: string;

  @Column()
  botToken: string;
}

3. Middleware Pattern (Bidirectional)

Middlewares are organized by direction:

  • middlewares/slack-to-growi/ - Process incoming Slack events
  • middlewares/growi-to-slack/ - Process outgoing messages to Slack

    // middlewares/slack-to-growi/authorizer.ts
    import { Middleware, Req, Next } from '@tsed/common';
    
    @Middleware()
    export class AuthorizerMiddleware {
    use(@Req() req: Request, @Next() next: () => void) {
    // Validate Slack signature
    next();
    }
    }
    

API Endpoints

Slack Events

Method Endpoint Description
POST /slack/events Slack event subscription endpoint
POST /slack/interactions Slack interactive components
GET /slack/oauth/callback OAuth callback

GROWI Integration

Method Endpoint Description
POST /g2s/* GROWI to Slack relay

Web Pages

Method Endpoint Description
GET / Landing page
GET /term Terms of service
GET /privacy Privacy policy

Environment Variables

Variable Description
PORT Server port
DATABASE_URL MySQL connection string
SLACK_CLIENT_ID Slack app client ID
SLACK_CLIENT_SECRET Slack app client secret
SLACK_SIGNING_SECRET Slack signing secret

Database Configuration

TypeORM is configured with MySQL. Entity synchronization should be disabled in production.

// In Server.ts
@Configuration({
  typeorm: {
    connections: {
      default: {
        type: 'mysql',
        url: process.env.DATABASE_URL,
        entities: [Installation, Relation, Order, SystemInformation],
        synchronize: process.env.NODE_ENV !== 'production',
      },
    },
  },
})

Before Committing

pnpm run lint:typecheck   # Type check
pnpm run lint:biome       # Lint
pnpm run build            # Verify build

Integration with GROWI

GROWI instances register with the proxy using the @growi/slack package:

// In apps/app
import { SlackIntegration } from '@growi/slack';

const slack = new SlackIntegration({
  proxyUrl: 'https://slackbot-proxy.example.com',
});

This service is deployed separately and requires its own MySQL database. It acts as a central hub for multiple GROWI instances to communicate with Slack.