@fedify/cli 2.3.0-dev.1336 → 2.3.0-dev.1344
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bench/action.js +2 -2
- package/dist/bench/command.js +6 -4
- package/dist/bench/compare.js +2 -2
- package/dist/bench/mod.js +1 -1
- package/dist/bench/result/build.js +1 -1
- package/dist/cache.js +1 -1
- package/dist/commands.js +110 -0
- package/dist/config.js +1 -1
- package/dist/deno.js +1 -1
- package/dist/docloader.js +1 -1
- package/dist/generate-vocab/action.js +1 -1
- package/dist/generate-vocab/command.js +5 -3
- package/dist/imagerenderer.js +2 -2
- package/dist/inbox/command.js +6 -4
- package/dist/inbox.js +4 -4
- package/dist/log.js +2 -2
- package/dist/lookup/command.js +121 -0
- package/dist/lookup.js +12 -123
- package/dist/mod.js +2 -22
- package/dist/nodeinfo.js +11 -9
- package/dist/options.js +1 -1
- package/dist/relay/command.js +6 -4
- package/dist/relay.js +2 -2
- package/dist/runner.js +68 -45
- package/dist/tempserver.js +1 -1
- package/dist/tunnel.js +6 -4
- package/dist/utils.js +4 -4
- package/dist/webfinger/action.js +1 -1
- package/dist/webfinger/command.js +6 -4
- package/dist/webfinger/lib.js +1 -1
- package/package.json +13 -12
- package/dist/generate-vocab/mod.js +0 -4
- package/dist/init/mod.js +0 -3
- package/dist/webfinger/mod.js +0 -4
package/dist/bench/action.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { getContextLoader, getDocumentLoader } from "../docloader.js";
|
|
3
2
|
import { describeError } from "../utils.js";
|
|
3
|
+
import { getContextLoader, getDocumentLoader } from "../docloader.js";
|
|
4
4
|
import { buildFleet } from "./actor/fleet.js";
|
|
5
5
|
import { convertUrlIfHandle } from "../webfinger/lib.js";
|
|
6
6
|
import { discoverInbox, selectInbox } from "./discovery/discover.js";
|
|
@@ -16,8 +16,8 @@ import { UnsafeTargetError, assertInboxDestinationAllowed, assertTargetAllowed,
|
|
|
16
16
|
import { classifyResolvedTarget } from "./safety/tiers.js";
|
|
17
17
|
import { resolveAdvertiseHost, spawnSyntheticServer } from "./server/synthetic.js";
|
|
18
18
|
import { runnerFor } from "./scenarios/registry.js";
|
|
19
|
-
import { writeFile } from "node:fs/promises";
|
|
20
19
|
import process from "node:process";
|
|
20
|
+
import { writeFile } from "node:fs/promises";
|
|
21
21
|
//#region src/bench/action.ts
|
|
22
22
|
/**
|
|
23
23
|
* Runs the `fedify bench` command: load and validate the suite, gate the
|
package/dist/bench/command.js
CHANGED
|
@@ -34,7 +34,7 @@ sending load.` }), false),
|
|
|
34
34
|
advertiseHost: advertiseHostOption,
|
|
35
35
|
allowUnsafeTarget
|
|
36
36
|
}), userAgentOption);
|
|
37
|
-
const
|
|
37
|
+
const benchOptions = or(command("compare", merge("Compare options", object({
|
|
38
38
|
command: constant("bench"),
|
|
39
39
|
mode: constant("compare"),
|
|
40
40
|
base: option("--base", string({ metavar: "REF" }), { description: message`The base git ref to benchmark.` }),
|
|
@@ -56,7 +56,8 @@ checked-out worktree.` }),
|
|
|
56
56
|
description: message`Run the same benchmark suite against two git revisions on the \
|
|
57
57
|
same runner, then fail when the head revision regresses beyond the configured \
|
|
58
58
|
tolerance and measured noise band.`
|
|
59
|
-
}), runParser)
|
|
59
|
+
}), runParser);
|
|
60
|
+
const benchMetadata = {
|
|
60
61
|
brief: message`Benchmark a Fedify federation workload.`,
|
|
61
62
|
description: message`Run an ActivityPub-specific load benchmark against a \
|
|
62
63
|
cooperative Fedify target running in benchmark mode.
|
|
@@ -65,6 +66,7 @@ The suite file declares the target, actors, and scenarios. This version \
|
|
|
65
66
|
executes the \`inbox\`, \`webfinger\`, \`actor\`, \`object\`, \`fanout\`, \
|
|
66
67
|
\`failure\`, and \`mixed\` scenario types; \`collection\` remains reserved by \
|
|
67
68
|
the suite format.`
|
|
68
|
-
}
|
|
69
|
+
};
|
|
70
|
+
command("bench", benchOptions, benchMetadata);
|
|
69
71
|
//#endregion
|
|
70
|
-
export {
|
|
72
|
+
export { benchMetadata, benchOptions };
|
package/dist/bench/compare.js
CHANGED
|
@@ -4,11 +4,11 @@ import { metricUnit } from "./result/expect/metrics.js";
|
|
|
4
4
|
import { parseDuration } from "./scenario/units.js";
|
|
5
5
|
import runBench from "./action.js";
|
|
6
6
|
import { COMPARE_REPORT_SCHEMA_ID } from "./compare/schema.js";
|
|
7
|
-
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
8
7
|
import process from "node:process";
|
|
9
|
-
import { spawn } from "node:child_process";
|
|
10
8
|
import { tmpdir } from "node:os";
|
|
11
9
|
import { join } from "node:path";
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
12
12
|
//#region src/bench/compare.ts
|
|
13
13
|
const ZERO_BASE_LATENCY_ALLOWANCE_MS = 1;
|
|
14
14
|
/** Runs `fedify bench compare`. */
|
package/dist/bench/mod.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
+
import "./command.js";
|
|
2
3
|
import runBench$1 from "./action.js";
|
|
3
4
|
import { runBenchCompare } from "./compare.js";
|
|
4
|
-
import "./command.js";
|
|
5
5
|
//#region src/bench/mod.ts
|
|
6
6
|
/** Runs a parsed benchmark command. */
|
|
7
7
|
function runBench(command) {
|
|
@@ -3,8 +3,8 @@ import { version } from "../../deno.js";
|
|
|
3
3
|
import { evaluateExpect } from "./expect/evaluate.js";
|
|
4
4
|
import { REPORT_SCHEMA_ID } from "./schema.js";
|
|
5
5
|
import process from "node:process";
|
|
6
|
-
import { createHash } from "node:crypto";
|
|
7
6
|
import { cpus } from "node:os";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
8
|
//#region src/bench/result/build.ts
|
|
9
9
|
/**
|
|
10
10
|
* Assembly of the canonical benchmark report from measured scenario data.
|
package/dist/cache.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { mkdir } from "node:fs/promises";
|
|
3
2
|
import process from "node:process";
|
|
4
3
|
import { homedir } from "node:os";
|
|
5
4
|
import { join } from "node:path";
|
|
5
|
+
import { mkdir } from "node:fs/promises";
|
|
6
6
|
//#region src/cache.ts
|
|
7
7
|
/**
|
|
8
8
|
* Returns the default cache directory path.
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import { benchMetadata, benchOptions } from "./bench/command.js";
|
|
3
|
+
import { generateVocabMetadata, generateVocabOptions } from "./generate-vocab/command.js";
|
|
4
|
+
import { inboxMetadata, inboxOptions } from "./inbox/command.js";
|
|
5
|
+
import { lookupMetadata, lookupOptions } from "./lookup/command.js";
|
|
6
|
+
import { nodeInfoMetadata, nodeInfoOptions, runNodeInfo } from "./nodeinfo.js";
|
|
7
|
+
import { relayMetadata, relayOptions } from "./relay/command.js";
|
|
8
|
+
import { runTunnel, tunnelMetadata, tunnelOptions } from "./tunnel.js";
|
|
9
|
+
import { webFingerMetadata, webFingerOptions } from "./webfinger/command.js";
|
|
10
|
+
import { constant, merge, message, object, optionNames } from "@optique/core";
|
|
11
|
+
import { initOptions, runInit } from "@fedify/init";
|
|
12
|
+
import { defineCommand } from "@optique/discover";
|
|
13
|
+
//#region src/commands.ts
|
|
14
|
+
function defineCliCommand(command) {
|
|
15
|
+
const { run, ...definition } = command;
|
|
16
|
+
return {
|
|
17
|
+
...defineCommand({
|
|
18
|
+
...definition,
|
|
19
|
+
handler: (_value) => {}
|
|
20
|
+
}),
|
|
21
|
+
run
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const generatingCommands = [defineCliCommand({
|
|
25
|
+
path: ["init"],
|
|
26
|
+
parser: merge(initOptions, object({ command: constant("init") })),
|
|
27
|
+
metadata: {
|
|
28
|
+
brief: message`Initialize a new Fedify project directory.`,
|
|
29
|
+
description: message`Initialize a new Fedify project directory.
|
|
30
|
+
|
|
31
|
+
By default, it initializes the current directory. You can specify a different directory as an argument.
|
|
32
|
+
|
|
33
|
+
Unless you specify all options (${optionNames(["-w", "--web-framework"])}, ${optionNames(["-p", "--package-manager"])}, ${optionNames(["-k", "--kv-store"])}, and ${optionNames(["-m", "--message-queue"])}), it will prompt you to select the options interactively.`
|
|
34
|
+
},
|
|
35
|
+
run: runInit
|
|
36
|
+
}), defineCliCommand({
|
|
37
|
+
path: ["generate-vocab"],
|
|
38
|
+
parser: generateVocabOptions,
|
|
39
|
+
metadata: generateVocabMetadata,
|
|
40
|
+
run: async (value) => {
|
|
41
|
+
const { default: runGenerateVocab } = await import("./generate-vocab/action.js");
|
|
42
|
+
return await runGenerateVocab(value);
|
|
43
|
+
}
|
|
44
|
+
})];
|
|
45
|
+
const activityPubCommands = [
|
|
46
|
+
defineCliCommand({
|
|
47
|
+
path: ["webfinger"],
|
|
48
|
+
parser: webFingerOptions,
|
|
49
|
+
metadata: webFingerMetadata,
|
|
50
|
+
run: async (value) => {
|
|
51
|
+
const { default: runWebFinger } = await import("./webfinger/action.js");
|
|
52
|
+
return await runWebFinger(value);
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
defineCliCommand({
|
|
56
|
+
path: ["lookup"],
|
|
57
|
+
parser: lookupOptions,
|
|
58
|
+
metadata: lookupMetadata,
|
|
59
|
+
run: async (value) => {
|
|
60
|
+
const { runLookup } = await import("./lookup.js");
|
|
61
|
+
return await runLookup(value);
|
|
62
|
+
}
|
|
63
|
+
}),
|
|
64
|
+
defineCliCommand({
|
|
65
|
+
path: ["inbox"],
|
|
66
|
+
parser: inboxOptions,
|
|
67
|
+
metadata: inboxMetadata,
|
|
68
|
+
run: async (value) => {
|
|
69
|
+
const { runInbox } = await import("./inbox.js");
|
|
70
|
+
return await runInbox(value);
|
|
71
|
+
}
|
|
72
|
+
}),
|
|
73
|
+
defineCliCommand({
|
|
74
|
+
path: ["nodeinfo"],
|
|
75
|
+
parser: nodeInfoOptions,
|
|
76
|
+
metadata: nodeInfoMetadata,
|
|
77
|
+
run: runNodeInfo
|
|
78
|
+
}),
|
|
79
|
+
defineCliCommand({
|
|
80
|
+
path: ["relay"],
|
|
81
|
+
parser: relayOptions,
|
|
82
|
+
metadata: relayMetadata,
|
|
83
|
+
run: async (value) => {
|
|
84
|
+
const { runRelay } = await import("./relay.js");
|
|
85
|
+
return await runRelay(value);
|
|
86
|
+
}
|
|
87
|
+
}),
|
|
88
|
+
defineCliCommand({
|
|
89
|
+
path: ["bench"],
|
|
90
|
+
parser: benchOptions,
|
|
91
|
+
metadata: benchMetadata,
|
|
92
|
+
run: async (value) => {
|
|
93
|
+
const { runBench } = await import("./bench/mod.js");
|
|
94
|
+
return await runBench(value);
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
];
|
|
98
|
+
const networkCommands = [defineCliCommand({
|
|
99
|
+
path: ["tunnel"],
|
|
100
|
+
parser: tunnelOptions,
|
|
101
|
+
metadata: tunnelMetadata,
|
|
102
|
+
run: runTunnel
|
|
103
|
+
})];
|
|
104
|
+
[
|
|
105
|
+
...generatingCommands,
|
|
106
|
+
...activityPubCommands,
|
|
107
|
+
...networkCommands
|
|
108
|
+
];
|
|
109
|
+
//#endregion
|
|
110
|
+
export { activityPubCommands, generatingCommands, networkCommands };
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import { message } from "@optique/core";
|
|
3
3
|
import { printError } from "@optique/run";
|
|
4
|
-
import { createConfigContext } from "@optique/config";
|
|
5
4
|
import { readFileSync } from "node:fs";
|
|
6
5
|
import { parse } from "smol-toml";
|
|
6
|
+
import { createConfigContext } from "@optique/config";
|
|
7
7
|
import { array, boolean, check, forward, integer as integer$1, minValue, number, object as object$1, optional as optional$1, picklist, pipe, string as string$1 } from "valibot";
|
|
8
8
|
//#region src/config.ts
|
|
9
9
|
/**
|
package/dist/deno.js
CHANGED
package/dist/docloader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { kvCache } from "@fedify/fedify";
|
|
3
2
|
import { getDocumentLoader } from "@fedify/vocab-runtime";
|
|
3
|
+
import { kvCache } from "@fedify/fedify";
|
|
4
4
|
import { getKvStore } from "#kv";
|
|
5
5
|
//#region src/docloader.ts
|
|
6
6
|
const documentLoaders = {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { stat } from "node:fs/promises";
|
|
3
2
|
import process from "node:process";
|
|
4
3
|
import { printError } from "@optique/run";
|
|
4
|
+
import { stat } from "node:fs/promises";
|
|
5
5
|
import { generateVocab } from "@fedify/vocab-tools";
|
|
6
6
|
import { message } from "@optique/core/message";
|
|
7
7
|
//#region src/generate-vocab/action.ts
|
|
@@ -12,10 +12,12 @@ const generatedPath = argument(path({
|
|
|
12
12
|
type: "file",
|
|
13
13
|
allowCreate: true
|
|
14
14
|
}), { description: message`Path to output the generated vocabulary classes. Should end with ${".ts"} suffix.` });
|
|
15
|
-
const
|
|
15
|
+
const generateVocabOptions = object("Generation options", {
|
|
16
16
|
command: constant("generate-vocab"),
|
|
17
17
|
schemaDir,
|
|
18
18
|
generatedPath
|
|
19
|
-
})
|
|
19
|
+
});
|
|
20
|
+
const generateVocabMetadata = { description: message`Generate vocabulary classes from schema files.` };
|
|
21
|
+
command("generate-vocab", generateVocabOptions, generateVocabMetadata);
|
|
20
22
|
//#endregion
|
|
21
|
-
export {
|
|
23
|
+
export { generateVocabMetadata, generateVocabOptions };
|
package/dist/imagerenderer.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import { Jimp } from "./nodeinfo.js";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
3
|
import process from "node:process";
|
|
5
|
-
import { validatePublicUrl } from "@fedify/vocab-runtime";
|
|
6
4
|
import os from "node:os";
|
|
7
5
|
import path from "node:path";
|
|
6
|
+
import { validatePublicUrl } from "@fedify/vocab-runtime";
|
|
7
|
+
import fs from "node:fs/promises";
|
|
8
8
|
import { encodeBase64 } from "byte-encodings/base64";
|
|
9
9
|
//#region src/imagerenderer.ts
|
|
10
10
|
const KITTY_IDENTIFIERS = [
|
package/dist/inbox/command.js
CHANGED
|
@@ -6,7 +6,7 @@ import { bindConfig } from "@optique/config";
|
|
|
6
6
|
//#region src/inbox/command.ts
|
|
7
7
|
const DEFAULT_EPHEMERAL_INBOX_NAME = "Fedify Ephemeral Inbox";
|
|
8
8
|
const DEFAULT_EPHEMERAL_INBOX_SUMMARY = "An ephemeral ActivityPub inbox for testing purposes.";
|
|
9
|
-
const
|
|
9
|
+
const inboxOptions = merge(object("Inbox options", {
|
|
10
10
|
command: constant("inbox"),
|
|
11
11
|
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.` })), {
|
|
12
12
|
context: configContext,
|
|
@@ -33,9 +33,11 @@ const inboxCommand = command("inbox", merge(object("Inbox options", {
|
|
|
33
33
|
key: (config) => config.inbox?.authorizedFetch ?? false,
|
|
34
34
|
default: false
|
|
35
35
|
})
|
|
36
|
-
}), group("Tunnel options", createTunnelOption("inbox")))
|
|
36
|
+
}), group("Tunnel options", createTunnelOption("inbox")));
|
|
37
|
+
const inboxMetadata = {
|
|
37
38
|
brief: message`Run an ephemeral ActivityPub inbox server.`,
|
|
38
39
|
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.`
|
|
39
|
-
}
|
|
40
|
+
};
|
|
41
|
+
command("inbox", inboxOptions, inboxMetadata);
|
|
40
42
|
//#endregion
|
|
41
|
-
export {
|
|
43
|
+
export { inboxMetadata, inboxOptions };
|
package/dist/inbox.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { Temporal } from "@js-temporal/polyfill";
|
|
2
|
-
import { getDocumentLoader } from "./docloader.js";
|
|
3
2
|
import { colors, matchesActor } from "./utils.js";
|
|
3
|
+
import { configureLogging, recordingSink } from "./log.js";
|
|
4
4
|
import { version } from "./deno.js";
|
|
5
|
+
import { getDocumentLoader } from "./docloader.js";
|
|
5
6
|
import { ActivityEntryPage, ActivityListPage } from "./inbox/view.js";
|
|
6
|
-
import { configureLogging, recordingSink } from "./log.js";
|
|
7
7
|
import { tableStyle } from "./table.js";
|
|
8
8
|
import { spawnTemporaryServer } from "./tempserver.js";
|
|
9
9
|
import process from "node:process";
|
|
10
10
|
import { MemoryKvStore, createFederation, generateCryptoKeyPair } from "@fedify/fedify";
|
|
11
|
-
import { Accept, Activity, Application, Delete, Endpoints, Follow, Image, PUBLIC_COLLECTION, isActor, lookupObject } from "@fedify/vocab";
|
|
12
11
|
import { getLogger } from "@logtape/logtape";
|
|
12
|
+
import ora from "ora";
|
|
13
|
+
import { Accept, Activity, Application, Delete, Endpoints, Follow, Image, PUBLIC_COLLECTION, isActor, lookupObject } from "@fedify/vocab";
|
|
13
14
|
import Table from "cli-table3";
|
|
14
15
|
import { Hono } from "hono";
|
|
15
|
-
import ora from "ora";
|
|
16
16
|
import { jsx } from "hono/jsx/jsx-runtime";
|
|
17
17
|
//#region src/inbox.tsx
|
|
18
18
|
/** @jsx react-jsx */
|
package/dist/log.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { mkdir } from "node:fs/promises";
|
|
3
2
|
import process from "node:process";
|
|
4
|
-
import { configure, getConsoleSink } from "@logtape/logtape";
|
|
5
3
|
import { dirname } from "node:path";
|
|
4
|
+
import { configure, getConsoleSink } from "@logtape/logtape";
|
|
5
|
+
import { mkdir } from "node:fs/promises";
|
|
6
6
|
import { getFileSink } from "@logtape/file";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
//#region src/log.ts
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import { configContext } from "../config.js";
|
|
3
|
+
import { createTunnelServiceOption, userAgentOption } from "../options.js";
|
|
4
|
+
import { argument, choice, command, constant, flag, float, integer, map, merge, message, multiple, object, option, optionNames, optional, or, string, withDefault } from "@optique/core";
|
|
5
|
+
import { path } from "@optique/run";
|
|
6
|
+
import { bindConfig } from "@optique/config";
|
|
7
|
+
//#region src/lookup/command.ts
|
|
8
|
+
const IN_REPLY_TO_IRI = "https://www.w3.org/ns/activitystreams#inReplyTo";
|
|
9
|
+
const QUOTE_IRI = "https://w3id.org/fep/044f#quote";
|
|
10
|
+
const QUOTE_URL_IRI = "https://www.w3.org/ns/activitystreams#quoteUrl";
|
|
11
|
+
const MISSKEY_QUOTE_IRI = "https://misskey-hub.net/ns#_misskey_quote";
|
|
12
|
+
const FEDIBIRD_QUOTE_IRI = "http://fedibird.com/ns#quoteUri";
|
|
13
|
+
const recurseProperties = [
|
|
14
|
+
"replyTarget",
|
|
15
|
+
"quote",
|
|
16
|
+
"quoteUrl",
|
|
17
|
+
IN_REPLY_TO_IRI,
|
|
18
|
+
QUOTE_IRI,
|
|
19
|
+
QUOTE_URL_IRI,
|
|
20
|
+
MISSKEY_QUOTE_IRI,
|
|
21
|
+
FEDIBIRD_QUOTE_IRI
|
|
22
|
+
];
|
|
23
|
+
const suppressErrorsOption = bindConfig(flag("-S", "--suppress-errors", { description: message`Suppress partial errors during traversal or recursion.` }), {
|
|
24
|
+
context: configContext,
|
|
25
|
+
key: (config) => config.lookup?.suppressErrors ?? false,
|
|
26
|
+
default: false
|
|
27
|
+
});
|
|
28
|
+
const allowPrivateAddressOption = bindConfig(flag("-p", "--allow-private-address", { description: message`Allow private IP addresses for URLs discovered \
|
|
29
|
+
during traversal or recursive object fetches. Recursive JSON-LD \
|
|
30
|
+
context URLs always remain blocked. URLs explicitly provided on the \
|
|
31
|
+
command line always allow private addresses.` }), {
|
|
32
|
+
context: configContext,
|
|
33
|
+
key: (config) => config.lookup?.allowPrivateAddress ?? false,
|
|
34
|
+
default: false
|
|
35
|
+
});
|
|
36
|
+
const authorizedFetchOption = withDefault(object("Authorized fetch options", {
|
|
37
|
+
authorizedFetch: bindConfig(map(flag("-a", "--authorized-fetch", { description: message`Sign the request with an one-time key.` }), () => true), {
|
|
38
|
+
context: configContext,
|
|
39
|
+
key: (config) => config.lookup?.authorizedFetch ? true : void 0
|
|
40
|
+
}),
|
|
41
|
+
firstKnock: bindConfig(option("--first-knock", choice(["draft-cavage-http-signatures-12", "rfc9421"]), { description: message`The first-knock spec for ${optionNames(["-a", "--authorized-fetch"])}. It is used for the double-knocking technique.` }), {
|
|
42
|
+
context: configContext,
|
|
43
|
+
key: (config) => config.lookup?.firstKnock ?? "draft-cavage-http-signatures-12",
|
|
44
|
+
default: "draft-cavage-http-signatures-12"
|
|
45
|
+
}),
|
|
46
|
+
tunnelService: optional(createTunnelServiceOption())
|
|
47
|
+
}), {
|
|
48
|
+
authorizedFetch: false,
|
|
49
|
+
firstKnock: void 0,
|
|
50
|
+
tunnelService: void 0
|
|
51
|
+
});
|
|
52
|
+
const lookupModeOption = withDefault(or(object("Recurse options", {
|
|
53
|
+
traverse: constant(false),
|
|
54
|
+
recurse: bindConfig(option("--recurse", choice(recurseProperties, { metavar: "PROPERTY" }), { description: message`Recursively follow a relationship property.` }), {
|
|
55
|
+
context: configContext,
|
|
56
|
+
key: (config) => config.lookup?.recurse
|
|
57
|
+
}),
|
|
58
|
+
recurseDepth: bindConfig(option("--recurse-depth", integer({
|
|
59
|
+
min: 1,
|
|
60
|
+
metavar: "DEPTH"
|
|
61
|
+
}), { description: message`Maximum recursion depth for ${optionNames(["--recurse"])}.` }), {
|
|
62
|
+
context: configContext,
|
|
63
|
+
key: (config) => config.lookup?.recurseDepth,
|
|
64
|
+
default: 20
|
|
65
|
+
}),
|
|
66
|
+
suppressErrors: suppressErrorsOption
|
|
67
|
+
}), object("Traverse options", {
|
|
68
|
+
traverse: bindConfig(flag("-t", "--traverse", { description: message`Traverse the given collection(s) to fetch all items.` }), {
|
|
69
|
+
context: configContext,
|
|
70
|
+
key: (config) => config.lookup?.traverse ?? false,
|
|
71
|
+
default: false
|
|
72
|
+
}),
|
|
73
|
+
recurse: constant(void 0),
|
|
74
|
+
recurseDepth: constant(void 0),
|
|
75
|
+
suppressErrors: suppressErrorsOption
|
|
76
|
+
})), {
|
|
77
|
+
traverse: false,
|
|
78
|
+
recurse: void 0,
|
|
79
|
+
recurseDepth: void 0,
|
|
80
|
+
suppressErrors: false
|
|
81
|
+
});
|
|
82
|
+
const lookupOptions = merge(object({ command: constant("lookup") }), lookupModeOption, authorizedFetchOption, merge("Network options", userAgentOption, object({
|
|
83
|
+
allowPrivateAddress: allowPrivateAddressOption,
|
|
84
|
+
timeout: optional(bindConfig(option("-T", "--timeout", float({
|
|
85
|
+
min: 0,
|
|
86
|
+
metavar: "SECONDS"
|
|
87
|
+
}), { description: message`Set timeout for network requests in seconds.` }), {
|
|
88
|
+
context: configContext,
|
|
89
|
+
key: (config) => config.lookup?.timeout
|
|
90
|
+
}))
|
|
91
|
+
})), object("Arguments", { urls: multiple(argument(string({ metavar: "URL_OR_HANDLE" }), { description: message`One or more URLs or handles to look up.` }), { min: 1 }) }), object("Output options", {
|
|
92
|
+
reverse: bindConfig(flag("--reverse", { description: message`Reverse the output order of fetched objects or items.` }), {
|
|
93
|
+
context: configContext,
|
|
94
|
+
key: (config) => config.lookup?.reverse ?? false,
|
|
95
|
+
default: false
|
|
96
|
+
}),
|
|
97
|
+
format: bindConfig(optional(or(map(flag("-r", "--raw", { description: message`Print the fetched JSON-LD document as is.` }), () => "raw"), map(flag("-C", "--compact", { description: message`Compact the fetched JSON-LD document.` }), () => "compact"), map(flag("-e", "--expand", { description: message`Expand the fetched JSON-LD document.` }), () => "expand"))), {
|
|
98
|
+
context: configContext,
|
|
99
|
+
key: (config) => config.lookup?.defaultFormat ?? "default",
|
|
100
|
+
default: "default"
|
|
101
|
+
}),
|
|
102
|
+
separator: bindConfig(option("-s", "--separator", string({ metavar: "SEPARATOR" }), { description: message`Specify the separator between adjacent output objects or collection items.` }), {
|
|
103
|
+
context: configContext,
|
|
104
|
+
key: (config) => config.lookup?.separator ?? "----",
|
|
105
|
+
default: "----"
|
|
106
|
+
}),
|
|
107
|
+
output: optional(option("-o", "--output", path({
|
|
108
|
+
metavar: "OUTPUT_PATH",
|
|
109
|
+
type: "file",
|
|
110
|
+
allowCreate: true
|
|
111
|
+
}), { description: message`Specify the output file path.` }))
|
|
112
|
+
}));
|
|
113
|
+
const lookupMetadata = {
|
|
114
|
+
brief: message`Look up Activity Streams objects.`,
|
|
115
|
+
description: message`Look up Activity Streams objects by URL or actor handle.
|
|
116
|
+
|
|
117
|
+
The arguments can be either URLs or actor handles (e.g., ${"@username@domain"}), and they can be multiple.`
|
|
118
|
+
};
|
|
119
|
+
command("lookup", lookupOptions, lookupMetadata);
|
|
120
|
+
//#endregion
|
|
121
|
+
export { FEDIBIRD_QUOTE_IRI, IN_REPLY_TO_IRI, MISSKEY_QUOTE_IRI, QUOTE_IRI, QUOTE_URL_IRI, authorizedFetchOption, lookupMetadata, lookupOptions };
|
package/dist/lookup.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import {
|
|
2
|
+
import { FEDIBIRD_QUOTE_IRI, IN_REPLY_TO_IRI, MISSKEY_QUOTE_IRI, QUOTE_IRI, QUOTE_URL_IRI } from "./lookup/command.js";
|
|
3
3
|
import { colorEnabled, colors, describeError, formatObject } from "./utils.js";
|
|
4
|
-
import { configContext } from "./config.js";
|
|
5
|
-
import { createTunnelServiceOption, userAgentOption } from "./options.js";
|
|
6
4
|
import { configureLogging } from "./log.js";
|
|
5
|
+
import { getContextLoader, getDocumentLoader as getDocumentLoader$1 } from "./docloader.js";
|
|
7
6
|
import { spawnTemporaryServer } from "./tempserver.js";
|
|
8
7
|
import { renderImages } from "./imagerenderer.js";
|
|
9
8
|
import process from "node:process";
|
|
10
|
-
import {
|
|
9
|
+
import { message, optionNames } from "@optique/core";
|
|
10
|
+
import { printError } from "@optique/run";
|
|
11
|
+
import { createWriteStream } from "node:fs";
|
|
11
12
|
import { UrlError, expandIPv6Address, isValidPublicIPv4Address, isValidPublicIPv6Address } from "@fedify/vocab-runtime";
|
|
12
|
-
import {
|
|
13
|
-
import { argument, choice, command, constant, flag, float, integer, map, merge, message, multiple, object, option, optionNames, optional, or, string, withDefault } from "@optique/core";
|
|
14
|
-
import { path, printError } from "@optique/run";
|
|
13
|
+
import { generateCryptoKeyPair, getAuthenticatedDocumentLoader, respondWithObject } from "@fedify/fedify";
|
|
15
14
|
import { getLogger } from "@logtape/logtape";
|
|
16
|
-
import { bindConfig } from "@optique/config";
|
|
17
|
-
import { createWriteStream } from "node:fs";
|
|
18
|
-
import { url } from "@optique/core/message";
|
|
19
15
|
import ora from "ora";
|
|
16
|
+
import { Application, Collection, CryptographicKey, Object as Object$1, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
17
|
+
import { url } from "@optique/core/message";
|
|
20
18
|
import { isIP } from "node:net";
|
|
21
19
|
//#region src/lookup.ts
|
|
22
20
|
const logger = getLogger([
|
|
@@ -24,116 +22,6 @@ const logger = getLogger([
|
|
|
24
22
|
"cli",
|
|
25
23
|
"lookup"
|
|
26
24
|
]);
|
|
27
|
-
const IN_REPLY_TO_IRI = "https://www.w3.org/ns/activitystreams#inReplyTo";
|
|
28
|
-
const QUOTE_IRI = "https://w3id.org/fep/044f#quote";
|
|
29
|
-
const QUOTE_URL_IRI = "https://www.w3.org/ns/activitystreams#quoteUrl";
|
|
30
|
-
const MISSKEY_QUOTE_IRI = "https://misskey-hub.net/ns#_misskey_quote";
|
|
31
|
-
const FEDIBIRD_QUOTE_IRI = "http://fedibird.com/ns#quoteUri";
|
|
32
|
-
const recurseProperties = [
|
|
33
|
-
"replyTarget",
|
|
34
|
-
"quote",
|
|
35
|
-
"quoteUrl",
|
|
36
|
-
IN_REPLY_TO_IRI,
|
|
37
|
-
QUOTE_IRI,
|
|
38
|
-
QUOTE_URL_IRI,
|
|
39
|
-
MISSKEY_QUOTE_IRI,
|
|
40
|
-
FEDIBIRD_QUOTE_IRI
|
|
41
|
-
];
|
|
42
|
-
const suppressErrorsOption = bindConfig(flag("-S", "--suppress-errors", { description: message`Suppress partial errors during traversal or recursion.` }), {
|
|
43
|
-
context: configContext,
|
|
44
|
-
key: (config) => config.lookup?.suppressErrors ?? false,
|
|
45
|
-
default: false
|
|
46
|
-
});
|
|
47
|
-
const allowPrivateAddressOption = bindConfig(flag("-p", "--allow-private-address", { description: message`Allow private IP addresses for URLs discovered \
|
|
48
|
-
during traversal or recursive object fetches. Recursive JSON-LD \
|
|
49
|
-
context URLs always remain blocked. URLs explicitly provided on the \
|
|
50
|
-
command line always allow private addresses.` }), {
|
|
51
|
-
context: configContext,
|
|
52
|
-
key: (config) => config.lookup?.allowPrivateAddress ?? false,
|
|
53
|
-
default: false
|
|
54
|
-
});
|
|
55
|
-
const authorizedFetchOption = withDefault(object("Authorized fetch options", {
|
|
56
|
-
authorizedFetch: bindConfig(map(flag("-a", "--authorized-fetch", { description: message`Sign the request with an one-time key.` }), () => true), {
|
|
57
|
-
context: configContext,
|
|
58
|
-
key: (config) => config.lookup?.authorizedFetch ? true : void 0
|
|
59
|
-
}),
|
|
60
|
-
firstKnock: bindConfig(option("--first-knock", choice(["draft-cavage-http-signatures-12", "rfc9421"]), { description: message`The first-knock spec for ${optionNames(["-a", "--authorized-fetch"])}. It is used for the double-knocking technique.` }), {
|
|
61
|
-
context: configContext,
|
|
62
|
-
key: (config) => config.lookup?.firstKnock ?? "draft-cavage-http-signatures-12",
|
|
63
|
-
default: "draft-cavage-http-signatures-12"
|
|
64
|
-
}),
|
|
65
|
-
tunnelService: optional(createTunnelServiceOption())
|
|
66
|
-
}), {
|
|
67
|
-
authorizedFetch: false,
|
|
68
|
-
firstKnock: void 0,
|
|
69
|
-
tunnelService: void 0
|
|
70
|
-
});
|
|
71
|
-
const lookupModeOption = withDefault(or(object("Recurse options", {
|
|
72
|
-
traverse: constant(false),
|
|
73
|
-
recurse: bindConfig(option("--recurse", choice(recurseProperties, { metavar: "PROPERTY" }), { description: message`Recursively follow a relationship property.` }), {
|
|
74
|
-
context: configContext,
|
|
75
|
-
key: (config) => config.lookup?.recurse
|
|
76
|
-
}),
|
|
77
|
-
recurseDepth: bindConfig(option("--recurse-depth", integer({
|
|
78
|
-
min: 1,
|
|
79
|
-
metavar: "DEPTH"
|
|
80
|
-
}), { description: message`Maximum recursion depth for ${optionNames(["--recurse"])}.` }), {
|
|
81
|
-
context: configContext,
|
|
82
|
-
key: (config) => config.lookup?.recurseDepth,
|
|
83
|
-
default: 20
|
|
84
|
-
}),
|
|
85
|
-
suppressErrors: suppressErrorsOption
|
|
86
|
-
}), object("Traverse options", {
|
|
87
|
-
traverse: bindConfig(flag("-t", "--traverse", { description: message`Traverse the given collection(s) to fetch all items.` }), {
|
|
88
|
-
context: configContext,
|
|
89
|
-
key: (config) => config.lookup?.traverse ?? false,
|
|
90
|
-
default: false
|
|
91
|
-
}),
|
|
92
|
-
recurse: constant(void 0),
|
|
93
|
-
recurseDepth: constant(void 0),
|
|
94
|
-
suppressErrors: suppressErrorsOption
|
|
95
|
-
})), {
|
|
96
|
-
traverse: false,
|
|
97
|
-
recurse: void 0,
|
|
98
|
-
recurseDepth: void 0,
|
|
99
|
-
suppressErrors: false
|
|
100
|
-
});
|
|
101
|
-
const lookupCommand = command("lookup", merge(object({ command: constant("lookup") }), lookupModeOption, authorizedFetchOption, merge("Network options", userAgentOption, object({
|
|
102
|
-
allowPrivateAddress: allowPrivateAddressOption,
|
|
103
|
-
timeout: optional(bindConfig(option("-T", "--timeout", float({
|
|
104
|
-
min: 0,
|
|
105
|
-
metavar: "SECONDS"
|
|
106
|
-
}), { description: message`Set timeout for network requests in seconds.` }), {
|
|
107
|
-
context: configContext,
|
|
108
|
-
key: (config) => config.lookup?.timeout
|
|
109
|
-
}))
|
|
110
|
-
})), object("Arguments", { urls: multiple(argument(string({ metavar: "URL_OR_HANDLE" }), { description: message`One or more URLs or handles to look up.` }), { min: 1 }) }), object("Output options", {
|
|
111
|
-
reverse: bindConfig(flag("--reverse", { description: message`Reverse the output order of fetched objects or items.` }), {
|
|
112
|
-
context: configContext,
|
|
113
|
-
key: (config) => config.lookup?.reverse ?? false,
|
|
114
|
-
default: false
|
|
115
|
-
}),
|
|
116
|
-
format: bindConfig(optional(or(map(flag("-r", "--raw", { description: message`Print the fetched JSON-LD document as is.` }), () => "raw"), map(flag("-C", "--compact", { description: message`Compact the fetched JSON-LD document.` }), () => "compact"), map(flag("-e", "--expand", { description: message`Expand the fetched JSON-LD document.` }), () => "expand"))), {
|
|
117
|
-
context: configContext,
|
|
118
|
-
key: (config) => config.lookup?.defaultFormat ?? "default",
|
|
119
|
-
default: "default"
|
|
120
|
-
}),
|
|
121
|
-
separator: bindConfig(option("-s", "--separator", string({ metavar: "SEPARATOR" }), { description: message`Specify the separator between adjacent output objects or collection items.` }), {
|
|
122
|
-
context: configContext,
|
|
123
|
-
key: (config) => config.lookup?.separator ?? "----",
|
|
124
|
-
default: "----"
|
|
125
|
-
}),
|
|
126
|
-
output: optional(option("-o", "--output", path({
|
|
127
|
-
metavar: "OUTPUT_PATH",
|
|
128
|
-
type: "file",
|
|
129
|
-
allowCreate: true
|
|
130
|
-
}), { description: message`Specify the output file path.` }))
|
|
131
|
-
})), {
|
|
132
|
-
brief: message`Look up Activity Streams objects.`,
|
|
133
|
-
description: message`Look up Activity Streams objects by URL or actor handle.
|
|
134
|
-
|
|
135
|
-
The arguments can be either URLs or actor handles (e.g., ${"@username@domain"}), and they can be multiple.`
|
|
136
|
-
});
|
|
137
25
|
var TimeoutError = class extends Error {
|
|
138
26
|
name = "TimeoutError";
|
|
139
27
|
constructor(message) {
|
|
@@ -472,6 +360,7 @@ async function runLookup(command, deps = {}) {
|
|
|
472
360
|
effectiveDeps.exit(cleanupFailed && code === 0 ? 1 : code);
|
|
473
361
|
};
|
|
474
362
|
if (command.authorizedFetch) {
|
|
363
|
+
const firstKnock = command.firstKnock ?? "draft-cavage-http-signatures-12";
|
|
475
364
|
spinner.text = "Generating a one-time key pair...";
|
|
476
365
|
const key = await generateCryptoKeyPair();
|
|
477
366
|
spinner.text = "Spinning up a temporary ActivityPub server...";
|
|
@@ -511,7 +400,7 @@ async function runLookup(command, deps = {}) {
|
|
|
511
400
|
userAgent: command.userAgent,
|
|
512
401
|
specDeterminer: {
|
|
513
402
|
determineSpec() {
|
|
514
|
-
return
|
|
403
|
+
return firstKnock;
|
|
515
404
|
},
|
|
516
405
|
rememberSpec() {}
|
|
517
406
|
}
|
|
@@ -521,7 +410,7 @@ async function runLookup(command, deps = {}) {
|
|
|
521
410
|
userAgent: command.userAgent,
|
|
522
411
|
specDeterminer: {
|
|
523
412
|
determineSpec() {
|
|
524
|
-
return
|
|
413
|
+
return firstKnock;
|
|
525
414
|
},
|
|
526
415
|
rememberSpec() {}
|
|
527
416
|
}
|
|
@@ -818,4 +707,4 @@ async function runLookup(command, deps = {}) {
|
|
|
818
707
|
if (success && command.output) spinner.succeed(`Successfully wrote output to ${colors.green(command.output)}.`);
|
|
819
708
|
}
|
|
820
709
|
//#endregion
|
|
821
|
-
export {
|
|
710
|
+
export { runLookup };
|
package/dist/mod.js
CHANGED
|
@@ -1,30 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --disable-warning=ExperimentalWarning
|
|
2
2
|
import "@js-temporal/polyfill";
|
|
3
|
-
import {
|
|
4
|
-
import runGenerateVocab from "./generate-vocab/action.js";
|
|
5
|
-
import "./generate-vocab/mod.js";
|
|
6
|
-
import { runInbox } from "./inbox.js";
|
|
7
|
-
import { runInit } from "./init/mod.js";
|
|
8
|
-
import { runNodeInfo } from "./nodeinfo.js";
|
|
9
|
-
import { runLookup } from "./lookup.js";
|
|
10
|
-
import { runRelay } from "./relay.js";
|
|
11
|
-
import { runTunnel } from "./tunnel.js";
|
|
12
|
-
import runWebFinger from "./webfinger/action.js";
|
|
13
|
-
import "./webfinger/mod.js";
|
|
14
|
-
import { runCli } from "./runner.js";
|
|
3
|
+
import { parseCliProgram } from "./runner.js";
|
|
15
4
|
import process from "node:process";
|
|
16
5
|
//#region src/mod.ts
|
|
17
6
|
async function main() {
|
|
18
|
-
|
|
19
|
-
if (result.command === "init") await runInit(result);
|
|
20
|
-
else if (result.command === "lookup") await runLookup(result);
|
|
21
|
-
else if (result.command === "webfinger") await runWebFinger(result);
|
|
22
|
-
else if (result.command === "inbox") await runInbox(result);
|
|
23
|
-
else if (result.command === "nodeinfo") await runNodeInfo(result);
|
|
24
|
-
else if (result.command === "tunnel") await runTunnel(result);
|
|
25
|
-
else if (result.command === "generate-vocab") await runGenerateVocab(result);
|
|
26
|
-
else if (result.command === "relay") await runRelay(result);
|
|
27
|
-
else if (result.command === "bench") await runBench(result);
|
|
7
|
+
await (await parseCliProgram(process.argv.slice(2))).run();
|
|
28
8
|
}
|
|
29
9
|
await main();
|
|
30
10
|
//#endregion
|
package/dist/nodeinfo.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { colors, formatObject } from "./utils.js";
|
|
3
2
|
import { configContext } from "./config.js";
|
|
4
3
|
import { userAgentOption } from "./options.js";
|
|
4
|
+
import { colors, formatObject } from "./utils.js";
|
|
5
5
|
import process from "node:process";
|
|
6
|
-
import { getNodeInfo } from "@fedify/fedify";
|
|
7
|
-
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
8
6
|
import { argument, command, constant, flag, group, merge, message, object, string, text } from "@optique/core";
|
|
9
7
|
import { print, printError } from "@optique/run";
|
|
10
|
-
import { getLogger } from "@logtape/logtape";
|
|
11
8
|
import os from "node:os";
|
|
12
9
|
import { bindConfig } from "@optique/config";
|
|
13
|
-
import
|
|
10
|
+
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
11
|
+
import { getNodeInfo } from "@fedify/fedify";
|
|
14
12
|
import { createJimp } from "@jimp/core";
|
|
15
13
|
import webp from "@jimp/wasm-webp";
|
|
14
|
+
import { getLogger } from "@logtape/logtape";
|
|
16
15
|
import { isICO, parseICO } from "icojs";
|
|
17
16
|
import { defaultFormats, defaultPlugins, intToRGBA } from "jimp";
|
|
17
|
+
import ora from "ora";
|
|
18
18
|
//#region src/nodeinfo.ts
|
|
19
19
|
const logger = getLogger([
|
|
20
20
|
"fedify",
|
|
@@ -46,15 +46,17 @@ const nodeInfoOption = merge(object("Display options", {
|
|
|
46
46
|
key: (config) => config.nodeinfo?.bestEffort ?? false,
|
|
47
47
|
default: false
|
|
48
48
|
}) }));
|
|
49
|
-
const
|
|
49
|
+
const nodeInfoOptions = merge(object("Arguments", {
|
|
50
50
|
command: constant("nodeinfo"),
|
|
51
51
|
host: argument(string({ metavar: "HOST" }), { description: message`Bare hostname or a full URL of the instance` })
|
|
52
|
-
}), nodeInfoOption, group("Network options", userAgentOption))
|
|
52
|
+
}), nodeInfoOption, group("Network options", userAgentOption));
|
|
53
|
+
const nodeInfoMetadata = {
|
|
53
54
|
brief: message`Get information about a remote node using the NodeInfo protocol`,
|
|
54
55
|
description: message`Get information about a remote node using the NodeInfo protocol.
|
|
55
56
|
|
|
56
57
|
The argument is the hostname of the remote node, or the URL of the remote node.`
|
|
57
|
-
}
|
|
58
|
+
};
|
|
59
|
+
command("nodeinfo", nodeInfoOptions, nodeInfoMetadata);
|
|
58
60
|
async function runNodeInfo(command) {
|
|
59
61
|
const spinner = ora({
|
|
60
62
|
text: "Fetching a NodeInfo document...",
|
|
@@ -270,4 +272,4 @@ function getAsciiArt(image, width = DEFAULT_IMAGE_WIDTH, colorSupport, colors) {
|
|
|
270
272
|
return art;
|
|
271
273
|
}
|
|
272
274
|
//#endregion
|
|
273
|
-
export { Jimp,
|
|
275
|
+
export { Jimp, nodeInfoMetadata, nodeInfoOptions, runNodeInfo };
|
package/dist/options.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import { configContext } from "./config.js";
|
|
3
|
-
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
4
3
|
import { choice, constant, flag, map, merge, message, object, option, optional, or, string, withDefault } from "@optique/core";
|
|
5
4
|
import { bindConfig } from "@optique/config";
|
|
5
|
+
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
6
6
|
//#region src/options.ts
|
|
7
7
|
/**
|
|
8
8
|
* Available tunneling services for exposing local servers to the public internet.
|
package/dist/relay/command.js
CHANGED
|
@@ -5,7 +5,7 @@ import { command, constant, group, integer, merge, message, multiple, object, op
|
|
|
5
5
|
import { bindConfig } from "@optique/config";
|
|
6
6
|
import { choice as choice$1 } from "@optique/core/valueparser";
|
|
7
7
|
//#region src/relay/command.ts
|
|
8
|
-
const
|
|
8
|
+
const relayOptions = merge(object("Relay options", {
|
|
9
9
|
command: constant("relay"),
|
|
10
10
|
protocol: bindConfig(option("-p", "--protocol", choice$1(["mastodon", "litepub"], { metavar: "TYPE" }), { description: message`The relay protocol to use. ${value("mastodon")} for Mastodon-compatible relay, ${value("litepub")} for LitePub-compatible relay.` }), {
|
|
11
11
|
context: configContext,
|
|
@@ -40,11 +40,13 @@ const relayCommand = command("relay", merge(object("Relay options", {
|
|
|
40
40
|
key: (config) => config.relay?.rejectFollow ?? [],
|
|
41
41
|
default: []
|
|
42
42
|
})
|
|
43
|
-
}), group("Tunnel options", createTunnelOption("relay")))
|
|
43
|
+
}), group("Tunnel options", createTunnelOption("relay")));
|
|
44
|
+
const relayMetadata = {
|
|
44
45
|
brief: message`Run an ephemeral ActivityPub relay server.`,
|
|
45
46
|
description: message`Spins up an ActivityPub relay server that forwards activities between federated instances. The server can use either Mastodon or LitePub compatible relay protocol.
|
|
46
47
|
|
|
47
48
|
By default, the server is tunneled to the public internet for external access. Use ${optionName("--no-tunnel")} to run locally only.`
|
|
48
|
-
}
|
|
49
|
+
};
|
|
50
|
+
command("relay", relayOptions, relayMetadata);
|
|
49
51
|
//#endregion
|
|
50
|
-
export {
|
|
52
|
+
export { relayMetadata, relayOptions };
|
package/dist/relay.js
CHANGED
|
@@ -6,11 +6,11 @@ import { spawnTemporaryServer } from "./tempserver.js";
|
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
import { MemoryKvStore } from "@fedify/fedify";
|
|
8
8
|
import { getLogger } from "@logtape/logtape";
|
|
9
|
-
import Table from "cli-table3";
|
|
10
9
|
import ora from "ora";
|
|
11
|
-
import { createRelay } from "@fedify/relay";
|
|
12
10
|
import { SqliteKvStore } from "@fedify/sqlite";
|
|
13
11
|
import { DatabaseSync } from "node:sqlite";
|
|
12
|
+
import Table from "cli-table3";
|
|
13
|
+
import { createRelay } from "@fedify/relay";
|
|
14
14
|
//#region src/relay.ts
|
|
15
15
|
const logger = getLogger([
|
|
16
16
|
"fedify",
|
package/dist/runner.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import { describeError } from "./utils.js";
|
|
3
|
-
import { version } from "./deno.js";
|
|
4
2
|
import { configContext, tryLoadToml } from "./config.js";
|
|
5
3
|
import { globalOptions } from "./options.js";
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import "./
|
|
9
|
-
import { initCommand } from "./init/mod.js";
|
|
10
|
-
import { nodeInfoCommand } from "./nodeinfo.js";
|
|
11
|
-
import { lookupCommand } from "./lookup.js";
|
|
12
|
-
import { inboxCommand } from "./inbox/command.js";
|
|
13
|
-
import { relayCommand } from "./relay/command.js";
|
|
14
|
-
import { tunnelCommand } from "./tunnel.js";
|
|
15
|
-
import { webFingerCommand } from "./webfinger/command.js";
|
|
16
|
-
import "./webfinger/mod.js";
|
|
4
|
+
import { describeError } from "./utils.js";
|
|
5
|
+
import { activityPubCommands, generatingCommands, networkCommands } from "./commands.js";
|
|
6
|
+
import { version } from "./deno.js";
|
|
17
7
|
import process from "node:process";
|
|
18
|
-
import { group, merge, message, or } from "@optique/core";
|
|
8
|
+
import { command, group, map, merge, message, or } from "@optique/core";
|
|
19
9
|
import { printError, run } from "@optique/run";
|
|
20
10
|
import { merge as merge$1 } from "es-toolkit";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
21
12
|
import { homedir } from "node:os";
|
|
22
13
|
import { join } from "node:path";
|
|
23
|
-
import { readFileSync } from "node:fs";
|
|
24
14
|
import { parse } from "smol-toml";
|
|
25
15
|
//#region src/runner.ts
|
|
26
16
|
/**
|
|
@@ -41,36 +31,35 @@ function getUserConfigPath() {
|
|
|
41
31
|
if (process.platform === "win32") return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), "fedify", "config.toml");
|
|
42
32
|
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "fedify", "config.toml");
|
|
43
33
|
}
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
} catch (error) {
|
|
54
|
-
printError(message`Could not load config file at ${parsed.configPath}: ${describeError(error)}`);
|
|
55
|
-
process.exit(1);
|
|
34
|
+
const selectedCommand = "__fedifyCliSelectedCommand";
|
|
35
|
+
const selectedRun = "__fedifyCliRunCommand";
|
|
36
|
+
function staticCommandParser(staticCommand) {
|
|
37
|
+
if (staticCommand.path.length < 1) throw new TypeError("Static command path must not be empty.");
|
|
38
|
+
let parser = staticCommand.parser;
|
|
39
|
+
for (let i = staticCommand.path.length - 1; i >= 0; i--) {
|
|
40
|
+
const name = staticCommand.path[i];
|
|
41
|
+
if (name == null) throw new TypeError("Static command path contains an empty segment.");
|
|
42
|
+
parser = command(name, parser, i === staticCommand.path.length - 1 ? staticCommand.metadata : void 0);
|
|
56
43
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
44
|
+
const runCommand = staticCommand.run;
|
|
45
|
+
return map(parser, (value) => ({
|
|
46
|
+
...value,
|
|
47
|
+
[selectedCommand]: staticCommand,
|
|
48
|
+
[selectedRun]: (globalOptions) => runCommand({
|
|
49
|
+
...value,
|
|
50
|
+
...globalOptions
|
|
51
|
+
})
|
|
52
|
+
}));
|
|
66
53
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
54
|
+
function staticCommandsParser(commands) {
|
|
55
|
+
const parsers = commands.map(staticCommandParser);
|
|
56
|
+
if (parsers.length < 1) throw new TypeError("Static command group must not be empty.");
|
|
57
|
+
return parsers.length === 1 ? parsers[0] : or(...parsers);
|
|
58
|
+
}
|
|
59
|
+
const runnableCommand = merge(or(group("Generating code", staticCommandsParser(generatingCommands)), group("ActivityPub tools", staticCommandsParser(activityPubCommands)), group("Network tools", staticCommandsParser(networkCommands))), globalOptions);
|
|
60
|
+
map(runnableCommand, ({ [selectedCommand]: _selectedCommand, [selectedRun]: _selectedRun, ...value }) => value);
|
|
61
|
+
function getRunOptions(args) {
|
|
62
|
+
return {
|
|
74
63
|
contexts: [configContext],
|
|
75
64
|
contextOptions: { load: loadConfig },
|
|
76
65
|
programName: "fedify",
|
|
@@ -92,7 +81,41 @@ function runCli(args) {
|
|
|
92
81
|
maxWidth: process.stdout.columns,
|
|
93
82
|
showDefault: true,
|
|
94
83
|
showChoices: true
|
|
95
|
-
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function loadConfig(parsed) {
|
|
87
|
+
if (parsed.ignoreConfig) return void 0;
|
|
88
|
+
const system = getSystemConfigPaths().map(tryLoadToml).reduce((acc, config) => merge$1(acc, config), {});
|
|
89
|
+
const user = tryLoadToml(getUserConfigPath());
|
|
90
|
+
const project = tryLoadToml(join(process.cwd(), ".fedify.toml"));
|
|
91
|
+
let custom = {};
|
|
92
|
+
if (parsed.configPath) try {
|
|
93
|
+
custom = parse(readFileSync(parsed.configPath, "utf-8"));
|
|
94
|
+
} catch (error) {
|
|
95
|
+
printError(message`Could not load config file at ${parsed.configPath}: ${describeError(error)}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
config: [
|
|
100
|
+
system,
|
|
101
|
+
user,
|
|
102
|
+
project,
|
|
103
|
+
custom
|
|
104
|
+
].reduce((acc, config) => merge$1(acc, config), {}),
|
|
105
|
+
meta: void 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function toCliProgram(parsed) {
|
|
109
|
+
const { [selectedCommand]: command, [selectedRun]: runCommand, ...value } = parsed;
|
|
110
|
+
const publicValue = value;
|
|
111
|
+
return {
|
|
112
|
+
command,
|
|
113
|
+
value: publicValue,
|
|
114
|
+
run: () => runCommand(publicValue)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function parseCliProgram(args) {
|
|
118
|
+
return toCliProgram(await run(runnableCommand, getRunOptions(args)));
|
|
96
119
|
}
|
|
97
120
|
//#endregion
|
|
98
|
-
export {
|
|
121
|
+
export { parseCliProgram };
|
package/dist/tempserver.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
2
|
import { getLogger } from "@logtape/logtape";
|
|
3
|
-
import { serve } from "srvx";
|
|
4
3
|
import { openTunnel } from "@hongminhee/localtunnel";
|
|
4
|
+
import { serve } from "srvx";
|
|
5
5
|
//#region src/tempserver.ts
|
|
6
6
|
const logger = getLogger([
|
|
7
7
|
"fedify",
|
package/dist/tunnel.js
CHANGED
|
@@ -7,19 +7,21 @@ import { print, printError } from "@optique/run";
|
|
|
7
7
|
import ora from "ora";
|
|
8
8
|
import { openTunnel } from "@hongminhee/localtunnel";
|
|
9
9
|
//#region src/tunnel.ts
|
|
10
|
-
const
|
|
10
|
+
const tunnelOptions = merge("Tunnel options", object({ command: constant("tunnel") }), object({
|
|
11
11
|
port: argument(integer({
|
|
12
12
|
metavar: "PORT",
|
|
13
13
|
min: 0,
|
|
14
14
|
max: 65535
|
|
15
15
|
}), { description: message`The local port number to expose.` }),
|
|
16
16
|
service: createTunnelServiceOption(["-s", "--service"])
|
|
17
|
-
}))
|
|
17
|
+
}));
|
|
18
|
+
const tunnelMetadata = {
|
|
18
19
|
brief: message`Expose a local HTTP server to the public internet using a secure tunnel.`,
|
|
19
20
|
description: message`Expose a local HTTP server to the public internet using a secure tunnel.
|
|
20
21
|
|
|
21
22
|
Note that the HTTP requests through the tunnel have X-Forwarded-* headers.`
|
|
22
|
-
}
|
|
23
|
+
};
|
|
24
|
+
command("tunnel", tunnelOptions, tunnelMetadata);
|
|
23
25
|
async function runTunnel(command, deps = {
|
|
24
26
|
openTunnel,
|
|
25
27
|
ora,
|
|
@@ -49,4 +51,4 @@ async function runTunnel(command, deps = {
|
|
|
49
51
|
});
|
|
50
52
|
}
|
|
51
53
|
//#endregion
|
|
52
|
-
export { runTunnel,
|
|
54
|
+
export { runTunnel, tunnelMetadata, tunnelOptions };
|
package/dist/utils.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import "@js-temporal/polyfill";
|
|
2
|
-
import "node:fs/promises";
|
|
3
2
|
import process from "node:process";
|
|
4
|
-
import { getActorHandle } from "@fedify/vocab";
|
|
5
|
-
import "@fxts/core";
|
|
6
3
|
import { message } from "@optique/core";
|
|
7
4
|
import { print, printError } from "@optique/run";
|
|
5
|
+
import { flow } from "es-toolkit";
|
|
6
|
+
import { getActorHandle } from "@fedify/vocab";
|
|
7
|
+
import "@fxts/core";
|
|
8
8
|
import { Chalk } from "chalk";
|
|
9
9
|
import { highlight } from "cli-highlight";
|
|
10
|
-
import { flow } from "es-toolkit";
|
|
11
10
|
import "node:child_process";
|
|
11
|
+
import "node:fs/promises";
|
|
12
12
|
import util from "node:util";
|
|
13
13
|
//#region src/utils.ts
|
|
14
14
|
const colorEnabled = process.stdout.isTTY && !("NO_COLOR" in process.env && process.env.NO_COLOR !== "");
|
package/dist/webfinger/action.js
CHANGED
|
@@ -3,8 +3,8 @@ import { formatObject } from "../utils.js";
|
|
|
3
3
|
import { NotFoundError, getErrorMessage } from "./error.js";
|
|
4
4
|
import { convertUrlIfHandle } from "./lib.js";
|
|
5
5
|
import { print } from "@optique/run";
|
|
6
|
-
import { formatMessage, message } from "@optique/core/message";
|
|
7
6
|
import ora from "ora";
|
|
7
|
+
import { formatMessage, message } from "@optique/core/message";
|
|
8
8
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
9
9
|
//#region src/webfinger/action.ts
|
|
10
10
|
async function runWebFinger({ command: _, resources, ...options }) {
|
|
@@ -14,16 +14,18 @@ const maxRedirection = bindConfig(option("--max-redirection", integer({ min: 0 }
|
|
|
14
14
|
key: (config) => config.webfinger?.maxRedirection ?? 5,
|
|
15
15
|
default: 5
|
|
16
16
|
});
|
|
17
|
-
const
|
|
17
|
+
const webFingerOptions = merge("Network options", object({
|
|
18
18
|
command: constant("webfinger"),
|
|
19
19
|
resources: group("Arguments", multiple(argument(string({ metavar: "RESOURCE" }), { description: message`WebFinger resource(s) to look up.` }), { min: 1 })),
|
|
20
20
|
allowPrivateAddresses,
|
|
21
21
|
maxRedirection
|
|
22
|
-
}), userAgentOption)
|
|
22
|
+
}), userAgentOption);
|
|
23
|
+
const webFingerMetadata = {
|
|
23
24
|
brief: message`Look up WebFinger resources.`,
|
|
24
25
|
description: message`Look up WebFinger resources.
|
|
25
26
|
|
|
26
27
|
The argument can be multiple.`
|
|
27
|
-
}
|
|
28
|
+
};
|
|
29
|
+
command("webfinger", webFingerOptions, webFingerMetadata);
|
|
28
30
|
//#endregion
|
|
29
|
-
export {
|
|
31
|
+
export { webFingerMetadata, webFingerOptions };
|
package/dist/webfinger/lib.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/cli",
|
|
3
|
-
"version": "2.3.0-dev.
|
|
3
|
+
"version": "2.3.0-dev.1344+d573d413",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"README.md",
|
|
@@ -59,9 +59,10 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@cfworker/json-schema": "^4.1.1",
|
|
61
61
|
"@fxts/core": "^1.20.0",
|
|
62
|
-
"@optique/config": "^1.0
|
|
63
|
-
"@optique/core": "^1.0
|
|
64
|
-
"@optique/
|
|
62
|
+
"@optique/config": "^1.1.0",
|
|
63
|
+
"@optique/core": "^1.1.0",
|
|
64
|
+
"@optique/discover": "^1.1.0",
|
|
65
|
+
"@optique/run": "^1.1.0",
|
|
65
66
|
"@standard-schema/spec": "^1.1.0",
|
|
66
67
|
"@hongminhee/localtunnel": "^0.3.0",
|
|
67
68
|
"@inquirer/prompts": "^7.8.4",
|
|
@@ -89,14 +90,14 @@
|
|
|
89
90
|
"srvx": "^0.8.7",
|
|
90
91
|
"valibot": "^1.4.0",
|
|
91
92
|
"yaml": "^2.9.0",
|
|
92
|
-
"@fedify/fedify": "2.3.0-dev.
|
|
93
|
-
"@fedify/
|
|
94
|
-
"@fedify/
|
|
95
|
-
"@fedify/
|
|
96
|
-
"@fedify/vocab
|
|
97
|
-
"@fedify/
|
|
98
|
-
"@fedify/
|
|
99
|
-
"@fedify/
|
|
93
|
+
"@fedify/fedify": "2.3.0-dev.1344+d573d413",
|
|
94
|
+
"@fedify/init": "2.3.0-dev.1344+d573d413",
|
|
95
|
+
"@fedify/sqlite": "2.3.0-dev.1344+d573d413",
|
|
96
|
+
"@fedify/relay": "2.3.0-dev.1344+d573d413",
|
|
97
|
+
"@fedify/vocab": "2.3.0-dev.1344+d573d413",
|
|
98
|
+
"@fedify/vocab-tools": "2.3.0-dev.1344+d573d413",
|
|
99
|
+
"@fedify/webfinger": "2.3.0-dev.1344+d573d413",
|
|
100
|
+
"@fedify/vocab-runtime": "2.3.0-dev.1344+d573d413"
|
|
100
101
|
},
|
|
101
102
|
"devDependencies": {
|
|
102
103
|
"@types/bun": "^1.2.23",
|
package/dist/init/mod.js
DELETED
package/dist/webfinger/mod.js
DELETED