Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@
"@opentelemetry/core": "npm:@opentelemetry/core@^2.5.0",
"@opentelemetry/sdk-trace-base": "npm:@opentelemetry/sdk-trace-base@^2.5.0",
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.39.0",
"@optique/config": "jsr:@optique/config@^0.10.7",
"@optique/core": "jsr:@optique/core@^0.10.7",
"@optique/run": "jsr:@optique/run@^0.10.7",
"@optique/config": "jsr:@optique/config@^1.0.0",
"@optique/core": "jsr:@optique/core@^1.0.0",
"@optique/run": "jsr:@optique/run@^1.0.0",
"@std/assert": "jsr:@std/assert@^1.0.13",
"@std/async": "jsr:@std/async@^1.0.13",
"@std/encoding": "jsr:@std/encoding@^1.0.10",
Expand Down
63 changes: 48 additions & 15 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 7 additions & 94 deletions packages/cli/src/inbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,18 @@ import {
type Recipient,
} from "@fedify/vocab";
import { getLogger } from "@logtape/logtape";
import { bindConfig } from "@optique/config";
import {
command,
constant,
group,
type InferValue,
merge,
message,
multiple,
object,
option,
string,
} from "@optique/core";
import type { InferValue } from "@optique/core";
import Table from "cli-table3";
import { type Context as HonoContext, Hono } from "hono";
import type { BlankEnv, BlankInput } from "hono/types";
import process from "node:process";
import ora from "ora";
import metadata from "../deno.json" with { type: "json" };
import { configContext } from "./config.ts";
import { getDocumentLoader } from "./docloader.ts";
import type { ActivityEntry } from "./inbox/entry.ts";
import { ActivityEntryPage, ActivityListPage } from "./inbox/view.tsx";
import { configureLogging, recordingSink } from "./log.ts";
import { createTunnelOption, type GlobalOptions } from "./options.ts";
import type { GlobalOptions } from "./options.ts";
import { tableStyle } from "./table.ts";
import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts";
import { colors, matchesActor } from "./utils.ts";
Expand All @@ -66,92 +53,18 @@ interface ContextData {

const logger = getLogger(["fedify", "cli", "inbox"]);

export const inboxCommand = command(
"inbox",
merge(
object("Inbox options", {
command: constant("inbox"),
follow: bindConfig(
multiple(
option("-f", "--follow", string({ metavar: "URI" }), {
description:
message`Follow the given actor. The argument can be either an actor URI or a handle. Can be specified multiple times.`,
}),
),
{
context: configContext,
key: (config) => config.inbox?.follow ?? [],
default: [],
},
),
acceptFollow: bindConfig(
multiple(
option("-a", "--accept-follow", string({ metavar: "URI" }), {
description:
message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.`,
}),
),
{
context: configContext,
key: (config) => config.inbox?.acceptFollow ?? [],
default: [],
},
),
actorName: bindConfig(
option("--actor-name", string({ metavar: "NAME" }), {
description: message`Customize the actor display name.`,
}),
{
context: configContext,
key: (config) => config.inbox?.actorName ?? "Fedify Ephemeral Inbox",
default: "Fedify Ephemeral Inbox",
},
),
actorSummary: bindConfig(
option("--actor-summary", string({ metavar: "SUMMARY" }), {
description: message`Customize the actor description.`,
}),
{
context: configContext,
key: (config) =>
config.inbox?.actorSummary ??
"An ephemeral ActivityPub inbox for testing purposes.",
default: "An ephemeral ActivityPub inbox for testing purposes.",
},
),
authorizedFetch: bindConfig(
option(
"-A",
"--authorized-fetch",
{
description:
message`Enable authorized fetch mode. Incoming requests without valid HTTP signatures will be rejected with 401 Unauthorized.`,
},
),
{
context: configContext,
key: (config) => config.inbox?.authorizedFetch ?? false,
default: false,
},
),
}),
group("Tunnel options", createTunnelOption("inbox")),
),
{
brief: message`Run an ephemeral ActivityPub inbox server.`,
description:
message`Spins up an ephemeral server that serves the ActivityPub inbox with an one-time actor, through a short-lived public DNS with HTTPS. You can monitor the incoming activities in real-time.`,
},
);

// Module-level state
const activities: ActivityEntry[] = [];
const acceptFollows: string[] = [];
const peers: Record<string, Actor> = {};
const followers: Record<string, Actor> = {};

type InboxCommand =
& InferValue<typeof import("./inbox/command.ts").inboxCommand>
& GlobalOptions;

export async function runInbox(
command: InferValue<typeof inboxCommand> & GlobalOptions,
command: InboxCommand,
) {
// Reset module-level state for a clean run
activities.length = 0;
Expand Down
97 changes: 97 additions & 0 deletions packages/cli/src/inbox/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { bindConfig } from "@optique/config";
import {
command,
constant,
group,
merge,
message,
multiple,
object,
option,
string,
} from "@optique/core";
import { configContext } from "../config.ts";
import { createTunnelOption } from "../options.ts";

const DEFAULT_EPHEMERAL_INBOX_NAME = "Fedify Ephemeral Inbox";
const DEFAULT_EPHEMERAL_INBOX_SUMMARY =
"An ephemeral ActivityPub inbox for testing purposes.";

export const inboxCommand = command(
"inbox",
merge(
object("Inbox options", {
command: constant("inbox"),
follow: bindConfig(
multiple(
option("-f", "--follow", string({ metavar: "URI" }), {
description:
message`Follow the given actor. The argument can be either an actor URI or a handle. Can be specified multiple times.`,
}),
),
{
context: configContext,
key: (config) => config.inbox?.follow ?? [],
default: [],
},
),
acceptFollow: bindConfig(
multiple(
option("-a", "--accept-follow", string({ metavar: "URI" }), {
description:
message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.`,
}),
),
{
context: configContext,
key: (config) => config.inbox?.acceptFollow ?? [],
default: [],
},
),
actorName: bindConfig(
option("--actor-name", string({ metavar: "NAME" }), {
description: message`Customize the actor display name.`,
}),
{
context: configContext,
key: (config) =>
config.inbox?.actorName ?? DEFAULT_EPHEMERAL_INBOX_NAME,
default: DEFAULT_EPHEMERAL_INBOX_NAME,
},
),
actorSummary: bindConfig(
option("--actor-summary", string({ metavar: "SUMMARY" }), {
description: message`Customize the actor description.`,
}),
{
context: configContext,
key: (config) =>
config.inbox?.actorSummary ??
DEFAULT_EPHEMERAL_INBOX_SUMMARY,
default: DEFAULT_EPHEMERAL_INBOX_SUMMARY,
},
),
authorizedFetch: bindConfig(
option(
"-A",
"--authorized-fetch",
{
description:
message`Enable authorized fetch mode. Incoming requests without valid HTTP signatures will be rejected with 401 Unauthorized.`,
},
),
{
context: configContext,
key: (config) => config.inbox?.authorizedFetch ?? false,
default: false,
},
),
}),
group("Tunnel options", createTunnelOption("inbox")),
),
{
brief: message`Run an ephemeral ActivityPub inbox server.`,
description:
message`Spins up an ephemeral server that serves the ActivityPub inbox with a one-time actor, through a short-lived public DNS with HTTPS. You can monitor the incoming activities in real-time.`,
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
);
Loading
Loading