@fedify/cli 2.0.7 → 2.0.9

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/lookup.js CHANGED
@@ -1,6 +1,4 @@
1
-
2
- import { Temporal } from "@js-temporal/polyfill";
3
-
1
+ import "@js-temporal/polyfill";
4
2
  import { configContext } from "./config.js";
5
3
  import { getContextLoader, getDocumentLoader } from "./docloader.js";
6
4
  import { configureLogging } from "./log.js";
@@ -8,16 +6,15 @@ import { createTunnelServiceOption, userAgentOption } from "./options.js";
8
6
  import { spawnTemporaryServer } from "./tempserver.js";
9
7
  import { colorEnabled, colors, formatObject } from "./utils.js";
10
8
  import { renderImages } from "./imagerenderer.js";
11
- import process from "node:process";
12
9
  import { argument, choice, command, constant, flag, float, map, merge, message, multiple, object, option, optionNames, optional, or, string, withDefault } from "@optique/core";
13
10
  import { path, print, printError } from "@optique/run";
14
11
  import { createWriteStream } from "node:fs";
12
+ import process from "node:process";
15
13
  import { bindConfig } from "@optique/config";
16
14
  import { generateCryptoKeyPair, getAuthenticatedDocumentLoader, respondWithObject } from "@fedify/fedify";
17
15
  import { Application, Collection, CryptographicKey, Object as Object$1, lookupObject, traverseCollection } from "@fedify/vocab";
18
16
  import { getLogger } from "@logtape/logtape";
19
17
  import ora from "ora";
20
-
21
18
  //#region src/lookup.ts
22
19
  const logger = getLogger([
23
20
  "fedify",
@@ -82,8 +79,8 @@ The arguments can be either URLs or actor handles (e.g., ${"@username@domain"}),
82
79
  });
