@fedify/cli 2.1.1 → 2.1.2
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/cache.js +7 -16
- package/dist/config.js +5 -13
- package/dist/deno.js +3 -79
- package/dist/docloader.js +3 -8
- package/dist/generate-vocab/action.js +4 -8
- package/dist/generate-vocab/command.js +2 -7
- package/dist/generate-vocab/mod.js +4 -5
- package/dist/imagerenderer.js +10 -20
- package/dist/inbox/rendercode.js +3 -8
- package/dist/inbox/view.js +7 -13
- package/dist/inbox.js +25 -29
- package/dist/init/mod.js +2 -5
- package/dist/kv.bun.js +4 -10
- package/dist/kv.node.js +4 -10
- package/dist/log.js +5 -9
- package/dist/lookup.js +95 -107
- package/dist/mod.js +16 -30
- package/dist/nodeinfo.js +35 -45
- package/dist/options.js +9 -26
- package/dist/relay.js +20 -25
- package/dist/table.js +2 -5
- package/dist/tempserver.js +13 -20
- package/dist/tunnel.js +9 -13
- package/dist/utils.js +7 -13
- package/dist/webfinger/action.js +5 -11
- package/dist/webfinger/command.js +2 -6
- package/dist/webfinger/error.js +2 -6
- package/dist/webfinger/lib.js +3 -8
- package/dist/webfinger/mod.js +4 -5
- package/package.json +11 -11
package/dist/nodeinfo.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { configContext } from "./config.js";
|
|
5
3
|
import { userAgentOption } from "./options.js";
|
|
6
4
|
import { colors, formatObject } from "./utils.js";
|
|
7
|
-
import os from "node:os";
|
|
8
|
-
import process from "node:process";
|
|
9
5
|
import { argument, command, constant, flag, group, merge, message, object, string, text } from "@optique/core";
|
|
10
6
|
import { print, printError } from "@optique/run";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import process from "node:process";
|
|
11
9
|
import { bindConfig } from "@optique/config";
|
|
12
10
|
import { getNodeInfo } from "@fedify/fedify";
|
|
13
11
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -17,7 +15,6 @@ import { createJimp } from "@jimp/core";
|
|
|
17
15
|
import webp from "@jimp/wasm-webp";
|
|
18
16
|
import { isICO, parseICO } from "icojs";
|
|
19
17
|
import { defaultFormats, defaultPlugins, intToRGBA } from "jimp";
|
|
20
|
-
|
|
21
18
|
//#region src/nodeinfo.ts
|
|
22
19
|
const logger = getLogger([
|
|
23
20
|
"fedify",
|
|
@@ -58,44 +55,44 @@ const nodeInfoCommand = command("nodeinfo", merge(object("Arguments", {
|
|
|
58
55
|
|
|
59
56
|
The argument is the hostname of the remote node, or the URL of the remote node.`
|
|
60
57
|
});
|
|
61
|
-
async function runNodeInfo(command
|
|
58
|
+
async function runNodeInfo(command) {
|
|
62
59
|
const spinner = ora({
|
|
63
60
|
text: "Fetching a NodeInfo document...",
|
|
64
61
|
discardStdin: false
|
|
65
62
|
}).start();
|
|
66
|
-
const url = new URL(URL.canParse(command
|
|
67
|
-
if (command
|
|
68
|
-
const nodeInfo
|
|
63
|
+
const url = new URL(URL.canParse(command.host) ? command.host : `https://${command.host}`);
|
|
64
|
+
if (command.raw) {
|
|
65
|
+
const nodeInfo = await getNodeInfo(url, {
|
|
69
66
|
parse: "none",
|
|
70
|
-
userAgent: command
|
|
67
|
+
userAgent: command.userAgent
|
|
71
68
|
});
|
|
72
|
-
if (nodeInfo
|
|
69
|
+
if (nodeInfo === void 0) {
|
|
73
70
|
spinner.fail("No NodeInfo document found.");
|
|
74
71
|
printError(message`No NodeInfo document found.`);
|
|
75
72
|
process.exit(1);
|
|
76
73
|
}
|
|
77
74
|
spinner.succeed("NodeInfo document fetched.");
|
|
78
|
-
print(message`${text(formatObject(nodeInfo
|
|
75
|
+
print(message`${text(formatObject(nodeInfo, void 0, true))}`);
|
|
79
76
|
return;
|
|
80
77
|
}
|
|
81
78
|
const nodeInfo = await getNodeInfo(url, {
|
|
82
|
-
parse: command
|
|
83
|
-
userAgent: command
|
|
79
|
+
parse: command.bestEffort ? "best-effort" : "strict",
|
|
80
|
+
userAgent: command.userAgent
|
|
84
81
|
});
|
|
85
82
|
logger.debug("NodeInfo document: {nodeInfo}", { nodeInfo });
|
|
86
83
|
if (nodeInfo == void 0) {
|
|
87
84
|
spinner.fail("No NodeInfo document found or it is invalid.");
|
|
88
85
|
printError(message`No NodeInfo document found or it is invalid.`);
|
|
89
|
-
if (!command
|
|
86
|
+
if (!command.bestEffort) printError(message`Use the -b/--best-effort option to try to parse the document anyway.`);
|
|
90
87
|
process.exit(1);
|
|
91
88
|
}
|
|
92
89
|
let layout;
|
|
93
90
|
let defaultWidth = 0;
|
|
94
|
-
if (!command
|
|
91
|
+
if (!command.noFavicon) {
|
|
95
92
|
spinner.text = "Fetching the favicon...";
|
|
96
93
|
try {
|
|
97
|
-
const faviconUrl = await getFaviconUrl(url, command
|
|
98
|
-
const response = await fetch(faviconUrl, { headers: { "User-Agent": command
|
|
94
|
+
const faviconUrl = await getFaviconUrl(url, command.userAgent);
|
|
95
|
+
const response = await fetch(faviconUrl, { headers: { "User-Agent": command.userAgent == null ? getUserAgent() : command.userAgent } });
|
|
99
96
|
if (response.ok) {
|
|
100
97
|
const contentType = response.headers.get("Content-Type");
|
|
101
98
|
let buffer = await response.arrayBuffer();
|
|
@@ -104,9 +101,7 @@ async function runNodeInfo(command$1) {
|
|
|
104
101
|
if (images.length < 1) throw new Error("No images found in the ICO file.");
|
|
105
102
|
buffer = images[0].buffer;
|
|
106
103
|
}
|
|
107
|
-
|
|
108
|
-
const colorSupport = checkTerminalColorSupport();
|
|
109
|
-
layout = getAsciiArt(image, DEFAULT_IMAGE_WIDTH, colorSupport, colors).split("\n").map((line) => ` ${line} `);
|
|
104
|
+
layout = getAsciiArt(await Jimp.read(buffer), DEFAULT_IMAGE_WIDTH, checkTerminalColorSupport(), colors).split("\n").map((line) => ` ${line} `);
|
|
110
105
|
defaultWidth = 41;
|
|
111
106
|
} else {
|
|
112
107
|
logger.error("Failed to fetch the favicon: {status} {statusText}", {
|
|
@@ -164,25 +159,25 @@ async function runNodeInfo(command$1) {
|
|
|
164
159
|
layout[next()] += colors.bold(colors.dim("Open registrations:"));
|
|
165
160
|
layout[next()] += " " + (nodeInfo.openRegistrations ? "Yes" : "No");
|
|
166
161
|
}
|
|
167
|
-
if (command
|
|
162
|
+
if (command.metadata && nodeInfo.metadata != null && Object.keys(nodeInfo.metadata).length > 0) {
|
|
168
163
|
layout[next()] += colors.bold(colors.dim("Metadata:"));
|
|
169
|
-
for (const [key, value
|
|
164
|
+
for (const [key, value] of Object.entries(nodeInfo.metadata)) layout[next()] += ` ${colors.dim(key + ":")} ${indent(typeof value === "string" ? value : formatObject(value), defaultWidth + 4 + key.length)}`;
|
|
170
165
|
}
|
|
171
166
|
console.log(layout.join("\n"));
|
|
172
167
|
}
|
|
173
|
-
function indent(text
|
|
174
|
-
return text
|
|
168
|
+
function indent(text, depth) {
|
|
169
|
+
return text.replace(/\n/g, "\n" + " ".repeat(depth));
|
|
175
170
|
}
|
|
176
171
|
const LINK_REGEXP = /<link((?:\s+(?:[-a-z]+)=(?:"[^"]*"|'[^']*'|[^\s]+))*)\s*\/?>/gi;
|
|
177
172
|
const LINK_ATTRS_REGEXP = /(?:\s+([-a-z]+)=("[^"]*"|'[^']*'|[^\s]+))/gi;
|
|
178
173
|
async function getFaviconUrl(url, userAgent) {
|
|
179
174
|
const response = await fetch(url, { headers: { "User-Agent": userAgent == null ? getUserAgent() : userAgent } });
|
|
180
|
-
const text
|
|
181
|
-
for (const match of text
|
|
175
|
+
const text = await response.text();
|
|
176
|
+
for (const match of text.matchAll(LINK_REGEXP)) {
|
|
182
177
|
const attrs = {};
|
|
183
178
|
for (const attrMatch of match[1].matchAll(LINK_ATTRS_REGEXP)) {
|
|
184
|
-
const [, key, value
|
|
185
|
-
attrs[key] = value
|
|
179
|
+
const [, key, value] = attrMatch;
|
|
180
|
+
attrs[key] = value.startsWith("\"") || value.startsWith("'") ? value.slice(1, -1) : value;
|
|
186
181
|
}
|
|
187
182
|
const rel = attrs.rel?.toLowerCase()?.trim()?.split(/\s+/) ?? [];
|
|
188
183
|
if (!rel.includes("icon") && !rel.includes("apple-touch-icon")) continue;
|
|
@@ -220,11 +215,11 @@ const CUBE_VALUES = [
|
|
|
220
215
|
215,
|
|
221
216
|
255
|
|
222
217
|
];
|
|
223
|
-
const findClosestIndex = (value
|
|
218
|
+
const findClosestIndex = (value) => {
|
|
224
219
|
let minDiff = Infinity;
|
|
225
220
|
let closestIndex = 0;
|
|
226
221
|
for (let idx = 0; idx < CUBE_VALUES.length; idx++) {
|
|
227
|
-
const diff = Math.abs(value
|
|
222
|
+
const diff = Math.abs(value - CUBE_VALUES[idx]);
|
|
228
223
|
if (diff < minDiff) {
|
|
229
224
|
minDiff = diff;
|
|
230
225
|
closestIndex = idx;
|
|
@@ -234,10 +229,8 @@ const findClosestIndex = (value$1) => {
|
|
|
234
229
|
};
|
|
235
230
|
function rgbTo256Color(r, g, b) {
|
|
236
231
|
const gray = Math.round((r + g + b) / 3);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const isExactCubeValue = CUBE_VALUES.includes(r) && r === g && g === b;
|
|
240
|
-
if (!isExactCubeValue) {
|
|
232
|
+
if (Math.abs(r - gray) <= 5 && Math.abs(g - gray) <= 5 && Math.abs(b - gray) <= 5) {
|
|
233
|
+
if (!(CUBE_VALUES.includes(r) && r === g && g === b)) {
|
|
241
234
|
if (gray < 8) return 232;
|
|
242
235
|
if (gray > 238) return 255;
|
|
243
236
|
const grayIndex = Math.round((gray - 8) / 10);
|
|
@@ -249,7 +242,7 @@ function rgbTo256Color(r, g, b) {
|
|
|
249
242
|
const b6 = findClosestIndex(b);
|
|
250
243
|
return 16 + 36 * r6 + 6 * g6 + b6;
|
|
251
244
|
}
|
|
252
|
-
function getAsciiArt(image, width = DEFAULT_IMAGE_WIDTH, colorSupport, colors
|
|
245
|
+
function getAsciiArt(image, width = DEFAULT_IMAGE_WIDTH, colorSupport, colors) {
|
|
253
246
|
const ratio = image.width / image.height;
|
|
254
247
|
const height = Math.round(width / ratio * .5);
|
|
255
248
|
image.resize({
|
|
@@ -259,25 +252,22 @@ function getAsciiArt(image, width = DEFAULT_IMAGE_WIDTH, colorSupport, colors$1)
|
|
|
259
252
|
let art = "";
|
|
260
253
|
for (let y = 0; y < height; y++) {
|
|
261
254
|
for (let x = 0; x < width; x++) {
|
|
262
|
-
const
|
|
263
|
-
const color = intToRGBA(pixel);
|
|
255
|
+
const color = intToRGBA(image.getPixelColor(x, y));
|
|
264
256
|
if (color.a < 1) {
|
|
265
257
|
art += " ";
|
|
266
258
|
continue;
|
|
267
259
|
}
|
|
268
260
|
const brightness = (color.r + color.g + color.b) / 3;
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
if (colorSupport === "truecolor") art += colors$1.rgb(color.r, color.g, color.b)(char);
|
|
261
|
+
const char = ASCII_CHARS[Math.round(brightness / 255 * 72)];
|
|
262
|
+
if (colorSupport === "truecolor") art += colors.rgb(color.r, color.g, color.b)(char);
|
|
272
263
|
else if (colorSupport === "256color") {
|
|
273
264
|
const colorIndex = rgbTo256Color(color.r, color.g, color.b);
|
|
274
|
-
art += colors
|
|
265
|
+
art += colors.ansi256(colorIndex)(char);
|
|
275
266
|
} else art += char;
|
|
276
267
|
}
|
|
277
268
|
if (y < height - 1) art += "\n";
|
|
278
269
|
}
|
|
279
270
|
return art;
|
|
280
271
|
}
|
|
281
|
-
|
|
282
272
|
//#endregion
|
|
283
|
-
export { Jimp, nodeInfoCommand, runNodeInfo };
|
|
273
|
+
export { Jimp, nodeInfoCommand, runNodeInfo };
|
package/dist/options.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { configContext } from "./config.js";
|
|
5
3
|
import { choice, constant, flag, map, merge, message, object, option, or, string, withDefault } from "@optique/core";
|
|
6
4
|
import { bindConfig } from "@optique/config";
|
|
7
5
|
import { getUserAgent } from "@fedify/vocab-runtime";
|
|
8
|
-
|
|
9
6
|
//#region src/options.ts
|
|
10
7
|
/**
|
|
11
8
|
* Available tunneling services for exposing local servers to the public internet.
|
|
@@ -18,8 +15,8 @@ const TUNNEL_SERVICES = [
|
|
|
18
15
|
/**
|
|
19
16
|
* Creates a tunnel service option with customizable option names.
|
|
20
17
|
*/
|
|
21
|
-
function createTunnelServiceOption(optionNames
|
|
22
|
-
return withDefault(bindConfig(option(...optionNames
|
|
18
|
+
function createTunnelServiceOption(optionNames = ["--tunnel-service"]) {
|
|
19
|
+
return withDefault(bindConfig(option(...optionNames, choice(TUNNEL_SERVICES, { metavar: "SERVICE" }), { description: message`The tunneling service to use.
|
|
23
20
|
By default, any of the supported tunneling services will be used
|
|
24
21
|
(randomly selected for each tunnel).` }), {
|
|
25
22
|
context: configContext,
|
|
@@ -54,31 +51,17 @@ const userAgentOption = object({ userAgent: bindConfig(option("-u", "--user-agen
|
|
|
54
51
|
default: getUserAgent()
|
|
55
52
|
}) });
|
|
56
53
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* These options are mutually exclusive:
|
|
60
|
-
* - `--config PATH` loads an additional config file on top of standard hierarchy
|
|
61
|
-
* - `--ignore-config` skips all config files (useful for CI reproducibility)
|
|
54
|
+
* Global options that apply to all commands.
|
|
62
55
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* - `{ ignoreConfig: false, configPath: string }` when `--config` is specified
|
|
66
|
-
* - `{ ignoreConfig: false }` when neither is specified (default)
|
|
56
|
+
* Combines debug mode and configuration file options into a single
|
|
57
|
+
* "Global options" group.
|
|
67
58
|
*/
|
|
68
|
-
const
|
|
59
|
+
const globalOptions = merge("Global options", debugOption, withDefault(or(object({ ignoreConfig: map(flag("--ignore-config", { description: message`Ignore all configuration files.` }), () => true) }), object({
|
|
69
60
|
ignoreConfig: constant(false),
|
|
70
61
|
configPath: option("--config", string({ metavar: "PATH" }), { description: message`Load an additional configuration file.` })
|
|
71
62
|
})), {
|
|
72
63
|
ignoreConfig: false,
|
|
73
64
|
configPath: void 0
|
|
74
|
-
});
|
|
75
|
-
/**
|
|
76
|
-
* Global options that apply to all commands.
|
|
77
|
-
*
|
|
78
|
-
* Combines debug mode and configuration file options into a single
|
|
79
|
-
* "Global options" group.
|
|
80
|
-
*/
|
|
81
|
-
const globalOptions = merge("Global options", debugOption, configOption);
|
|
82
|
-
|
|
65
|
+
}));
|
|
83
66
|
//#endregion
|
|
84
|
-
export { createTunnelOption, createTunnelServiceOption, globalOptions, userAgentOption };
|
|
67
|
+
export { createTunnelOption, createTunnelServiceOption, globalOptions, userAgentOption };
|
package/dist/relay.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { configContext } from "./config.js";
|
|
5
3
|
import { configureLogging } from "./log.js";
|
|
6
4
|
import { createTunnelOption } from "./options.js";
|
|
7
5
|
import { tableStyle } from "./table.js";
|
|
8
6
|
import { spawnTemporaryServer } from "./tempserver.js";
|
|
9
7
|
import { colors, matchesActor } from "./utils.js";
|
|
10
|
-
import { SqliteKvStore } from "@fedify/sqlite";
|
|
11
|
-
import process from "node:process";
|
|
12
|
-
import { DatabaseSync } from "node:sqlite";
|
|
13
8
|
import { command, constant, group, integer, merge, message, multiple, object, option, optionName, optional, string, value } from "@optique/core";
|
|
9
|
+
import process from "node:process";
|
|
14
10
|
import { bindConfig } from "@optique/config";
|
|
15
11
|
import { MemoryKvStore } from "@fedify/fedify";
|
|
16
12
|
import { getLogger } from "@logtape/logtape";
|
|
17
13
|
import Table from "cli-table3";
|
|
18
14
|
import ora from "ora";
|
|
19
15
|
import { createRelay } from "@fedify/relay";
|
|
16
|
+
import { SqliteKvStore } from "@fedify/sqlite";
|
|
20
17
|
import { choice as choice$1 } from "@optique/core/valueparser";
|
|
21
|
-
|
|
18
|
+
import { DatabaseSync } from "node:sqlite";
|
|
22
19
|
//#region src/relay.ts
|
|
23
20
|
const logger = getLogger([
|
|
24
21
|
"fedify",
|
|
@@ -66,17 +63,16 @@ const relayCommand = command("relay", merge(object("Relay options", {
|
|
|
66
63
|
|
|
67
64
|
By default, the server is tunneled to the public internet for external access. Use ${optionName("--no-tunnel")} to run locally only.`
|
|
68
65
|
});
|
|
69
|
-
async function runRelay(command
|
|
70
|
-
if (command
|
|
66
|
+
async function runRelay(command) {
|
|
67
|
+
if (command.debug) await configureLogging();
|
|
71
68
|
const spinner = ora({
|
|
72
69
|
text: "Starting relay server...",
|
|
73
70
|
discardStdin: false
|
|
74
71
|
}).start();
|
|
75
72
|
let kv;
|
|
76
|
-
if (command
|
|
77
|
-
logger.debug("Using SQLite storage at {path}.", { path: command
|
|
78
|
-
|
|
79
|
-
kv = new SqliteKvStore(db);
|
|
73
|
+
if (command.persistent) {
|
|
74
|
+
logger.debug("Using SQLite storage at {path}.", { path: command.persistent });
|
|
75
|
+
kv = new SqliteKvStore(new DatabaseSync(command.persistent));
|
|
80
76
|
} else {
|
|
81
77
|
logger.debug("Using in-memory storage.");
|
|
82
78
|
kv = new MemoryKvStore();
|
|
@@ -85,18 +81,18 @@ async function runRelay(command$1) {
|
|
|
85
81
|
let server = null;
|
|
86
82
|
const acceptFollows = [];
|
|
87
83
|
const rejectFollows = [];
|
|
88
|
-
if (command
|
|
89
|
-
if (command
|
|
84
|
+
if (command.acceptFollow != null && command.acceptFollow.length > 0) acceptFollows.push(...command.acceptFollow ?? []);
|
|
85
|
+
if (command.rejectFollow != null && command.rejectFollow.length > 0) rejectFollows.push(...command.rejectFollow ?? []);
|
|
90
86
|
server = await spawnTemporaryServer(async (request) => {
|
|
91
87
|
return await relay.fetch(request);
|
|
92
88
|
}, {
|
|
93
|
-
noTunnel: !command
|
|
94
|
-
port: command
|
|
95
|
-
...command
|
|
89
|
+
noTunnel: !command.tunnel,
|
|
90
|
+
port: command.port,
|
|
91
|
+
...command.tunnel && { service: command.tunnelService }
|
|
96
92
|
});
|
|
97
|
-
relay = createRelay(command
|
|
93
|
+
relay = createRelay(command.protocol, {
|
|
98
94
|
origin: server?.url.origin,
|
|
99
|
-
name: command
|
|
95
|
+
name: command.name,
|
|
100
96
|
kv,
|
|
101
97
|
subscriptionHandler: async (_ctx, actor) => {
|
|
102
98
|
const isInAcceptList = await matchesActor(actor, acceptFollows);
|
|
@@ -106,9 +102,9 @@ async function runRelay(command$1) {
|
|
|
106
102
|
});
|
|
107
103
|
spinner.succeed(`Relay server is running: ${colors.green(server.url.href)}`);
|
|
108
104
|
await printRelayInfo(relay, {
|
|
109
|
-
protocol: command
|
|
110
|
-
name: command
|
|
111
|
-
persistent: command
|
|
105
|
+
protocol: command.protocol,
|
|
106
|
+
name: command.name,
|
|
107
|
+
persistent: command.persistent
|
|
112
108
|
});
|
|
113
109
|
process.on("SIGINT", async () => {
|
|
114
110
|
spinner.start("Shutting down relay server...");
|
|
@@ -131,6 +127,5 @@ async function printRelayInfo(relay, options) {
|
|
|
131
127
|
console.log(table.toString());
|
|
132
128
|
console.log("\nPress ^C to stop the relay server.");
|
|
133
129
|
}
|
|
134
|
-
|
|
135
130
|
//#endregion
|
|
136
|
-
export { relayCommand, runRelay };
|
|
131
|
+
export { relayCommand, runRelay };
|
package/dist/table.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
//#region src/table.ts
|
|
5
3
|
const tableStyle = {
|
|
6
4
|
top: "─",
|
|
@@ -19,6 +17,5 @@ const tableStyle = {
|
|
|
19
17
|
rightMid: "┤",
|
|
20
18
|
middle: "│"
|
|
21
19
|
};
|
|
22
|
-
|
|
23
20
|
//#endregion
|
|
24
|
-
export { tableStyle };
|
|
21
|
+
export { tableStyle };
|
package/dist/tempserver.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { getLogger } from "@logtape/logtape";
|
|
5
3
|
import { openTunnel } from "@hongminhee/localtunnel";
|
|
6
4
|
import { serve } from "srvx";
|
|
7
|
-
|
|
8
5
|
//#region src/tempserver.ts
|
|
9
6
|
const logger = getLogger([
|
|
10
7
|
"fedify",
|
|
@@ -14,28 +11,27 @@ const logger = getLogger([
|
|
|
14
11
|
async function spawnTemporaryServer(fetch, options = {}) {
|
|
15
12
|
const serverPort = options.port ?? 0;
|
|
16
13
|
if (options.noTunnel) {
|
|
17
|
-
const server
|
|
14
|
+
const server = serve({
|
|
18
15
|
port: serverPort,
|
|
19
16
|
hostname: "::",
|
|
20
17
|
silent: true,
|
|
21
18
|
fetch
|
|
22
19
|
});
|
|
23
|
-
await server
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
logger.debug("Temporary server is listening on port {port}.", { port: port$1 });
|
|
20
|
+
await server.ready();
|
|
21
|
+
const port = new URL(server.url).port;
|
|
22
|
+
logger.debug("Temporary server is listening on port {port}.", { port });
|
|
27
23
|
return {
|
|
28
|
-
url: new URL(`http://localhost:${port
|
|
24
|
+
url: new URL(`http://localhost:${port}`),
|
|
29
25
|
async close() {
|
|
30
|
-
await server
|
|
26
|
+
await server.close();
|
|
31
27
|
}
|
|
32
28
|
};
|
|
33
29
|
}
|
|
34
30
|
const server = serve({
|
|
35
31
|
fetch: "Deno" in globalThis ? (request) => {
|
|
36
|
-
const url
|
|
37
|
-
url
|
|
38
|
-
|
|
32
|
+
const url = new URL(request.url);
|
|
33
|
+
url.protocol = "https:";
|
|
34
|
+
return fetch(new Request(url, {
|
|
39
35
|
method: request.method,
|
|
40
36
|
headers: request.headers,
|
|
41
37
|
body: request.method === "GET" || request.method === "HEAD" ? null : request.body,
|
|
@@ -48,8 +44,7 @@ async function spawnTemporaryServer(fetch, options = {}) {
|
|
|
48
44
|
integrity: request.integrity,
|
|
49
45
|
keepalive: request.keepalive,
|
|
50
46
|
signal: request.signal
|
|
51
|
-
});
|
|
52
|
-
return fetch(newRequest);
|
|
47
|
+
}));
|
|
53
48
|
} : fetch,
|
|
54
49
|
port: serverPort,
|
|
55
50
|
hostname: "::",
|
|
@@ -57,8 +52,7 @@ async function spawnTemporaryServer(fetch, options = {}) {
|
|
|
57
52
|
protocol: "https"
|
|
58
53
|
});
|
|
59
54
|
await server.ready();
|
|
60
|
-
const
|
|
61
|
-
const port = url.port;
|
|
55
|
+
const port = new URL(server.url).port;
|
|
62
56
|
logger.debug("Temporary server is listening on port {port}.", { port });
|
|
63
57
|
const tun = await openTunnel({
|
|
64
58
|
port: parseInt(port),
|
|
@@ -73,6 +67,5 @@ async function spawnTemporaryServer(fetch, options = {}) {
|
|
|
73
67
|
}
|
|
74
68
|
};
|
|
75
69
|
}
|
|
76
|
-
|
|
77
70
|
//#endregion
|
|
78
|
-
export { spawnTemporaryServer };
|
|
71
|
+
export { spawnTemporaryServer };
|
package/dist/tunnel.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { configureLogging } from "./log.js";
|
|
5
3
|
import { createTunnelServiceOption } from "./options.js";
|
|
6
|
-
import process from "node:process";
|
|
7
4
|
import { argument, command, constant, integer, merge, message, object } from "@optique/core";
|
|
8
5
|
import { print, printError } from "@optique/run";
|
|
6
|
+
import process from "node:process";
|
|
9
7
|
import ora from "ora";
|
|
10
8
|
import { openTunnel } from "@hongminhee/localtunnel";
|
|
11
|
-
|
|
12
9
|
//#region src/tunnel.ts
|
|
13
10
|
const tunnelCommand = command("tunnel", merge("Tunnel options", object({ command: constant("tunnel") }), object({
|
|
14
11
|
port: argument(integer({
|
|
@@ -23,12 +20,12 @@ const tunnelCommand = command("tunnel", merge("Tunnel options", object({ command
|
|
|
23
20
|
|
|
24
21
|
Note that the HTTP requests through the tunnel have X-Forwarded-* headers.`
|
|
25
22
|
});
|
|
26
|
-
async function runTunnel(command
|
|
23
|
+
async function runTunnel(command, deps = {
|
|
27
24
|
openTunnel,
|
|
28
25
|
ora,
|
|
29
26
|
exit: process.exit
|
|
30
27
|
}) {
|
|
31
|
-
if (command
|
|
28
|
+
if (command.debug) await configureLogging();
|
|
32
29
|
const spinner = deps.ora({
|
|
33
30
|
text: "Creating a secure tunnel...",
|
|
34
31
|
discardStdin: false
|
|
@@ -36,21 +33,20 @@ async function runTunnel(command$1, deps = {
|
|
|
36
33
|
let tunnel;
|
|
37
34
|
try {
|
|
38
35
|
tunnel = await deps.openTunnel({
|
|
39
|
-
port: command
|
|
40
|
-
service: command
|
|
36
|
+
port: command.port,
|
|
37
|
+
service: command.service
|
|
41
38
|
});
|
|
42
39
|
} catch (error) {
|
|
43
|
-
if (command
|
|
40
|
+
if (command.debug) printError(message`${String(error)}`);
|
|
44
41
|
spinner.fail("Failed to create a secure tunnel.");
|
|
45
42
|
deps.exit(1);
|
|
46
43
|
}
|
|
47
|
-
spinner.succeed(`Your local server at ${command
|
|
44
|
+
spinner.succeed(`Your local server at ${command.port} is now publicly accessible:\n`);
|
|
48
45
|
print(message`${tunnel.url.href}`);
|
|
49
46
|
print(message`\nPress ^C to close the tunnel.`);
|
|
50
47
|
process.on("SIGINT", async () => {
|
|
51
48
|
await tunnel.close();
|
|
52
49
|
});
|
|
53
50
|
}
|
|
54
|
-
|
|
55
51
|
//#endregion
|
|
56
|
-
export { runTunnel, tunnelCommand };
|
|
52
|
+
export { runTunnel, tunnelCommand };
|
package/dist/utils.js
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
4
|
-
import "node:fs/promises";
|
|
5
|
-
import process from "node:process";
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
6
2
|
import { message } from "@optique/core";
|
|
7
3
|
import { print, printError } from "@optique/run";
|
|
8
4
|
import { flow } from "es-toolkit";
|
|
5
|
+
import process from "node:process";
|
|
9
6
|
import { getActorHandle } from "@fedify/vocab";
|
|
10
7
|
import util from "node:util";
|
|
11
8
|
import "@fxts/core";
|
|
12
9
|
import { Chalk } from "chalk";
|
|
13
10
|
import { highlight } from "cli-highlight";
|
|
14
|
-
import "node:child_process";
|
|
15
|
-
|
|
16
11
|
//#region src/utils.ts
|
|
17
12
|
const colorEnabled = process.stdout.isTTY && !("NO_COLOR" in process.env && process.env.NO_COLOR !== "");
|
|
18
13
|
const colors = new Chalk(colorEnabled ? {} : { level: 0 });
|
|
19
|
-
function formatObject(obj, colors
|
|
20
|
-
const enableColors = colors
|
|
14
|
+
function formatObject(obj, colors, json) {
|
|
15
|
+
const enableColors = colors ?? colorEnabled;
|
|
21
16
|
if (!json) return util.inspect(obj, { colors: enableColors });
|
|
22
17
|
const formatted = JSON.stringify(obj, null, 2);
|
|
23
18
|
if (enableColors) return highlight(formatted, { language: "json" });
|
|
@@ -38,8 +33,7 @@ async function matchesActor(actor, actorList) {
|
|
|
38
33
|
}
|
|
39
34
|
return false;
|
|
40
35
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
flow(message, print);
|
|
37
|
+
flow(message, printError);
|
|
44
38
|
//#endregion
|
|
45
|
-
export { colorEnabled, colors, formatObject, matchesActor };
|
|
39
|
+
export { colorEnabled, colors, formatObject, matchesActor };
|
package/dist/webfinger/action.js
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { formatObject } from "../utils.js";
|
|
5
3
|
import { NotFoundError, getErrorMessage } from "./error.js";
|
|
6
4
|
import { convertUrlIfHandle } from "./lib.js";
|
|
@@ -8,18 +6,15 @@ import { print } from "@optique/run";
|
|
|
8
6
|
import { formatMessage, message } from "@optique/core/message";
|
|
9
7
|
import ora from "ora";
|
|
10
8
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
11
|
-
|
|
12
9
|
//#region src/webfinger/action.ts
|
|
13
|
-
async function runWebFinger({ command: _, resources
|
|
10
|
+
async function runWebFinger({ command: _, resources, ...options }) {
|
|
14
11
|
await Array.fromAsync(resources.map((resource) => ({
|
|
15
12
|
resource,
|
|
16
13
|
...options
|
|
17
14
|
})), spinnerWrapper(lookupSingleWebFinger));
|
|
18
15
|
}
|
|
19
|
-
async function lookupSingleWebFinger({ resource
|
|
20
|
-
|
|
21
|
-
const webFinger = await lookupWebFinger(url, options) ?? new NotFoundError(resource).throw();
|
|
22
|
-
return webFinger;
|
|
16
|
+
async function lookupSingleWebFinger({ resource, ...options }) {
|
|
17
|
+
return await lookupWebFinger(convertUrlIfHandle(resource), options) ?? new NotFoundError(resource).throw();
|
|
23
18
|
}
|
|
24
19
|
function spinnerWrapper(func) {
|
|
25
20
|
return async (...args) => {
|
|
@@ -39,6 +34,5 @@ function spinnerWrapper(func) {
|
|
|
39
34
|
}
|
|
40
35
|
};
|
|
41
36
|
}
|
|
42
|
-
|
|
43
37
|
//#endregion
|
|
44
|
-
export { runWebFinger };
|
|
38
|
+
export { runWebFinger as default };
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { configContext } from "../config.js";
|
|
5
3
|
import { userAgentOption } from "../options.js";
|
|
6
4
|
import { argument, command, constant, flag, group, integer, merge, message, multiple, object, option, string } from "@optique/core";
|
|
7
5
|
import { bindConfig } from "@optique/config";
|
|
8
|
-
|
|
9
6
|
//#region src/webfinger/command.ts
|
|
10
7
|
const allowPrivateAddresses = bindConfig(flag("-p", "--allow-private-address", { description: message`Allow private IP addresses in the URL.` }), {
|
|
11
8
|
context: configContext,
|
|
@@ -28,6 +25,5 @@ const webFingerCommand = command("webfinger", merge("Network options", object({
|
|
|
28
25
|
|
|
29
26
|
The argument can be multiple.`
|
|
30
27
|
});
|
|
31
|
-
|
|
32
28
|
//#endregion
|
|
33
|
-
export { webFingerCommand };
|
|
29
|
+
export { webFingerCommand };
|
package/dist/webfinger/error.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { message } from "@optique/core";
|
|
5
|
-
|
|
6
3
|
//#region src/webfinger/error.ts
|
|
7
4
|
/**
|
|
8
5
|
* Generates a user-friendly error message based on the type of error
|
|
@@ -42,6 +39,5 @@ var NotFoundError = class extends Error {
|
|
|
42
39
|
throw this;
|
|
43
40
|
}
|
|
44
41
|
};
|
|
45
|
-
|
|
46
42
|
//#endregion
|
|
47
|
-
export { InvalidHandleError, NotFoundError, getErrorMessage };
|
|
43
|
+
export { InvalidHandleError, NotFoundError, getErrorMessage };
|
package/dist/webfinger/lib.js
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { Temporal } from "@js-temporal/polyfill";
|
|
3
|
-
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
4
2
|
import { InvalidHandleError } from "./error.js";
|
|
5
3
|
import { toAcctUrl } from "@fedify/vocab";
|
|
6
4
|
import { getLogger } from "@logtape/logtape";
|
|
7
|
-
|
|
8
|
-
//#region src/webfinger/lib.ts
|
|
9
|
-
const logger = getLogger([
|
|
5
|
+
getLogger([
|
|
10
6
|
"fedify",
|
|
11
7
|
"cli",
|
|
12
8
|
"webfinger"
|
|
@@ -40,6 +36,5 @@ function convertUrlIfHandle(handleOrUrl) {
|
|
|
40
36
|
function convertHandleToUrl(handle) {
|
|
41
37
|
return toAcctUrl(handle) ?? new InvalidHandleError(handle).throw();
|
|
42
38
|
}
|
|
43
|
-
|
|
44
39
|
//#endregion
|
|
45
|
-
export { convertUrlIfHandle };
|
|
40
|
+
export { convertUrlIfHandle };
|
package/dist/webfinger/mod.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { webFingerCommand } from "./command.js";
|
|
1
|
+
import "@js-temporal/polyfill";
|
|
2
|
+
import "./action.js";
|
|
3
|
+
import "./command.js";
|
|
4
|
+
export {};
|