Skip to content

Commit b5d7739

Browse files
sij411claude
andcommitted
Add Relay interface and make implementation classes internal
- Add public Relay interface with fetch(), listFollowers(), getFollower() - Update BaseRelay to implement Relay interface (marked @internal) - Change createRelay() return type from BaseRelay to Relay - Remove MastodonRelay and LitePubRelay exports from mod.ts - Update README to document interface-based API 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent a3cbb0e commit b5d7739

File tree

5 files changed

+47
-27
lines changed

5 files changed

+47
-27
lines changed

packages/relay/README.md

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -263,19 +263,19 @@ Factory function to create a relay instance.
263263
function createRelay(
264264
type: "mastodon" | "litepub",
265265
options: RelayOptions
266-
): BaseRelay
266+
): Relay
267267
~~~~
268268

269269
**Parameters:**
270270

271271
- `type`: The type of relay to create (`"mastodon"` or `"litepub"`)
272272
- `options`: Configuration options for the relay
273273

274-
**Returns:** A relay instance (`MastodonRelay` or `LitePubRelay`)
274+
**Returns:** A `Relay` instance
275275

276-
### `BaseRelay`
276+
### `Relay`
277277

278-
Abstract base class for relay implementations.
278+
Public interface for ActivityPub relay implementations.
279279

280280
#### Methods
281281

@@ -285,21 +285,14 @@ Abstract base class for relay implementations.
285285
- `getFollower(actorId: string): Promise<RelayFollower | null>`: Gets
286286
a specific follower by actor ID
287287

288-
### `MastodonRelay`
288+
#### Relay types
289289

290-
A Mastodon-compatible ActivityPub relay implementation that extends `BaseRelay`.
290+
The relay type is specified when calling `createRelay()`:
291291

292-
- Uses direct activity forwarding
293-
- Immediate subscription approval
294-
- Compatible with standard ActivityPub implementations
295-
296-
### `LitePubRelay`
297-
298-
A LitePub-compatible ActivityPub relay implementation that extends `BaseRelay`.
299-
300-
- Uses bidirectional following
301-
- Activities wrapped in `Announce`
302-
- Two-phase subscription (pendingaccepted)
292+
- `"mastodon"`: Mastodon-compatible relay using direct activity forwarding,
293+
immediate subscription approval, and LD signatures
294+
- `"litepub"`: LitePub-compatible relay using bidirectional following,
295+
activities wrapped in `Announce`, and two-phase subscription
303296

304297
### `RelayOptions`
305298

packages/relay/src/base.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Federation, FederationBuilder } from "@fedify/fedify";
22
import { isActor, Object as APObject } from "@fedify/fedify/vocab";
33
import {
44
isRelayFollowerData,
5+
type Relay,
56
type RelayFollower,
67
type RelayOptions,
78
} from "./types.ts";
@@ -10,9 +11,9 @@ import {
1011
* Abstract base class for relay implementations.
1112
* Provides common infrastructure for both Mastodon and LitePub relays.
1213
*
13-
* @since 2.0.0
14+
* @internal
1415
*/
15-
export abstract class BaseRelay {
16+
export abstract class BaseRelay implements Relay {
1617
protected federationBuilder: FederationBuilder<RelayOptions>;
1718
protected options: RelayOptions;
1819
protected federation?: Federation<RelayOptions>;
@@ -49,14 +50,11 @@ export abstract class BaseRelay {
4950
actorId: string,
5051
data: unknown,
5152
): Promise<RelayFollower | null> {
52-
// Validate storage format
5353
if (!isRelayFollowerData(data)) return null;
5454

55-
// Deserialize and validate actor
5655
const actor = await APObject.fromJsonLd(data.actor);
5756
if (!isActor(actor)) return null;
5857

59-
// Construct and return RelayFollower
6058
return {
6159
actorId,
6260
actor,

packages/relay/src/factory.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import type { BaseRelay } from "./base.ts";
21
import { relayBuilder } from "./builder.ts";
32
import { LitePubRelay } from "./litepub.ts";
43
import { MastodonRelay } from "./mastodon.ts";
5-
import type { RelayOptions, RelayType } from "./types.ts";
4+
import type { Relay, RelayOptions, RelayType } from "./types.ts";
65

76
/**
87
* Factory function to create a relay instance.
@@ -28,7 +27,7 @@ import type { RelayOptions, RelayType } from "./types.ts";
2827
export function createRelay(
2928
type: RelayType,
3029
options: RelayOptions,
31-
): BaseRelay {
30+
): Relay {
3231
switch (type) {
3332
case "mastodon":
3433
return new MastodonRelay(options, relayBuilder);

packages/relay/src/mod.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
* @module
99
*/
1010
export { createRelay } from "./factory.ts";
11-
export { LitePubRelay } from "./litepub.ts";
12-
export { MastodonRelay } from "./mastodon.ts";
1311
export {
12+
type Relay,
1413
RELAY_SERVER_ACTOR,
1514
type RelayFollower,
1615
type RelayOptions,

packages/relay/src/types.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,37 @@ export interface RelayFollower {
6262
readonly state: "pending" | "accepted";
6363
}
6464

65+
/**
66+
* Public interface for ActivityPub relay implementations.
67+
* Use {@link createRelay} to create a relay instance.
68+
*
69+
* @since 2.0.0
70+
*/
71+
export interface Relay {
72+
/**
73+
* Handle incoming HTTP requests.
74+
*
75+
* @param request The incoming HTTP request
76+
* @returns The HTTP response
77+
*/
78+
fetch(request: Request): Promise<Response>;
79+
80+
/**
81+
* Lists all followers of the relay.
82+
*
83+
* @returns An async iterator of follower entries
84+
*/
85+
listFollowers(): AsyncIterableIterator<RelayFollower>;
86+
87+
/**
88+
* Gets a specific follower by actor ID.
89+
*
90+
* @param actorId The actor ID (URL) of the follower to retrieve
91+
* @returns The follower entry if found, null otherwise
92+
*/
93+
getFollower(actorId: string): Promise<RelayFollower | null>;
94+
}
95+
6596
/**
6697
* Type predicate to check if a value is valid RelayFollowerData from KV store.
6798
* Validates the storage format (JSON-LD), not the deserialized Actor instance.

0 commit comments

Comments
 (0)