83
80
  var TimeoutError = class extends Error {
84
81
  name = "TimeoutError";
85
- constructor(message$1) {
86
- super(message$1);
82
+ constructor(message) {
83
+ super(message);
87
84
  this.name = "TimeoutError";
88
85
  }
89
86
  };
@@ -95,34 +92,32 @@ async function findAllImages(obj) {
95
92
  if (image && image.url instanceof URL) result.push(image.url);
96
93
  return result;
97
94
  }
98
- async function writeObjectToStream(object$1, outputPath, format, contextLoader) {
95
+ async function writeObjectToStream(object, outputPath, format, contextLoader) {
99
96
  const stream = outputPath ? createWriteStream(outputPath) : process.stdout;
100
97
  let content;
101
98
  let json = true;
102
99
  let imageUrls = [];
103
- if (format) if (format === "raw") content = await object$1.toJsonLd({ contextLoader });
104
- else if (format === "compact") content = await object$1.toJsonLd({
100
+ if (format) if (format === "raw") content = await object.toJsonLd({ contextLoader });
101
+ else if (format === "compact") content = await object.toJsonLd({
105
102
  format: "compact",
106
103
  contextLoader
107
104
  });
108
- else if (format === "expand") content = await object$1.toJsonLd({
105
+ else if (format === "expand") content = await object.toJsonLd({
109
106
  format: "expand",
110
107
  contextLoader
111
108
  });
112
109
  else {
113
- content = object$1;
110
+ content = object;
114
111
  json = false;
115
112
  }
116
113
  else {
117
- content = object$1;
114
+ content = object;
118
115
  json = false;
119
116
  }
120
- const enableColors = colorEnabled && outputPath === void 0;
121
- content = formatObject(content, enableColors, json);
122
- const encoder = new TextEncoder();
123
- const bytes = encoder.encode(content + "\n");
117
+ content = formatObject(content, colorEnabled && outputPath === void 0, json);
118
+ const bytes = new TextEncoder().encode(content + "\n");
124
119
  stream.write(bytes);
125
- if (object$1 instanceof Object$1) imageUrls = await findAllImages(object$1);
120
+ if (object instanceof Object$1) imageUrls = await findAllImages(object);
126
121
  if (!outputPath && imageUrls.length > 0) await renderImages(imageUrls);
127
122
  }
128
123
  const signalTimers = /* @__PURE__ */ new WeakMap();
@@ -158,23 +153,21 @@ function handleTimeoutError(spinner, timeoutSeconds, url) {
158
153
  spinner.fail(`Request timed out after ${timeoutSeconds} seconds${urlText}.`);
159
154
  printError(message`Try increasing the timeout with -T/--timeout option or check network connectivity.`);
160
155
  }
161
- async function runLookup(command$1) {
162
- if (command$1.urls.length < 1) {
156
+ async function runLookup(command) {
157
+ if (command.urls.length < 1) {
163
158
  printError(message`At least one URL or actor handle must be provided.`);
164
159
  process.exit(1);
165
160
  }
166
- if (command$1.debug) await configureLogging();
161
+ if (command.debug) await configureLogging();
167
162
  const spinner = ora({
168
- text: `Looking up the ${command$1.traverse ? "collection" : command$1.urls.length > 1 ? "objects" : "object"}...`,
163
+ text: `Looking up the ${command.traverse ? "collection" : command.urls.length > 1 ? "objects" : "object"}...`,
169
164
  discardStdin: false
170
165
  }).start();
171
166
  let server = void 0;
172
- const baseDocumentLoader = await getDocumentLoader({ userAgent: command$1.userAgent });
173
- const documentLoader = wrapDocumentLoaderWithTimeout(baseDocumentLoader, command$1.timeout);
174
- const baseContextLoader = await getContextLoader({ userAgent: command$1.userAgent });
175
- const contextLoader = wrapDocumentLoaderWithTimeout(baseContextLoader, command$1.timeout);
167
+ const documentLoader = wrapDocumentLoaderWithTimeout(await getDocumentLoader({ userAgent: command.userAgent }), command.timeout);
168
+ const contextLoader = wrapDocumentLoaderWithTimeout(await getContextLoader({ userAgent: command.userAgent }), command.timeout);
176
169
  let authLoader = void 0;
177
- if (command$1.authorizedFetch) {
170
+ if (command.authorizedFetch) {
178
171
  spinner.text = "Generating a one-time key pair...";
179
172
  const key = await generateCryptoKeyPair();
180
173
  spinner.text = "Spinning up a temporary ActivityPub server...";
@@ -204,33 +197,32 @@ async function runLookup(command$1) {
204
197
  inbox: new URL("/inbox", serverUrl),
205
198
  outbox: new URL("/outbox", serverUrl)
206
199
  }), { contextLoader });
207
- }, { service: command$1.tunnelService });
208
- const baseAuthLoader = getAuthenticatedDocumentLoader({
200
+ }, { service: command.tunnelService });
201
+ authLoader = wrapDocumentLoaderWithTimeout(getAuthenticatedDocumentLoader({
209
202
  keyId: new URL("#main-key", server.url),
210
203
  privateKey: key.privateKey
211
204
  }, { specDeterminer: {
212
205
  determineSpec() {
213
- return command$1.firstKnock;
206
+ return command.firstKnock;
214
207
  },
215
208
  rememberSpec() {}
216
- } });
217
- authLoader = wrapDocumentLoaderWithTimeout(baseAuthLoader, command$1.timeout);
209
+ } }), command.timeout);
218
210
  }
219
- spinner.text = `Looking up the ${command$1.traverse ? "collection" : command$1.urls.length > 1 ? "objects" : "object"}...`;
220
- if (command$1.traverse) {
211
+ spinner.text = `Looking up the ${command.traverse ? "collection" : command.urls.length > 1 ? "objects" : "object"}...`;
212
+ if (command.traverse) {
221
213
  let totalItems = 0;
222
- for (let urlIndex = 0; urlIndex < command$1.urls.length; urlIndex++) {
223
- const url = command$1.urls[urlIndex];
224
- if (urlIndex > 0) spinner.text = `Looking up collection ${urlIndex + 1}/${command$1.urls.length}...`;
214
+ for (let urlIndex = 0; urlIndex < command.urls.length; urlIndex++) {
215
+ const url = command.urls[urlIndex];
216
+ if (urlIndex > 0) spinner.text = `Looking up collection ${urlIndex + 1}/${command.urls.length}...`;
225
217
  let collection;
226
218
  try {
227
219
  collection = await lookupObject(url, {
228
220
  documentLoader: authLoader ?? documentLoader,
229
221
  contextLoader,
230
- userAgent: command$1.userAgent
222
+ userAgent: command.userAgent
231
223
  });
232
224
  } catch (error) {
233
- if (error instanceof TimeoutError) handleTimeoutError(spinner, command$1.timeout, url);
225
+ if (error instanceof TimeoutError) handleTimeoutError(spinner, command.timeout, url);
234
226
  else {
235
227
  spinner.fail(`Failed to fetch object: ${colors.red(url)}.`);
236
228
  if (authLoader == null) printError(message`It may be a private object. Try with -a/--authorized-fetch.`);
@@ -255,10 +247,10 @@ async function runLookup(command$1) {
255
247
  for await (const item of traverseCollection(collection, {
256
248
  documentLoader: authLoader ?? documentLoader,
257
249
  contextLoader,
258
- suppressError: command$1.suppressErrors
250
+ suppressError: command.suppressErrors
259
251
  })) {
260
- if (!command$1.output && (totalItems > 0 || collectionItems > 0)) print(message`${command$1.separator}`);
261
- await writeObjectToStream(item, command$1.output, command$1.format, contextLoader);
252
+ if (!command.output && (totalItems > 0 || collectionItems > 0)) print(message`${command.separator}`);
253
+ await writeObjectToStream(item, command.output, command.format, contextLoader);
262
254
  collectionItems++;
263
255
  totalItems++;
264
256
  }
@@ -267,7 +259,7 @@ async function runLookup(command$1) {
267
259
  url,
268
260
  error
269
261
  });
270
- if (error instanceof TimeoutError) handleTimeoutError(spinner, command$1.timeout, url);
262
+ if (error instanceof TimeoutError) handleTimeoutError(spinner, command.timeout, url);
271
263
  else {
272
264
  spinner.fail(`Failed to complete the traversal for: ${colors.red(url)}.`);
273
265
  if (authLoader == null) printError(message`It may be a private object. Try with -a/--authorized-fetch.`);
@@ -282,12 +274,12 @@ async function runLookup(command$1) {
282
274
  process.exit(0);
283
275
  }
284
276
  const promises = [];
285
- for (const url of command$1.urls) promises.push(lookupObject(url, {
277
+ for (const url of command.urls) promises.push(lookupObject(url, {
286
278
  documentLoader: authLoader ?? documentLoader,
287
279
  contextLoader,
288
- userAgent: command$1.userAgent
280
+ userAgent: command.userAgent
289
281
  }).catch((error) => {
290
- if (error instanceof TimeoutError) handleTimeoutError(spinner, command$1.timeout, url);
282
+ if (error instanceof TimeoutError) handleTimeoutError(spinner, command.timeout, url);
291
283
  throw error;
292
284
  }));
293
285
  let objects;
@@ -301,8 +293,8 @@ async function runLookup(command$1) {
301
293
  let success = true;
302
294
  let i = 0;
303
295
  for (const obj of objects) {
304
- const url = command$1.urls[i];
305
- if (i > 0) print(message`${command$1.separator}`);
296
+ const url = command.urls[i];
297
+ if (i > 0) print(message`${command.separator}`);
306
298
  i++;
307
299
  if (obj == null) {
308
300
  spinner.fail(`Failed to fetch ${colors.red(url)}`);
@@ -310,15 +302,14 @@ async function runLookup(command$1) {
310
302
  success = false;
311
303
  } else {
312
304
  spinner.succeed(`Fetched object: ${colors.green(url)}`);
313
- await writeObjectToStream(obj, command$1.output, command$1.format, contextLoader);
314
- if (i < command$1.urls.length - 1) print(message`${command$1.separator}`);
305
+ await writeObjectToStream(obj, command.output, command.format, contextLoader);
306
+ if (i < command.urls.length - 1) print(message`${command.separator}`);
315
307
  }
316
308
  }
317
- if (success) spinner.succeed(command$1.urls.length > 1 ? "Successfully fetched all objects." : "Successfully fetched the object.");
309
+ if (success) spinner.succeed(command.urls.length > 1 ? "Successfully fetched all objects." : "Successfully fetched the object.");
318
310
  await server?.close();
319
311
  if (!success) process.exit(1);
320
- if (success && command$1.output) spinner.succeed(`Successfully wrote output to ${colors.green(command$1.output)}.`);
312
+ if (success && command.output) spinner.succeed(`Successfully wrote output to ${colors.green(command.output)}.`);
321
313
  }
322
-
323
314
  //#endregion
324
- export { lookupCommand, runLookup };
315
+ export { lookupCommand, runLookup };
package/dist/mod.js CHANGED
@@ -1,12 +1,10 @@
1
1
  #!/usr/bin/env -S node --disable-warning=ExperimentalWarning
2
-
3
- import { Temporal } from "@js-temporal/polyfill";
4
-
2
+ import "@js-temporal/polyfill";
5
3
  import { configContext, tryLoadToml } from "./config.js";
6
- import { runGenerateVocab } from "./generate-vocab/action.js";
7
- import command_default from "./generate-vocab/command.js";
4
+ import runGenerateVocab from "./generate-vocab/action.js";
5
+ import generateVocabCommand from "./generate-vocab/command.js";
8
6
  import "./generate-vocab/mod.js";
9
- import deno_default from "./deno.js";
7
+ import { version } from "./deno.js";
10
8
  import { globalOptions } from "./options.js";
11
9
  import { inboxCommand, runInbox } from "./inbox.js";
12
10
  import { initCommand, runInit } from "./init/mod.js";
@@ -14,19 +12,18 @@ import { nodeInfoCommand, runNodeInfo } from "./nodeinfo.js";
14
12
  import { lookupCommand, runLookup } from "./lookup.js";
15
13
  import { relayCommand, runRelay } from "./relay.js";
16
14
  import { runTunnel, tunnelCommand } from "./tunnel.js";
17
- import { runWebFinger } from "./webfinger/action.js";
15
+ import runWebFinger from "./webfinger/action.js";
18
16
  import { webFingerCommand } from "./webfinger/command.js";
19
17
  import "./webfinger/mod.js";
20
- import { join } from "node:path";
21
- import { homedir } from "node:os";
22
- import process from "node:process";
23
18
  import { runWithConfig } from "@optique/config/run";
24
19
  import { group, merge, message, or } from "@optique/core";
25
20
  import { printError } from "@optique/run";
26
21
  import { merge as merge$1 } from "es-toolkit";
27
22
  import { readFileSync } from "node:fs";
23
+ import { homedir } from "node:os";
24
+ import { join } from "node:path";
25
+ import process from "node:process";
28
26
  import { parse } from "smol-toml";
29
-
30
27
  //#region src/mod.ts
31
28
  /**
32
29
  * Returns the system-wide configuration file paths.
@@ -34,10 +31,7 @@ import { parse } from "smol-toml";
34
31
  * - Windows: Uses `%ProgramData%` (default: C:\ProgramData)
35
32
  */
36
33
  function getSystemConfigPaths() {
37
- if (process.platform === "win32") {
38
- const programData = process.env.ProgramData || "C:\\ProgramData";
39
- return [join(programData, "fedify", "config.toml")];
40
- }
34
+ if (process.platform === "win32") return [join(process.env.ProgramData || "C:\\ProgramData", "fedify", "config.toml")];
41
35
  return (process.env.XDG_CONFIG_DIRS || "/etc/xdg").split(":").map((dir) => join(dir, "fedify", "config.toml"));
42
36
  }
43
37
  /**
@@ -46,21 +40,16 @@ function getSystemConfigPaths() {
46
40
  * - Windows: `%APPDATA%\fedify\config.toml`
47
41
  */
48
42
  function getUserConfigPath() {
49
- if (process.platform === "win32") {
50
- const appData = process.env.APPDATA || join(homedir(), "AppData", "Roaming");
51
- return join(appData, "fedify", "config.toml");
52
- }
53
- const xdgConfigHome = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
54
- return join(xdgConfigHome, "fedify", "config.toml");
43
+ if (process.platform === "win32") return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), "fedify", "config.toml");
44
+ return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), "fedify", "config.toml");
55
45
  }
56
- const command$1 = merge(or(group("Generating code", or(initCommand, command_default)), group("ActivityPub tools", or(webFingerCommand, lookupCommand, inboxCommand, nodeInfoCommand, relayCommand)), group("Network tools", tunnelCommand)), globalOptions);
46
+ const command$1 = merge(or(group("Generating code", or(initCommand, generateVocabCommand)), group("ActivityPub tools", or(webFingerCommand, lookupCommand, inboxCommand, nodeInfoCommand, relayCommand)), group("Network tools", tunnelCommand)), globalOptions);
57
47
  async function main() {
58
48
  const result = await runWithConfig(command$1, configContext, {
59
49
  programName: "fedify",
60
50
  load: (parsed) => {
61
51
  if (parsed.ignoreConfig) return {};
62
- const systemConfigs = getSystemConfigPaths().map(tryLoadToml);
63
- const system = systemConfigs.reduce((acc, config) => merge$1(acc, config), {});
52
+ const system = getSystemConfigPaths().map(tryLoadToml).reduce((acc, config) => merge$1(acc, config), {});
64
53
  const user = tryLoadToml(getUserConfigPath());
65
54
  const project = tryLoadToml(join(process.cwd(), ".fedify.toml"));
66
55
  let custom = {};
@@ -85,7 +74,7 @@ async function main() {
85
74
  },
86
75
  version: {
87
76
  mode: "both",
88
- value: deno_default.version,
77
+ value: version,
89
78
  group: "Meta commands"
90
79
  },
91
80
  completion: {
@@ -108,10 +97,7 @@ async function main() {
108
97
  else if (result.command === "tunnel") await runTunnel(result);
109
98
  else if (result.command === "generate-vocab") await runGenerateVocab(result);
110
99
  else if (result.command === "relay") await runRelay(result);
111
- else {
112
- const _exhaustiveCheck = result;
113
- }
114
100
  }
115
101
  await main();
116
-
117
- //#endregion
102
+ //#endregion
103
+ export {};
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$1) {
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$1.host) ? command$1.host : `https://${command$1.host}`);
67
- if (command$1.raw) {
68
- const nodeInfo$1 = await getNodeInfo(url, {
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$1.userAgent
67
+ userAgent: command.userAgent
71
68
  });
72
- if (nodeInfo$1 === void 0) {
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$1, void 0, true))}`);
75
+ print(message`${text(formatObject(nodeInfo, void 0, true))}`);
79
76
  return;
80
77
  }
81
78
  const nodeInfo = await getNodeInfo(url, {
82
- parse: command$1.bestEffort ? "best-effort" : "strict",
83
- userAgent: command$1.userAgent
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$1.bestEffort) printError(message`Use the -b/--best-effort option to try to parse the document anyway.`);
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$1.noFavicon) {
91
+ if (!command.noFavicon) {
95
92
  spinner.text = "Fetching the favicon...";
96
93
  try {
97
- const faviconUrl = await getFaviconUrl(url, command$1.userAgent);
98
- const response = await fetch(faviconUrl, { headers: { "User-Agent": command$1.userAgent == null ? getUserAgent() : command$1.userAgent } });
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
- const image = await Jimp.read(buffer);
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$1.metadata && nodeInfo.metadata != null && Object.keys(nodeInfo.metadata).length > 0) {
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$1] of Object.entries(nodeInfo.metadata)) layout[next()] += ` ${colors.dim(key + ":")} ${indent(typeof value$1 === "string" ? value$1 : formatObject(value$1), defaultWidth + 4 + key.length)}`;
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$1, depth) {
174
- return text$1.replace(/\n/g, "\n" + " ".repeat(depth));
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$1 = await response.text();
181
- for (const match of text$1.matchAll(LINK_REGEXP)) {
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$1] = attrMatch;
185
- attrs[key] = value$1.startsWith("\"") || value$1.startsWith("'") ? value$1.slice(1, -1) : value$1;
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$1) => {
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$1 - CUBE_VALUES[idx]);
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
- const isGrayscale = Math.abs(r - gray) <= 5 && Math.abs(g - gray) <= 5 && Math.abs(b - gray) <= 5;
238
- if (isGrayscale) {
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$1) {
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 pixel = image.getPixelColor(x, y);
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 charIndex = Math.round(brightness / 255 * 72);
270
- const char = ASCII_CHARS[charIndex];
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$1.ansi256(colorIndex)(char);
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$1 = ["--tunnel-service"]) {
22
- return withDefault(bindConfig(option(...optionNames$1, choice(TUNNEL_SERVICES, { metavar: "SERVICE" }), { description: message`The tunneling service to use.
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
- * Configuration file options.
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
- * Returns either:
64
- * - `{ ignoreConfig: true }` when `--ignore-config` is specified
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 configOption = withDefault(or(object({ ignoreConfig: map(flag("--ignore-config", { description: message`Ignore all configuration files.` }), () => true) }), object({
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 };