From d507c79568d21ffabab219b79b4a52dbdb819799 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Fri, 30 Jan 2026 16:58:03 +0900 Subject: [PATCH 01/35] Remove globals.ts and relocate its contents to appropriate modules The globals.ts file mixed unrelated concerns: CLI option definitions and logging configuration. This refactoring improves code organization by moving each piece to its natural home: - debugOption moved to options.ts, where all other CLI options are defined - configureLogging() moved to log.ts, where recordingSink and other logging utilities already reside This eliminates globals.ts entirely and makes the codebase easier to navigate by grouping related functionality together. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/globals.ts | 43 --------------------------- packages/cli/src/inbox.tsx | 5 ++-- packages/cli/src/log.ts | 35 ++++++++++++++++++++-- packages/cli/src/lookup.ts | 4 +-- packages/cli/src/nodeinfo.ts | 4 +-- packages/cli/src/options.ts | 6 ++++ packages/cli/src/relay.ts | 6 ++-- packages/cli/src/tunnel.ts | 5 ++-- packages/cli/src/webfinger/command.ts | 2 +- 9 files changed, 51 insertions(+), 59 deletions(-) delete mode 100644 packages/cli/src/globals.ts diff --git a/packages/cli/src/globals.ts b/packages/cli/src/globals.ts deleted file mode 100644 index b6699e387..000000000 --- a/packages/cli/src/globals.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { getFileSink } from "@logtape/file"; -import { configure, getConsoleSink } from "@logtape/logtape"; -import { message, object, option } from "@optique/core"; -import { AsyncLocalStorage } from "node:async_hooks"; -import process from "node:process"; -import { recordingSink } from "./log.ts"; - -export const debugOption = object("Global options", { - debug: option("-d", "--debug", { - description: message`Enable debug mode.`, - }), -}); - -export async function configureLogging() { - const logFile = process.env["FEDIFY_LOG_FILE"]; - await configure({ - sinks: { - console: getConsoleSink(), - recording: recordingSink, - file: logFile == null ? () => undefined : getFileSink(logFile), - }, - filters: {}, - loggers: [ - { - category: "fedify", - lowestLevel: "debug", - sinks: ["console", "recording", "file"], - }, - { - category: "localtunnel", - lowestLevel: "debug", - sinks: ["console", "file"], - }, - { - category: ["logtape", "meta"], - lowestLevel: "warning", - sinks: ["console", "file"], - }, - ], - reset: true, - contextLocalStorage: new AsyncLocalStorage(), - }); -} diff --git a/packages/cli/src/inbox.tsx b/packages/cli/src/inbox.tsx index 0cc841935..7d1af7793 100644 --- a/packages/cli/src/inbox.tsx +++ b/packages/cli/src/inbox.tsx @@ -43,11 +43,10 @@ import process from "node:process"; import ora from "ora"; import metadata from "../deno.json" with { type: "json" }; import { getDocumentLoader } from "./docloader.ts"; -import { configureLogging, debugOption } from "./globals.ts"; -import { tunnelOption } from "./options.ts"; import type { ActivityEntry } from "./inbox/entry.ts"; import { ActivityEntryPage, ActivityListPage } from "./inbox/view.tsx"; -import { recordingSink } from "./log.ts"; +import { configureLogging, recordingSink } from "./log.ts"; +import { debugOption, tunnelOption } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; diff --git a/packages/cli/src/log.ts b/packages/cli/src/log.ts index 971c3b3e9..10c0ac48a 100644 --- a/packages/cli/src/log.ts +++ b/packages/cli/src/log.ts @@ -5,10 +5,10 @@ import { type LogRecord, type Sink, } from "@logtape/logtape"; -import { dirname } from "node:path"; -import process from "node:process"; import { AsyncLocalStorage } from "node:async_hooks"; import { mkdir } from "node:fs/promises"; +import { dirname } from "node:path"; +import process from "node:process"; export interface RecordingSink extends Sink { startRecording(): void; @@ -62,3 +62,34 @@ await configure({ contextLocalStorage: new AsyncLocalStorage(), reset: true, }); + +export async function configureLogging() { + const logFile = process.env["FEDIFY_LOG_FILE"]; + await configure({ + sinks: { + console: getConsoleSink(), + recording: recordingSink, + file: logFile == null ? () => undefined : getFileSink(logFile), + }, + filters: {}, + loggers: [ + { + category: "fedify", + lowestLevel: "debug", + sinks: ["console", "recording", "file"], + }, + { + category: "localtunnel", + lowestLevel: "debug", + sinks: ["console", "file"], + }, + { + category: ["logtape", "meta"], + lowestLevel: "warning", + sinks: ["console", "file"], + }, + ], + reset: true, + contextLocalStorage: new AsyncLocalStorage(), + }); +} diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 15c6d182a..99a3c0047 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -40,9 +40,9 @@ import { createWriteStream, type WriteStream } from "node:fs"; import process from "node:process"; import ora from "ora"; import { getContextLoader, getDocumentLoader } from "./docloader.ts"; -import { configureLogging, debugOption } from "./globals.ts"; import { renderImages } from "./imagerenderer.ts"; -import { tunnelServiceOption } from "./options.ts"; +import { configureLogging } from "./log.ts"; +import { debugOption, tunnelServiceOption } from "./options.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colorEnabled, colors, formatObject } from "./utils.ts"; diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index 32eb039d3..f1dc5d754 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -22,10 +22,10 @@ import { print, printError } from "@optique/run"; import type { ChalkInstance } from "chalk"; import { isICO, parseICO } from "icojs"; import { defaultFormats, defaultPlugins, intToRGBA } from "jimp"; -import ora from "ora"; import os from "node:os"; import process from "node:process"; -import { debugOption } from "./globals.ts"; +import ora from "ora"; +import { debugOption } from "./options.ts"; import { colors, formatObject } from "./utils.ts"; const logger = getLogger(["fedify", "cli", "nodeinfo"]); diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index 86d19a6d2..e3cf2253e 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -63,3 +63,9 @@ export const tunnelOption = or( tunnelService: tunnelServiceOption, }), ); + +export const debugOption = object("Global options", { + debug: option("-d", "--debug", { + description: message`Enable debug mode.`, + }), +}); diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index 291836302..822d0ebcc 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -20,11 +20,11 @@ import { } from "@optique/core"; import { choice } from "@optique/core/valueparser"; import Table from "cli-table3"; -import { DatabaseSync } from "node:sqlite"; import process from "node:process"; +import { DatabaseSync } from "node:sqlite"; import ora from "ora"; -import { configureLogging, debugOption } from "./globals.ts"; -import { tunnelOption } from "./options.ts"; +import { configureLogging } from "./log.ts"; +import { debugOption, tunnelOption } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; diff --git a/packages/cli/src/tunnel.ts b/packages/cli/src/tunnel.ts index 13f49637a..33730b71b 100644 --- a/packages/cli/src/tunnel.ts +++ b/packages/cli/src/tunnel.ts @@ -13,12 +13,11 @@ import { valueSet, } from "@optique/core"; import { choice } from "@optique/core/valueparser"; -import { TUNNEL_SERVICES } from "./options.ts"; import { print, printError } from "@optique/run"; import process from "node:process"; import ora from "ora"; -import { configureLogging, debugOption } from "./globals.ts"; - +import { configureLogging } from "./log.ts"; +import { debugOption, TUNNEL_SERVICES } from "./options.ts"; export const tunnelCommand = command( "tunnel", merge( diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 4ab6e8e0a..6f0259391 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -14,7 +14,7 @@ import { string, withDefault, } from "@optique/core"; -import { debugOption } from "../globals.ts"; +import { debugOption } from "../options.ts"; const userAgent = optional(option( "-u", From 8d0f2f705f136be06d202444f670ab16b0dd32b1 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Fri, 30 Jan 2026 17:12:30 +0900 Subject: [PATCH 02/35] Add unified configuration module for CLI Introduce config.ts that consolidates configuration handling: - Valibot schemas for validating config structure (global debug option, command-specific sections for webfinger, lookup, inbox, relay, nodeinfo) - TOML parsing via smol-toml library - Hierarchical config loading from system (/etc/fedify/config.toml), user (~/.config/fedify/config.toml), and project (.fedify.toml) levels - Recursive merging where later configs override earlier ones This lays the groundwork for issue fedify-dev/fedify#265. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 211 +++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 packages/cli/src/config.ts diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts new file mode 100644 index 000000000..7098436ca --- /dev/null +++ b/packages/cli/src/config.ts @@ -0,0 +1,211 @@ +import { message } from "@optique/core"; +import { printError } from "@optique/run"; +import { readFile } from "node:fs/promises"; +import { homedir } from "node:os"; +import { join } from "node:path"; +import { env, exit } from "node:process"; +import { parse as parseToml, type TomlTable } from "smol-toml"; +import { + boolean, + type InferOutput, + number, + object, + optional, + picklist, + safeParse, + string, +} from "valibot"; + +/** + * Schema for the webfinger command configuration. + */ +const webfingerSchema = object({ + userAgent: optional(string()), + allowPrivateAddress: optional(boolean()), + maxRedirection: optional(number()), +}); + +/** + * Schema for the lookup command configuration. + */ +const lookupSchema = object({ + authorizedFetch: optional(boolean()), + traverse: optional(boolean()), + suppressErrors: optional(boolean()), + userAgent: optional(string()), + timeout: optional(number()), +}); + +/** + * Schema for the inbox command configuration. + */ +const inboxSchema = object({ + tunnel: optional(boolean()), + tunnelService: optional( + picklist(["localhost.run", "serveo.net", "pinggy.io"]), + ), + actorName: optional(string()), + actorSummary: optional(string()), + authorizedFetch: optional(boolean()), +}); + +/** + * Schema for the relay command configuration. + */ +const relaySchema = object({ + protocol: optional(picklist(["mastodon", "litepub"])), + port: optional(number()), + name: optional(string()), + tunnel: optional(boolean()), + tunnelService: optional( + picklist(["localhost.run", "serveo.net", "pinggy.io"]), + ), +}); + +/** + * Schema for the nodeinfo command configuration. + */ +const nodeinfoSchema = object({ + userAgent: optional(string()), +}); + +/** + * Schema for the complete configuration file. + */ +export const configSchema = object({ + // Global settings + debug: optional(boolean()), + + // Command-specific sections + webfinger: optional(webfingerSchema), + lookup: optional(lookupSchema), + inbox: optional(inboxSchema), + relay: optional(relaySchema), + nodeinfo: optional(nodeinfoSchema), +}); + +/** + * Type representing the configuration file structure. + */ +export type Config = InferOutput; + +function getUserConfigPath(): string { + const xdgConfigHome = env.XDG_CONFIG_HOME; + const baseDir = xdgConfigHome || join(homedir(), ".config"); + return join(baseDir, "fedify", "config.toml"); +} + +/** + * Default config file paths in order of priority (lowest to highest). + */ +const CONFIG_PATHS = [ + "/etc/fedify/config.toml", + getUserConfigPath(), + ".fedify.toml", +]; + +async function loadConfigFile(configPath: string): Promise { + let contents: string; + try { + contents = await readFile(configPath, "utf-8"); + } catch { + // silently fail when it failed to read file + return null; + } + return contents; +} + +function parseConfigFile(contents: string, configPath: string): Config | null { + let toml: TomlTable; + try { + toml = parseToml(contents); + } catch { + printError(message`Invalid TOML syntax in ${configPath}`); + return null; + } + + const results = safeParse(configSchema, toml); + if (!results.success) { + printError( + message`Invalid configuration in ${configPath}: ${ + results.issues[0].message + }`, + ); + return null; + } + return results.output; +} + +function mergeSection( + target: T | undefined, + source: T | undefined, +): T | undefined { + if (!target) return source; + if (!source) return target; + return { ...target, ...source } as T; +} + +function mergeConfig(target: Config, source: Config): Config { + return { + debug: source.debug ?? target.debug, + lookup: mergeSection(target.lookup, source.lookup), + webfinger: mergeSection(target.webfinger, source.webfinger), + inbox: mergeSection(target.inbox, source.inbox), + relay: mergeSection(target.relay, source.relay), + nodeinfo: mergeSection(target.nodeinfo, source.nodeinfo), + }; +} + +/** + * Load and merge configuration from the standard hierarchy. + * + * Priority order (lowest to highest): + * + * 1. /etc/fedify/config.toml (system-wide) + * 2. ~/.config/fedify/config.toml (user) + * 3. ./.fedify.toml (project-local) + * 4. --config PATH (explicit, if provided) + * + * @param explicitConfigPath - Optional explicit config path from --config option + * @param ignoreConfig - If true, skip all config files and return empty config + * @returns The merged configuration object + * @exits 1 if explicit config path is provided but file can't be read or parsed + */ +export async function loadConfig( + explicitConfigPath?: string, + ignoreConfig: boolean = false, +): Promise { + if (ignoreConfig) { + return {}; + } + + let config: Config = {}; + + for (const configPath of CONFIG_PATHS) { + const contents = await loadConfigFile(configPath); + if (!contents) { + continue; + } + const loaded = parseConfigFile(contents, configPath); + if (loaded) { + config = mergeConfig(config, loaded); + } + } + + if (explicitConfigPath) { + const contents = await loadConfigFile(explicitConfigPath); + if (!contents) { + printError( + message`Failed to read config file ${explicitConfigPath}`, + ); + exit(1); + } + const loaded = parseConfigFile(contents, explicitConfigPath); + if (!loaded) { + exit(1); + } + config = mergeConfig(config, loaded); + } + + return config; +} From dabbb49d3a832220246413c9d9060463843718a4 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Fri, 30 Jan 2026 17:19:33 +0900 Subject: [PATCH 03/35] Add --config and --ignore-config CLI options Introduce configOption with two mutually exclusive flags: - -c, --config PATH: loads an additional configuration file on top of the standard hierarchy (system, user, project) - -I, --ignore-config: skips all configuration files entirely, useful for CI environments requiring reproducible behavior Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/options.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index e3cf2253e..af370a8f8 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -8,6 +8,7 @@ import { option, optional, or, + string, valueSet, } from "@optique/core"; @@ -69,3 +70,33 @@ export const debugOption = object("Global options", { description: message`Enable debug mode.`, }), }); + +/** + * Configuration file options. + * + * These options are mutually exclusive: + * - `--config PATH` loads an additional config file on top of standard hierarchy + * - `--ignore-config` skips all config files (useful for CI reproducibility) + * + * Returns either: + * - `{ ignoreConfig: true }` when `--ignore-config` is specified + * - `{ ignoreConfig: false, configPath?: string }` otherwise + */ +export const configOption = or( + object({ + ignoreConfig: map( + flag("-I", "--ignore-config", { + description: message`Ignore all configuration files.`, + }), + () => true as const, + ), + }), + object({ + ignoreConfig: constant(false), + configPath: optional( + option("-c", "--config", string({ metavar: "PATH" }), { + description: message`Load an additional configuration file.`, + }), + ), + }), +); From 5bde9db9b9230070ff7da709b140feb3b3961178 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Wed, 4 Feb 2026 03:42:18 +0900 Subject: [PATCH 04/35] Simplify config module to use Optique's config system The config module now delegates file loading and merging to @optique/config instead of implementing custom logic. This removes: - Manual config file path resolution - Multi-file loading and merging logic - Custom TOML parsing with error handling The configOption now uses withDefault() to properly handle the case when neither --ignore-config nor --config is specified. Also removed short flags (-I, -c) to keep only long flags (--ignore-config, --config) for clarity. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 132 +++--------------------------------- packages/cli/src/options.ts | 35 +++++----- 2 files changed, 27 insertions(+), 140 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 7098436ca..ab7015852 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -1,10 +1,4 @@ -import { message } from "@optique/core"; -import { printError } from "@optique/run"; -import { readFile } from "node:fs/promises"; -import { homedir } from "node:os"; -import { join } from "node:path"; -import { env, exit } from "node:process"; -import { parse as parseToml, type TomlTable } from "smol-toml"; +import { parse as parseToml } from "smol-toml"; import { boolean, type InferOutput, @@ -12,7 +6,6 @@ import { object, optional, picklist, - safeParse, string, } from "valibot"; @@ -89,123 +82,14 @@ export const configSchema = object({ */ export type Config = InferOutput; -function getUserConfigPath(): string { - const xdgConfigHome = env.XDG_CONFIG_HOME; - const baseDir = xdgConfigHome || join(homedir(), ".config"); - return join(baseDir, "fedify", "config.toml"); -} - -/** - * Default config file paths in order of priority (lowest to highest). - */ -const CONFIG_PATHS = [ - "/etc/fedify/config.toml", - getUserConfigPath(), - ".fedify.toml", -]; - -async function loadConfigFile(configPath: string): Promise { - let contents: string; - try { - contents = await readFile(configPath, "utf-8"); - } catch { - // silently fail when it failed to read file - return null; - } - return contents; -} - -function parseConfigFile(contents: string, configPath: string): Config | null { - let toml: TomlTable; - try { - toml = parseToml(contents); - } catch { - printError(message`Invalid TOML syntax in ${configPath}`); - return null; - } - - const results = safeParse(configSchema, toml); - if (!results.success) { - printError( - message`Invalid configuration in ${configPath}: ${ - results.issues[0].message - }`, - ); - return null; - } - return results.output; -} - -function mergeSection( - target: T | undefined, - source: T | undefined, -): T | undefined { - if (!target) return source; - if (!source) return target; - return { ...target, ...source } as T; -} - -function mergeConfig(target: Config, source: Config): Config { - return { - debug: source.debug ?? target.debug, - lookup: mergeSection(target.lookup, source.lookup), - webfinger: mergeSection(target.webfinger, source.webfinger), - inbox: mergeSection(target.inbox, source.inbox), - relay: mergeSection(target.relay, source.relay), - nodeinfo: mergeSection(target.nodeinfo, source.nodeinfo), - }; -} - /** - * Load and merge configuration from the standard hierarchy. - * - * Priority order (lowest to highest): + * TOML parser for Optique config context. + * Parses TOML file contents into a JavaScript object. * - * 1. /etc/fedify/config.toml (system-wide) - * 2. ~/.config/fedify/config.toml (user) - * 3. ./.fedify.toml (project-local) - * 4. --config PATH (explicit, if provided) - * - * @param explicitConfigPath - Optional explicit config path from --config option - * @param ignoreConfig - If true, skip all config files and return empty config - * @returns The merged configuration object - * @exits 1 if explicit config path is provided but file can't be read or parsed + * @param contents - Raw file contents as Uint8Array + * @returns Parsed TOML data */ -export async function loadConfig( - explicitConfigPath?: string, - ignoreConfig: boolean = false, -): Promise { - if (ignoreConfig) { - return {}; - } - - let config: Config = {}; - - for (const configPath of CONFIG_PATHS) { - const contents = await loadConfigFile(configPath); - if (!contents) { - continue; - } - const loaded = parseConfigFile(contents, configPath); - if (loaded) { - config = mergeConfig(config, loaded); - } - } - - if (explicitConfigPath) { - const contents = await loadConfigFile(explicitConfigPath); - if (!contents) { - printError( - message`Failed to read config file ${explicitConfigPath}`, - ); - exit(1); - } - const loaded = parseConfigFile(contents, explicitConfigPath); - if (!loaded) { - exit(1); - } - config = mergeConfig(config, loaded); - } - - return config; +export function parseTomlConfig(contents: Uint8Array): unknown { + const text = new TextDecoder().decode(contents); + return parseToml(text); } diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index af370a8f8..a3bcbec38 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -10,6 +10,7 @@ import { or, string, valueSet, + withDefault, } from "@optique/core"; /** @@ -80,23 +81,25 @@ export const debugOption = object("Global options", { * * Returns either: * - `{ ignoreConfig: true }` when `--ignore-config` is specified - * - `{ ignoreConfig: false, configPath?: string }` otherwise + * - `{ ignoreConfig: false, configPath: string }` when `--config` is specified + * - `{ ignoreConfig: false }` when neither is specified (default) */ -export const configOption = or( - object({ - ignoreConfig: map( - flag("-I", "--ignore-config", { - description: message`Ignore all configuration files.`, - }), - () => true as const, - ), - }), - object({ - ignoreConfig: constant(false), - configPath: optional( - option("-c", "--config", string({ metavar: "PATH" }), { +export const configOption = withDefault( + or( + object({ + ignoreConfig: map( + flag("--ignore-config", { + description: message`Ignore all configuration files.`, + }), + () => true as const, + ), + }), + object({ + ignoreConfig: constant(false), + configPath: option("--config", string({ metavar: "PATH" }), { description: message`Load an additional configuration file.`, }), - ), - }), + }), + ), + { ignoreConfig: false, configPath: undefined } as const, ); From 48fe66c5a7899c3aba49da4736fc93966106a76f Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Wed, 4 Feb 2026 15:38:22 +0900 Subject: [PATCH 05/35] Add hierarchical config file loading with Optique integration Implement config file loading that merges multiple sources in order: 1. /etc/fedify/config.toml (system-wide, silently skipped if missing) 2. ~/.config/fedify/config.toml (user config) 3. ./.fedify.toml (project config) 4. --config PATH (custom, throws on error if specified but missing) Use Optique's runWithConfig with load callback for two-pass parsing, and es-toolkit's merge for deep merging config objects. Co-Authored-By: Claude Opus 4.5 --- deno.lock | 84 ++++++++++++++++++++++++++++++++++++-- packages/cli/deno.json | 39 ++++++++++++++---- packages/cli/package.json | 17 +++++--- packages/cli/src/config.ts | 17 ++++---- packages/cli/src/mod.ts | 64 ++++++++++++++++++++++------- 5 files changed, 184 insertions(+), 37 deletions(-) diff --git a/deno.lock b/deno.lock index ab0a53a06..1bb5b4d39 100644 --- a/deno.lock +++ b/deno.lock @@ -82,6 +82,9 @@ "npm:@opentelemetry/sdk-trace-base@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", + "npm:@optique/config@~0.10.0-dev.346": "0.10.0-dev.377_@standard-schema+spec@1.1.0", + "npm:@optique/core@~0.10.0-dev.346": "0.10.0-dev.377", + "npm:@optique/run@~0.10.0-dev.346": "0.10.0-dev.377", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", "npm:@preact/signals@^2.2.1": "2.5.1_preact@10.19.6", "npm:@preact/signals@^2.3.2": "2.5.1_preact@10.19.6", @@ -102,10 +105,12 @@ "npm:chalk@^5.6.2": "5.6.2", "npm:cli-highlight@^2.1.11": "2.1.11", "npm:cli-table3@~0.6.5": "0.6.5", + "npm:enquirer@^2.4.1": "2.4.1", "npm:env-paths@3": "3.0.0", "npm:es-toolkit@^1.30.0": "1.43.0", "npm:es-toolkit@^1.31.0": "1.43.0", "npm:es-toolkit@^1.39.10": "1.43.0", + "npm:es-toolkit@^1.39.4": "1.43.0", "npm:es-toolkit@^1.42.0": "1.43.0", "npm:es-toolkit@^1.43.0": "1.43.0", "npm:esbuild-wasm@~0.25.11": "0.25.12", @@ -122,6 +127,7 @@ "npm:hono@^4.8.3": "4.11.3", "npm:icojs@~0.19.5": "0.19.5", "npm:inquirer-toggle@^1.0.1": "1.0.1", + "npm:inquirer@^12.9.4": "12.11.1_@types+node@22.19.3", "npm:ioredis@^5.8.2": "5.9.1", "npm:jimp@^1.6.0": "1.6.0", "npm:json-canon@^1.0.1": "1.0.1", @@ -140,12 +146,14 @@ "npm:preact@^10.27.2": "10.28.2", "npm:rollup@^4.50.0": "4.55.1", "npm:shiki@^1.6.4": "1.29.2", + "npm:smol-toml@^1.6.0": "1.6.0", "npm:srvx@~0.8.7": "0.8.16", "npm:structured-field-values@^2.0.4": "2.0.4", "npm:tsdown@~0.18.4": "0.18.4_rolldown@1.0.0-beta.57", "npm:tsx@^4.19.4": "4.21.0", "npm:uri-template-router@1": "1.0.0", "npm:url-template@^3.1.1": "3.1.1", + "npm:valibot@^1.2.0": "1.2.0", "npm:vite@^7.1.3": "7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", "npm:vite@^7.1.4": "7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", "npm:vitest@3.2": "3.2.4_@types+node@22.19.3_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", @@ -274,7 +282,7 @@ "@optique/run@0.9.0": { "integrity": "d71b0a05a1342e874fe1718a01d10384ca6b3de3245ae485f6565d6e2f0c16ad", "dependencies": [ - "jsr:@optique/core" + "jsr:@optique/core@0.9" ] }, "@std/assert@0.224.0": { @@ -2081,6 +2089,22 @@ "@opentelemetry/semantic-conventions@1.39.0": { "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==" }, + "@optique/config@0.10.0-dev.377_@standard-schema+spec@1.1.0": { + "integrity": "sha512-wBZ+GQnuhLU70VvagHJ+4mRdrOxVMOzom5cdJ7teYl2ikVFGHU073vE/2vEg8ELVPc4fbNgqYyNxKB1trQ/oCw==", + "dependencies": [ + "@optique/core", + "@standard-schema/spec" + ] + }, + "@optique/core@0.10.0-dev.377": { + "integrity": "sha512-3Nrn62wbKzs+C8oMsDtIawkNiaWvUWMhTI6hTJex0KpGr7/PmYyTQE5EP9q4MKeNCxZyEC2nLXyYlsO0dMTtlA==" + }, + "@optique/run@0.10.0-dev.377": { + "integrity": "sha512-0whyOg0o+VBV7ziKxwhu2Jph+KUqswExmWIUmxJNI5RmI/XjXMdq1G2Ko5yX1egPsJiLNxjTYylv0e/Lww0Xmg==", + "dependencies": [ + "@optique/core" + ] + }, "@oxc-project/types@0.103.0": { "integrity": "sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==" }, @@ -2832,6 +2856,9 @@ "url-parse" ] }, + "ansi-colors@4.1.3": { + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==" + }, "ansi-escapes@4.3.2": { "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dependencies": [ @@ -3303,6 +3330,13 @@ "encodeurl@2.0.0": { "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" }, + "enquirer@2.4.1": { + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dependencies": [ + "ansi-colors", + "strip-ansi@6.0.1" + ] + }, "env-paths@3.0.0": { "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==" }, @@ -4012,6 +4046,22 @@ "@inquirer/core@8.2.4" ] }, + "inquirer@12.11.1_@types+node@22.19.3": { + "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", + "dependencies": [ + "@inquirer/ansi", + "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/prompts", + "@inquirer/type@3.0.10_@types+node@22.19.3", + "@types/node@22.19.3", + "mute-stream@2.0.0", + "run-async", + "rxjs" + ], + "optionalPeers": [ + "@types/node@22.19.3" + ] + }, "ioredis@5.9.1": { "integrity": "sha512-BXNqFQ66oOsR82g9ajFFsR8ZKrjVvYCLyeML9IvSMAsP56XH2VXBdZjmI11p65nXXJxTEt1hie3J2QeFJVgrtQ==", "dependencies": [ @@ -4960,6 +5010,9 @@ ], "bin": true }, + "run-async@4.0.6": { + "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==" + }, "rxjs@7.8.2": { "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dependencies": [ @@ -5156,6 +5209,9 @@ "totalist" ] }, + "smol-toml@1.6.0": { + "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==" + }, "sonic-boom@4.2.0": { "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", "dependencies": [ @@ -5579,6 +5635,9 @@ "utils-merge@1.0.1": { "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, + "valibot@1.2.0": { + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==" + }, "varint@6.0.0": { "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==" }, @@ -5918,32 +5977,51 @@ "dependencies": [ "jsr:@hongminhee/localtunnel@0.3", "jsr:@hono/hono@^4.8.3", + "jsr:@optique/config@~0.10.0-dev.346", + "jsr:@optique/core@~0.10.0-dev.346", + "jsr:@optique/run@~0.10.0-dev.346", + "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", "npm:@poppanator/http-constants@^1.1.1", + "npm:chalk@^5.6.2", "npm:cli-table3@~0.6.5", "npm:env-paths@3", + "npm:es-toolkit@^1.39.4", "npm:fetch-mock@^12.5.4", "npm:icojs@~0.19.5", + "npm:inquirer-toggle@^1.0.1", "npm:ora@^8.2.0", "npm:shiki@^1.6.4", - "npm:srvx@~0.8.7" + "npm:smol-toml@^1.6.0", + "npm:srvx@~0.8.7", + "npm:valibot@^1.2.0" ], "packageJson": { "dependencies": [ "npm:@hongminhee/localtunnel@0.3", + "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", + "npm:@optique/config@~0.10.0-dev.346", + "npm:@optique/core@~0.10.0-dev.346", + "npm:@optique/run@~0.10.0-dev.346", "npm:@poppanator/http-constants@^1.1.1", + "npm:chalk@^5.6.2", "npm:cli-highlight@^2.1.11", "npm:cli-table3@~0.6.5", + "npm:enquirer@^2.4.1", "npm:env-paths@3", "npm:hono@^4.8.3", "npm:icojs@~0.19.5", + "npm:inquirer-toggle@^1.0.1", + "npm:inquirer@^12.9.4", "npm:jimp@^1.6.0", "npm:ora@^8.2.0", "npm:shiki@^1.6.4", - "npm:srvx@~0.8.7" + "npm:smol-toml@^1.6.0", + "npm:srvx@~0.8.7", + "npm:valibot@^1.2.0" ] } }, diff --git a/packages/cli/deno.json b/packages/cli/deno.json index 61fdf8f63..db7f8f574 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -5,17 +5,27 @@ "exports": "./src/mod.ts", "imports": { "@hongminhee/localtunnel": "jsr:@hongminhee/localtunnel@^0.3.0", + "@inquirer/prompts": "npm:@inquirer/prompts@^7.8.4", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", + "@optique/config": "jsr:@optique/config@^0.10.0-dev.346", + "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.346/run", + "@optique/core": "jsr:@optique/core@^0.10.0-dev.346", + "@optique/run": "jsr:@optique/run@^0.10.0-dev.346", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", + "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", "env-paths": "npm:env-paths@^3.0.0", + "es-toolkit": "npm:es-toolkit@^1.39.4", "fetch-mock": "npm:fetch-mock@^12.5.4", "hono": "jsr:@hono/hono@^4.8.3", "icojs": "npm:icojs@^0.19.5", + "inquirer-toggle": "npm:inquirer-toggle@^1.0.1", "ora": "npm:ora@^8.2.0", "shiki": "npm:shiki@^1.6.4", + "smol-toml": "npm:smol-toml@^1.6.0", "srvx": "npm:srvx@^0.8.7", + "valibot": "npm:valibot@^1.2.0", "#kv": "./src/kv.node.ts" }, "exclude": [ @@ -25,11 +35,7 @@ "fedify-cli-*.zip" ], "publish": { - "exclude": [ - "**/*.test.ts", - "tsdown.config.ts", - "scripts/" - ] + "exclude": ["**/*.test.ts", "tsdown.config.ts", "scripts/"] }, "tasks": { "codegen": "deno task -f @fedify/vocab compile", @@ -57,8 +63,27 @@ "dependencies": [ "codegen" ] + }, + "test-init": { + "command": "FEDIFY_TEST_MODE=true deno run --allow-all src/init/test/mod.ts test-init", + "dependencies": [ + "codegen" + ] } }, - "fmt": {}, - "lint": {} + "fmt": { + "exclude": [ + "src/init/templates/**" + ] + }, + "lint": { + "exclude": [ + "src/init/templates/**" + ] + }, + "test": { + "exclude": [ + "src/init/test/**" + ] + } } diff --git a/packages/cli/package.json b/packages/cli/package.json index 0b220c2b3..00739f904 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -45,7 +45,6 @@ }, "dependencies": { "@fedify/fedify": "workspace:*", - "@fedify/init": "workspace:*", "@fedify/relay": "workspace:*", "@fedify/sqlite": "workspace:*", "@fedify/vocab": "workspace:*", @@ -54,27 +53,34 @@ "@fedify/webfinger": "workspace:*", "@fxts/core": "catalog:", "@hongminhee/localtunnel": "^0.3.0", + "@inquirer/prompts": "^7.8.4", "@jimp/core": "^1.6.0", "@jimp/wasm-webp": "^1.6.0", "@js-temporal/polyfill": "catalog:", "@logtape/file": "catalog:", "@logtape/logtape": "catalog:", - "@optique/core": "catalog:", - "@optique/run": "catalog:", + "@optique/config": "^0.10.0-dev.346", + "@optique/core": "^0.10.0-dev.346", + "@optique/run": "^0.10.0-dev.346", "@poppanator/http-constants": "^1.1.1", "byte-encodings": "catalog:", - "chalk": "catalog:", + "chalk": "^5.6.2", "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", + "enquirer": "^2.4.1", "env-paths": "^3.0.0", "es-toolkit": "catalog:", "fetch-mock": "catalog:", "hono": "^4.8.3", "icojs": "^0.19.5", + "inquirer": "^12.9.4", + "inquirer-toggle": "^1.0.1", "jimp": "^1.6.0", "ora": "^8.2.0", "shiki": "^1.6.4", - "srvx": "^0.8.7" + "smol-toml": "^1.6.0", + "srvx": "^0.8.7", + "valibot": "^1.2.0" }, "devDependencies": { "@types/bun": "catalog:", @@ -89,6 +95,7 @@ "prepublish": "pnpm build", "pretest": "pnpm build", "test": "node --test --experimental-transform-types 'src/**/*.test.ts' '!src/init/test/**'", + "test-init": "deno task test-init", "pretest:bun": "pnpm build", "test:bun": "bun test", "run": "pnpm build && node dist/mod.js", diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index ab7015852..17a4c574c 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -1,3 +1,4 @@ +import { readFileSync } from "node:fs"; import { parse as parseToml } from "smol-toml"; import { boolean, @@ -83,13 +84,13 @@ export const configSchema = object({ export type Config = InferOutput; /** - * TOML parser for Optique config context. - * Parses TOML file contents into a JavaScript object. - * - * @param contents - Raw file contents as Uint8Array - * @returns Parsed TOML data + * Try to load and parse a TOML config file. + * Returns an empty object if the file doesn't exist or fails to parse. */ -export function parseTomlConfig(contents: Uint8Array): unknown { - const text = new TextDecoder().decode(contents); - return parseToml(text); +export function tryLoadToml(path: string): Record { + try { + return parseToml(readFileSync(path, "utf-8")); + } catch { + return {}; + } } diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index f1af67909..60edb2e43 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -1,6 +1,14 @@ #!/usr/bin/env node -import { or } from "@optique/core"; -import { run } from "@optique/run"; +import { createConfigContext } from "@optique/config"; +import { runWithConfig } from "@optique/config/run"; +import { merge, or } from "@optique/core"; +import envPaths from "env-paths"; +import { merge as deepMerge } from "es-toolkit"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import process from "node:process"; +import { parse as parseToml } from "smol-toml"; +import { configSchema, tryLoadToml } from "./config.ts"; import { generateVocabCommand, runGenerateVocab, @@ -9,25 +17,53 @@ import { inboxCommand, runInbox } from "./inbox.tsx"; import { initCommand, runInit } from "./init/mod.ts"; import { lookupCommand, runLookup } from "./lookup.ts"; import { nodeInfoCommand, runNodeInfo } from "./nodeinfo.ts"; +import { configOption } from "./options.ts"; +import { relayCommand, runRelay } from "./relay.ts"; import { runTunnel, tunnelCommand } from "./tunnel.ts"; import { runWebFinger, webFingerCommand } from "./webfinger/mod.ts"; -import { relayCommand, runRelay } from "./relay.ts"; -const command = or( - initCommand, - webFingerCommand, - lookupCommand, - inboxCommand, - nodeInfoCommand, - tunnelCommand, - generateVocabCommand, - relayCommand, +const configContext = createConfigContext({ schema: configSchema }); + +const command = merge( + or( + initCommand, + webFingerCommand, + lookupCommand, + inboxCommand, + nodeInfoCommand, + tunnelCommand, + generateVocabCommand, + relayCommand, + ), + configOption, ); async function main() { - const result = run(command, { + const result = await runWithConfig(command, configContext, { programName: "fedify", - help: "both", + load: (parsed) => { + if (parsed.ignoreConfig) return {}; + + const userConfigDir = envPaths("fedify", { suffix: "" }).config; + const system = tryLoadToml("/etc/fedify/config.toml"); + const user = tryLoadToml(join(userConfigDir, "config.toml")); + const project = tryLoadToml(join(process.cwd(), ".fedify.toml")); + + // Custom config via --config throws on error (required file) + const custom = parsed.configPath + ? parseToml(readFileSync(parsed.configPath, "utf-8")) + : {}; + + return [system, user, project, custom].reduce( + (acc, config) => deepMerge(acc, config), + {}, + ); + }, + args: process.argv.slice(2), + help: { + mode: "both", + onShow: () => process.exit(0), + }, }); if (result.command === "init") { await runInit(result); From 8cb928b9a35c73c8ce1c71bc8d0e2bf060f3f6b5 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 5 Feb 2026 18:24:22 +0900 Subject: [PATCH 06/35] Add bindConfig integration for CLI options Integrate Optique's bindConfig() to allow CLI options to fall back to config file values. Uses type assertion on the key function return type to properly narrow types when defaults are provided. Commands updated: - relay: protocol, port, name - inbox: actorName, actorSummary, authorizedFetch - webfinger: userAgent, allowPrivateAddress, maxRedirection - lookup: userAgent, timeout - nodeinfo: userAgent Also fixes version mismatches across workspace packages (1.10.3). Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 6 ++++ packages/cli/src/inbox.tsx | 35 +++++++++++++++------ packages/cli/src/lookup.ts | 36 ++++++++++++++++------ packages/cli/src/mod.ts | 5 +-- packages/cli/src/nodeinfo.ts | 18 ++++++++--- packages/cli/src/relay.ts | 44 ++++++++++++++++++--------- packages/cli/src/webfinger/command.ts | 41 +++++++++++++++++-------- packages/elysia/deno.json | 7 +++-- packages/fixture/deno.json | 2 +- packages/fresh/deno.json | 6 ++-- packages/lint/deno.json | 7 +++-- packages/lint/package.json | 2 +- packages/relay/deno.json | 7 +++-- packages/relay/package.json | 2 +- packages/vocab-runtime/deno.json | 7 +++-- packages/vocab-runtime/package.json | 2 +- packages/vocab-tools/deno.json | 7 +++-- packages/vocab-tools/package.json | 2 +- packages/vocab/deno.json | 8 +++-- packages/vocab/package.json | 2 +- packages/webfinger/deno.json | 7 +++-- packages/webfinger/package.json | 2 +- 22 files changed, 177 insertions(+), 78 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 17a4c574c..805ed7de0 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -1,3 +1,4 @@ +import { createConfigContext } from "@optique/config"; import { readFileSync } from "node:fs"; import { parse as parseToml } from "smol-toml"; import { @@ -83,6 +84,11 @@ export const configSchema = object({ */ export type Config = InferOutput; +/** + * Config context for use with bindConfig(). + */ +export const configContext = createConfigContext({ schema: configSchema }); + /** * Try to load and parse a TOML config file. * Returns an empty object if the file doesn't exist or fails to parse. diff --git a/packages/cli/src/inbox.tsx b/packages/cli/src/inbox.tsx index 7d1af7793..f7f149653 100644 --- a/packages/cli/src/inbox.tsx +++ b/packages/cli/src/inbox.tsx @@ -23,6 +23,7 @@ import { type Recipient, } from "@fedify/vocab"; import { getLogger } from "@logtape/logtape"; +import { bindConfig } from "@optique/config"; import { command, constant, @@ -34,8 +35,8 @@ import { option, optional, string, - withDefault, } from "@optique/core"; +import { configContext } from "./config.ts"; import Table from "cli-table3"; import { type Context as HonoContext, Hono } from "hono"; import type { BlankEnv, BlankInput } from "hono/types"; @@ -89,24 +90,38 @@ export const inboxCommand = command( }), tunnelOption, object({ - actorName: withDefault( + actorName: bindConfig( option("--actor-name", string({ metavar: "NAME" }), { description: message`Customize the actor display name.`, }), - "Fedify Ephemeral Inbox", + { + context: configContext, + key: (config) => config.inbox?.actorName as string, + default: "Fedify Ephemeral Inbox", + }, ), - actorSummary: withDefault( + actorSummary: bindConfig( option("--actor-summary", string({ metavar: "SUMMARY" }), { description: message`Customize the actor description.`, }), - "An ephemeral ActivityPub inbox for testing purposes.", + { + context: configContext, + key: (config) => config.inbox?.actorSummary as string, + default: "An ephemeral ActivityPub inbox for testing purposes.", + }, ), - authorizedFetch: option( - "-A", - "--authorized-fetch", + authorizedFetch: bindConfig( + optional(option( + "-A", + "--authorized-fetch", + { + description: + message`Enable authorized fetch mode. Incoming requests without valid HTTP signatures will be rejected with 401 Unauthorized.`, + }, + )), { - description: - message`Enable authorized fetch mode. Incoming requests without valid HTTP signatures will be rejected with 401 Unauthorized.`, + context: configContext, + key: (config) => config.inbox?.authorizedFetch, }, ), }), diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 99a3c0047..8f186fd71 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -15,6 +15,7 @@ import { import type { DocumentLoader } from "@fedify/vocab-runtime"; import type { ResourceDescriptor } from "@fedify/webfinger"; import { getLogger } from "@logtape/logtape"; +import { bindConfig } from "@optique/config"; import { argument, choice, @@ -39,6 +40,7 @@ import { path, print, printError } from "@optique/run"; import { createWriteStream, type WriteStream } from "node:fs"; import process from "node:process"; import ora from "ora"; +import { configContext } from "./config.ts"; import { getContextLoader, getDocumentLoader } from "./docloader.ts"; import { renderImages } from "./imagerenderer.ts"; import { configureLogging } from "./log.ts"; @@ -125,10 +127,16 @@ export const lookupCommand = command( ), "default" as const, ), - userAgent: optional( - option("-u", "--user-agent", string({ metavar: "USER_AGENT" }), { - description: message`The custom User-Agent header value.`, - }), + userAgent: bindConfig( + optional( + option("-u", "--user-agent", string({ metavar: "USER_AGENT" }), { + description: message`The custom User-Agent header value.`, + }), + ), + { + context: configContext, + key: (config) => config.lookup?.userAgent, + }, ), separator: withDefault( option("-s", "--separator", string({ metavar: "SEPARATOR" }), { @@ -147,12 +155,20 @@ export const lookupCommand = command( }), { description: message`Specify the output file path.` }, )), - timeout: optional(option( - "-T", - "--timeout", - float({ min: 0, metavar: "SECONDS" }), - { description: message`Set timeout for network requests in seconds.` }, - )), + timeout: bindConfig( + optional(option( + "-T", + "--timeout", + float({ min: 0, metavar: "SECONDS" }), + { + description: message`Set timeout for network requests in seconds.`, + }, + )), + { + context: configContext, + key: (config) => config.lookup?.timeout, + }, + ), }), ), { diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index 60edb2e43..6505d7d97 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -1,5 +1,4 @@ #!/usr/bin/env node -import { createConfigContext } from "@optique/config"; import { runWithConfig } from "@optique/config/run"; import { merge, or } from "@optique/core"; import envPaths from "env-paths"; @@ -8,7 +7,7 @@ import { readFileSync } from "node:fs"; import { join } from "node:path"; import process from "node:process"; import { parse as parseToml } from "smol-toml"; -import { configSchema, tryLoadToml } from "./config.ts"; +import { configContext, tryLoadToml } from "./config.ts"; import { generateVocabCommand, runGenerateVocab, @@ -22,8 +21,6 @@ import { relayCommand, runRelay } from "./relay.ts"; import { runTunnel, tunnelCommand } from "./tunnel.ts"; import { runWebFinger, webFingerCommand } from "./webfinger/mod.ts"; -const configContext = createConfigContext({ schema: configSchema }); - const command = merge( or( initCommand, diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index f1dc5d754..d2201fd53 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -3,6 +3,7 @@ import { getUserAgent } from "@fedify/vocab-runtime"; import { createJimp } from "@jimp/core"; import webp from "@jimp/wasm-webp"; import { getLogger } from "@logtape/logtape"; +import { bindConfig } from "@optique/config"; import { argument, command as Command, @@ -25,6 +26,7 @@ import { defaultFormats, defaultPlugins, intToRGBA } from "jimp"; import os from "node:os"; import process from "node:process"; import ora from "ora"; +import { configContext } from "./config.ts"; import { debugOption } from "./options.ts"; import { colors, formatObject } from "./utils.ts"; @@ -58,11 +60,17 @@ const nodeInfoOption = optional( ), ); -const userAgentOption = optional(object({ - userAgent: option("-u", "--user-agent", string(), { - description: message`The custom User-Agent header value.`, - }), -})); +const userAgentOption = object({ + userAgent: bindConfig( + optional(option("-u", "--user-agent", string(), { + description: message`The custom User-Agent header value.`, + })), + { + context: configContext, + key: (config) => config.nodeinfo?.userAgent, + }, + ), +}); export const nodeInfoCommand = Command( "nodeinfo", diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index 822d0ebcc..ad8cda70f 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -2,6 +2,7 @@ import { MemoryKvStore } from "@fedify/fedify"; import { createRelay, type Relay, type RelayType } from "@fedify/relay"; import { SqliteKvStore } from "@fedify/sqlite"; import { getLogger } from "@logtape/logtape"; +import { bindConfig } from "@optique/config"; import { command, constant, @@ -16,13 +17,13 @@ import { optionName, string, value, - withDefault, } from "@optique/core"; import { choice } from "@optique/core/valueparser"; import Table from "cli-table3"; import process from "node:process"; import { DatabaseSync } from "node:sqlite"; import ora from "ora"; +import { configContext } from "./config.ts"; import { configureLogging } from "./log.ts"; import { debugOption, tunnelOption } from "./options.ts"; import { tableStyle } from "./table.ts"; @@ -36,16 +37,23 @@ export const relayCommand = command( merge( object("Relay options", { command: constant("relay"), - protocol: option( - "-p", - "--protocol", - choice(["mastodon", "litepub"], { metavar: "TYPE" }), + protocol: bindConfig( + option( + "-p", + "--protocol", + choice(["mastodon", "litepub"], { metavar: "TYPE" }), + { + description: message`The relay protocol to use. ${ + value("mastodon") + } for Mastodon-compatible relay, ${ + value("litepub") + } for LitePub-compatible relay.`, + }, + ), { - description: message`The relay protocol to use. ${ - value("mastodon") - } for Mastodon-compatible relay, ${ - value("litepub") - } for LitePub-compatible relay.`, + context: configContext, + key: (config) => config.relay?.protocol as string, + default: "mastodon", }, ), persistent: optional( @@ -54,7 +62,7 @@ export const relayCommand = command( message`Path to SQLite database file for persistent storage. If not specified, uses in-memory storage which is lost when the server stops.`, }), ), - port: withDefault( + port: bindConfig( option( "-P", "--port", @@ -63,13 +71,21 @@ export const relayCommand = command( description: message`The local port to listen on.`, }, ), - 8000, + { + context: configContext, + key: (config) => config.relay?.port as number, + default: 8000, + }, ), - name: withDefault( + name: bindConfig( option("-n", "--name", string({ metavar: "NAME" }), { description: message`The relay display name.`, }), - "Fedify Relay", + { + context: configContext, + key: (config) => config.relay?.name as string, + default: "Fedify Relay", + }, ), acceptFollow: optional(multiple( option("-a", "--accept-follow", string({ metavar: "URI" }), { diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 6f0259391..42c94d4ee 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -1,3 +1,4 @@ +import { bindConfig } from "@optique/config"; import { argument, command, @@ -12,28 +13,44 @@ import { option, optional, string, - withDefault, } from "@optique/core"; +import { configContext } from "../config.ts"; import { debugOption } from "../options.ts"; -const userAgent = optional(option( - "-u", - "--user-agent", - string({ metavar: "USER_AGENT" }), - { description: message`The custom User-Agent header value.` }, -)); +const userAgent = bindConfig( + optional(option( + "-u", + "--user-agent", + string({ metavar: "USER_AGENT" }), + { description: message`The custom User-Agent header value.` }, + )), + { + context: configContext, + key: (config) => config.webfinger?.userAgent, + }, +); -const allowPrivateAddresses = optional(flag("-p", "--allow-private-address", { - description: message`Allow private IP addresses in the URL.`, -})); +const allowPrivateAddresses = bindConfig( + optional(flag("-p", "--allow-private-address", { + description: message`Allow private IP addresses in the URL.`, + })), + { + context: configContext, + key: (config) => config.webfinger?.allowPrivateAddress, + }, +); -const maxRedirection = withDefault( +const maxRedirection = bindConfig( option( "--max-redirection", integer({ min: 0 }), { description: message`Maximum number of redirections to follow.` }, ), - 5, + { + context: configContext, + key: (config) => config.webfinger?.maxRedirection as number, + default: 5, + }, ); export const webFingerCommand = command( diff --git a/packages/elysia/deno.json b/packages/elysia/deno.json index fe7a74567..27740031c 100644 --- a/packages/elysia/deno.json +++ b/packages/elysia/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/elysia", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/index.ts" @@ -10,7 +10,10 @@ "node_modules" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts" diff --git a/packages/fixture/deno.json b/packages/fixture/deno.json index 6d73f0889..9706e81ce 100644 --- a/packages/fixture/deno.json +++ b/packages/fixture/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/fixture", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/fresh/deno.json b/packages/fresh/deno.json index d8b402269..15904431b 100644 --- a/packages/fresh/deno.json +++ b/packages/fresh/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/fresh", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "imports": { "@fresh/core": "jsr:@fresh/core@^2.1.4", @@ -14,7 +14,9 @@ "node_modules" ], "publish": { - "exclude": ["**/*.test.ts"] + "exclude": [ + "**/*.test.ts" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts" diff --git a/packages/lint/deno.json b/packages/lint/deno.json index 64af306be..b1688d33f 100644 --- a/packages/lint/deno.json +++ b/packages/lint/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/lint", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" @@ -10,7 +10,10 @@ "estree": "npm:@types/estree@^1.0.8" }, "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "test": "deno test --allow-env" diff --git a/packages/lint/package.json b/packages/lint/package.json index 8667bbdd4..5ccccc8f4 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/lint", - "version": "2.0.0", + "version": "1.10.3", "description": "Fedify linting rules and plugins", "keywords": [ "Fedify", diff --git a/packages/relay/deno.json b/packages/relay/deno.json index f6b08ccc6..62d453199 100644 --- a/packages/relay/deno.json +++ b/packages/relay/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/relay", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "imports": { "@std/assert": "jsr:@std/assert@^1.0.13" @@ -13,7 +13,10 @@ "node_modules/" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "codegen": "deno task -f @fedify/vocab compile", diff --git a/packages/relay/package.json b/packages/relay/package.json index 82daa7a91..9b008ccf7 100644 --- a/packages/relay/package.json +++ b/packages/relay/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/relay", - "version": "2.0.0", + "version": "1.10.3", "description": "ActivityPub relay support for Fedify", "keywords": [ "Fedify", diff --git a/packages/vocab-runtime/deno.json b/packages/vocab-runtime/deno.json index f6febbb9b..6a6b53a43 100644 --- a/packages/vocab-runtime/deno.json +++ b/packages/vocab-runtime/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-runtime", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" @@ -24,7 +24,10 @@ "node_modules" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts", diff --git a/packages/vocab-runtime/package.json b/packages/vocab-runtime/package.json index 665cc3642..b0ab86824 100644 --- a/packages/vocab-runtime/package.json +++ b/packages/vocab-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-runtime", - "version": "2.0.0", + "version": "1.10.3", "homepage": "https://fedify.dev/", "repository": { "type": "git", diff --git a/packages/vocab-tools/deno.json b/packages/vocab-tools/deno.json index f68c2e79b..7540d49f4 100644 --- a/packages/vocab-tools/deno.json +++ b/packages/vocab-tools/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-tools", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" @@ -20,7 +20,10 @@ "src/schema.yaml" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts", diff --git a/packages/vocab-tools/package.json b/packages/vocab-tools/package.json index 73e496d14..ae546fe84 100644 --- a/packages/vocab-tools/package.json +++ b/packages/vocab-tools/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-tools", - "version": "2.0.0", + "version": "1.10.3", "description": "Code generator for Activity Vocabulary APIs", "homepage": "https://fedify.dev/", "repository": { diff --git a/packages/vocab/deno.json b/packages/vocab/deno.json index bfa9d7172..3c376e346 100644 --- a/packages/vocab/deno.json +++ b/packages/vocab/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" @@ -23,7 +23,11 @@ "!src/vocab.ts" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts", "scripts/"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts", + "scripts/" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts", diff --git a/packages/vocab/package.json b/packages/vocab/package.json index 20842be63..9aeb90640 100644 --- a/packages/vocab/package.json +++ b/packages/vocab/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab", - "version": "2.0.0", + "version": "1.10.3", "homepage": "https://fedify.dev/", "repository": { "type": "git", diff --git a/packages/webfinger/deno.json b/packages/webfinger/deno.json index 36f26b5ca..1b140179f 100644 --- a/packages/webfinger/deno.json +++ b/packages/webfinger/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/webfinger", - "version": "2.0.0", + "version": "1.10.3", "license": "MIT", "exports": { ".": "./src/mod.ts" @@ -20,7 +20,10 @@ "node_modules" ], "publish": { - "exclude": ["**/*.test.ts", "tsdown.config.ts"] + "exclude": [ + "**/*.test.ts", + "tsdown.config.ts" + ] }, "tasks": { "check": "deno fmt --check && deno lint && deno check src/*.ts", diff --git a/packages/webfinger/package.json b/packages/webfinger/package.json index 443b357a5..6959d85c8 100644 --- a/packages/webfinger/package.json +++ b/packages/webfinger/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/webfinger", - "version": "2.0.0", + "version": "1.10.3", "homepage": "https://fedify.dev/", "repository": { "type": "git", From 14350a8d528432eb6069af86802c4d464552c978 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 5 Feb 2026 18:41:29 +0900 Subject: [PATCH 07/35] Add bindConfig integration for tunnel command Add tunnel section to config schema and wrap the service option with bindConfig() to allow tunnel service to be configured via config file. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 8 ++++++++ packages/cli/src/tunnel.ts | 34 +++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 805ed7de0..20b0fb750 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -64,6 +64,13 @@ const nodeinfoSchema = object({ userAgent: optional(string()), }); +/** + * Schema for the tunnel command configuration. + */ +const tunnelSchema = object({ + service: optional(picklist(["localhost.run", "serveo.net", "pinggy.io"])), +}); + /** * Schema for the complete configuration file. */ @@ -77,6 +84,7 @@ export const configSchema = object({ inbox: optional(inboxSchema), relay: optional(relaySchema), nodeinfo: optional(nodeinfoSchema), + tunnel: optional(tunnelSchema), }); /** diff --git a/packages/cli/src/tunnel.ts b/packages/cli/src/tunnel.ts index 33730b71b..b7867a582 100644 --- a/packages/cli/src/tunnel.ts +++ b/packages/cli/src/tunnel.ts @@ -1,4 +1,5 @@ import { openTunnel, type Tunnel } from "@hongminhee/localtunnel"; +import { bindConfig } from "@optique/config"; import { argument, command, @@ -16,6 +17,7 @@ import { choice } from "@optique/core/valueparser"; import { print, printError } from "@optique/run"; import process from "node:process"; import ora from "ora"; +import { configContext } from "./config.ts"; import { configureLogging } from "./log.ts"; import { debugOption, TUNNEL_SERVICES } from "./options.ts"; export const tunnelCommand = command( @@ -29,20 +31,26 @@ export const tunnelCommand = command( port: argument(integer({ metavar: "PORT", min: 0, max: 65535 }), { description: message`The local port number to expose.`, }), - service: optional( - option( - "-s", - "--service", - "--tunnel-service", - choice(TUNNEL_SERVICES, { - metavar: "SERVICE", - }), - { - description: message`The tunneling service to use: ${ - valueSet(TUNNEL_SERVICES) - }.`, - }, + service: bindConfig( + optional( + option( + "-s", + "--service", + "--tunnel-service", + choice(TUNNEL_SERVICES, { + metavar: "SERVICE", + }), + { + description: message`The tunneling service to use: ${ + valueSet(TUNNEL_SERVICES) + }.`, + }, + ), ), + { + context: configContext, + key: (config) => config.tunnel?.service, + }, ), }), debugOption, From ac8ef431afaee0004d70861aa91c61eaa16e7adb Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 5 Feb 2026 19:01:14 +0900 Subject: [PATCH 08/35] Extend config schema and add more bindConfig integrations Add missing fields to config schema: - lookup: firstKnock, defaultFormat, separator - relay: persistent, acceptFollow, rejectFollow - nodeinfo: raw, bestEffort, noFavicon, metadata Add bindConfig() for: - lookup: separator - relay: persistent Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 12 ++++++++++++ packages/cli/src/lookup.ts | 8 ++++++-- packages/cli/src/relay.ts | 16 +++++++++++----- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index 20b0fb750..e53f02a1c 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -25,8 +25,13 @@ const webfingerSchema = object({ */ const lookupSchema = object({ authorizedFetch: optional(boolean()), + firstKnock: optional( + picklist(["draft-cavage-http-signatures-12", "rfc9421"]), + ), traverse: optional(boolean()), suppressErrors: optional(boolean()), + defaultFormat: optional(picklist(["default", "raw", "compact", "expand"])), + separator: optional(string()), userAgent: optional(string()), timeout: optional(number()), }); @@ -55,6 +60,9 @@ const relaySchema = object({ tunnelService: optional( picklist(["localhost.run", "serveo.net", "pinggy.io"]), ), + persistent: optional(string()), + acceptFollow: optional(string()), + rejectFollow: optional(string()), }); /** @@ -62,6 +70,10 @@ const relaySchema = object({ */ const nodeinfoSchema = object({ userAgent: optional(string()), + raw: optional(boolean()), + bestEffort: optional(boolean()), + noFavicon: optional(boolean()), + metadata: optional(boolean()), }); /** diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 8f186fd71..5a9f3b81b 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -138,12 +138,16 @@ export const lookupCommand = command( key: (config) => config.lookup?.userAgent, }, ), - separator: withDefault( + separator: bindConfig( option("-s", "--separator", string({ metavar: "SEPARATOR" }), { description: message`Specify the separator between adjacent output objects or collection items.`, }), - "----", + { + context: configContext, + key: (config) => config.lookup?.separator as string, + default: "----", + }, ), output: optional(option( "-o", diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index ad8cda70f..8672a6947 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -56,11 +56,17 @@ export const relayCommand = command( default: "mastodon", }, ), - persistent: optional( - option("--persistent", string({ metavar: "PATH" }), { - description: - message`Path to SQLite database file for persistent storage. If not specified, uses in-memory storage which is lost when the server stops.`, - }), + persistent: bindConfig( + optional( + option("--persistent", string({ metavar: "PATH" }), { + description: + message`Path to SQLite database file for persistent storage. If not specified, uses in-memory storage which is lost when the server stops.`, + }), + ), + { + context: configContext, + key: (config) => config.relay?.persistent, + }, ), port: bindConfig( option( From 5a84e7a0ba7201ba3546d58c270a86147f483bbd Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 5 Feb 2026 20:08:07 +0900 Subject: [PATCH 09/35] Add bindConfig for lookup and nodeinfo command options Extend config file support for more CLI options: - lookup: authorizedFetch, traverse, suppressErrors, format (defaultFormat) - nodeinfo: raw, bestEffort, noFavicon, metadata The nodeinfo options were restructured from an or() discriminated union to a flat object structure to enable bindConfig integration. This simplifies the runtime checks from `"raw" in command && command.raw` to `command.raw`. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/lookup.ts | 110 +++++++++++++++++++++++------------ packages/cli/src/nodeinfo.ts | 73 ++++++++++++++--------- 2 files changed, 116 insertions(+), 67 deletions(-) diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 5a9f3b81b..9571ec6c9 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -52,11 +52,18 @@ const logger = getLogger(["fedify", "cli", "lookup"]); export const authorizedFetchOption = withDefault( object({ - authorizedFetch: map( - flag("-a", "--authorized-fetch", { - description: message`Sign the request with an one-time key.`, - }), - () => true as const, + authorizedFetch: bindConfig( + map( + flag("-a", "--authorized-fetch", { + description: message`Sign the request with an one-time key.`, + }), + () => true as const, + ), + { + context: configContext, + key: (config) => config.lookup?.authorizedFetch as boolean, + default: false, + }, ), firstKnock: withDefault( option( @@ -75,19 +82,34 @@ export const authorizedFetchOption = withDefault( { authorizedFetch: false } as const, ); -const traverseOption = withDefault( - object({ - traverse: flag("-t", "--traverse", { - description: - message`Traverse the given collection(s) to fetch all items.`, - }), - suppressErrors: option("-S", "--suppress-errors", { - description: - message`Suppress partial errors while traversing the collection.`, - }), - }), - { traverse: false } as const, -); +const traverseOption = object({ + traverse: bindConfig( + withDefault( + flag("-t", "--traverse", { + description: + message`Traverse the given collection(s) to fetch all items.`, + }), + false, + ), + { + context: configContext, + key: (config) => config.lookup?.traverse as boolean, + default: false, + }, + ), + suppressErrors: bindConfig( + optional( + option("-S", "--suppress-errors", { + description: + message`Suppress partial errors while traversing the collection.`, + }), + ), + { + context: configContext, + key: (config) => config.lookup?.suppressErrors, + }, + ), +}); export const lookupCommand = command( "lookup", @@ -104,28 +126,40 @@ export const lookupCommand = command( }), { min: 1 }, ), - format: withDefault( - or( - map( - option("-r", "--raw", { - description: message`Print the fetched JSON-LD document as is.`, - }), - () => "raw" as const, - ), - map( - option("-C", "--compact", { - description: message`Compact the fetched JSON-LD document.`, - }), - () => "compact" as const, - ), - map( - option("-e", "--expand", { - description: message`Expand the fetched JSON-LD document.`, - }), - () => "expand" as const, + format: bindConfig( + withDefault( + or( + map( + option("-r", "--raw", { + description: message`Print the fetched JSON-LD document as is.`, + }), + () => "raw" as const, + ), + map( + option("-C", "--compact", { + description: message`Compact the fetched JSON-LD document.`, + }), + () => "compact" as const, + ), + map( + option("-e", "--expand", { + description: message`Expand the fetched JSON-LD document.`, + }), + () => "expand" as const, + ), ), + "default" as const, ), - "default" as const, + { + context: configContext, + key: (config) => + config.lookup?.defaultFormat as + | "default" + | "raw" + | "compact" + | "expand", + default: "default", + }, ), userAgent: bindConfig( optional( diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index d2201fd53..5e7367e8c 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -15,7 +15,6 @@ import { object, option, optional, - or, string, text, } from "@optique/core"; @@ -37,28 +36,46 @@ export const Jimp = createJimp({ plugins: defaultPlugins, }); -const nodeInfoOption = optional( - or( - object({ - raw: flag("-r", "--raw", { - description: message`Show NodeInfo document in the raw JSON format`, - }), - }), - object({ - bestEffort: optional(flag("-b", "--best-effort", { - description: - message`Parse the NodeInfo document with best effort. If the NodeInfo document is not well-formed, the option will try to parse it as much as possible.`, - })), - noFavicon: optional(flag("--no-favicon", { - description: message`Disable fetching the favicon of the instance`, - })), - metadata: optional(flag("-m", "--metadata", { - description: - message`Show the extra metadata of the NodeInfo, i.e., the metadata field of the document.`, - })), - }), +const nodeInfoOption = object({ + raw: bindConfig( + optional(flag("-r", "--raw", { + description: message`Show NodeInfo document in the raw JSON format`, + })), + { + context: configContext, + key: (config) => config.nodeinfo?.raw, + }, ), -); + bestEffort: bindConfig( + optional(flag("-b", "--best-effort", { + description: + message`Parse the NodeInfo document with best effort. If the NodeInfo document is not well-formed, the option will try to parse it as much as possible.`, + })), + { + context: configContext, + key: (config) => config.nodeinfo?.bestEffort, + }, + ), + noFavicon: bindConfig( + optional(flag("--no-favicon", { + description: message`Disable fetching the favicon of the instance`, + })), + { + context: configContext, + key: (config) => config.nodeinfo?.noFavicon, + }, + ), + metadata: bindConfig( + optional(flag("-m", "--metadata", { + description: + message`Show the extra metadata of the NodeInfo, i.e., the metadata field of the document.`, + })), + { + context: configContext, + key: (config) => config.nodeinfo?.metadata, + }, + ), +}); const userAgentOption = object({ userAgent: bindConfig( @@ -107,7 +124,7 @@ export async function runNodeInfo( URL.canParse(command.host) ? command.host : `https://${command.host}`, ); - if ("raw" in command && command.raw) { + if (command.raw) { const nodeInfo = await getNodeInfo(url, { parse: "none", userAgent: command.userAgent, @@ -124,16 +141,14 @@ export async function runNodeInfo( return; } const nodeInfo = await getNodeInfo(url, { - parse: "bestEffort" in command && command.bestEffort - ? "best-effort" - : "strict", + parse: command.bestEffort ? "best-effort" : "strict", userAgent: command.userAgent, }); logger.debug("NodeInfo document: {nodeInfo}", { nodeInfo }); if (nodeInfo == undefined) { spinner.fail("No NodeInfo document found or it is invalid."); printError(message`No NodeInfo document found or it is invalid.`); - if (!("bestEffort" in command && command.bestEffort)) { + if (!command.bestEffort) { printError( message`Use the -b/--best-effort option to try to parse the document anyway.`, ); @@ -144,7 +159,7 @@ export async function runNodeInfo( let layout: string[]; let defaultWidth = 0; - if (!("noFavicon" in command && command.noFavicon)) { + if (!command.noFavicon) { spinner.text = "Fetching the favicon..."; try { const faviconUrl = await getFaviconUrl(url, command.userAgent); @@ -267,7 +282,7 @@ export async function runNodeInfo( } if ( - "metadata" in command && command.metadata && nodeInfo.metadata != null && + command.metadata && nodeInfo.metadata != null && Object.keys(nodeInfo.metadata).length > 0 ) { layout[next()] += colors.bold(colors.dim("Metadata:")); From 7037417b153ebb87dec3c74bfb8c1dd967ead39e Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 17:28:51 +0900 Subject: [PATCH 10/35] Update Optique to 0.10.0-dev.347 This version includes a fix for type inference with bindConfig and multiple() for array options. Co-Authored-By: Claude Opus 4.5 --- deno.lock | 81 ++++++------- packages/cli/deno.json | 8 +- packages/cli/package.json | 6 +- pnpm-lock.yaml | 245 ++++++++++++++++++++++---------------- 4 files changed, 190 insertions(+), 150 deletions(-) diff --git a/deno.lock b/deno.lock index 1bb5b4d39..eaa78e8dc 100644 --- a/deno.lock +++ b/deno.lock @@ -19,8 +19,9 @@ "jsr:@logtape/file@2": "2.0.0", "jsr:@logtape/logtape@2": "2.0.0", "jsr:@logtape/logtape@^1.0.4": "1.3.6", - "jsr:@optique/core@0.9": "0.9.0", - "jsr:@optique/run@0.9": "0.9.0", + "jsr:@optique/config@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", + "jsr:@optique/core@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", + "jsr:@optique/run@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", "jsr:@std/assert@0.224": "0.224.0", "jsr:@std/assert@0.226": "0.226.0", "jsr:@std/assert@^1.0.13": "1.0.16", @@ -78,17 +79,23 @@ "npm:@opentelemetry/context-async-hooks@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", "npm:@opentelemetry/context-async-hooks@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/core@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/core@2": "2.3.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/core@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/sdk-trace-base@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/sdk-trace-base@2": "2.3.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/semantic-conventions@^1.27.0": "1.38.0", "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", - "npm:@optique/config@~0.10.0-dev.346": "0.10.0-dev.377_@standard-schema+spec@1.1.0", - "npm:@optique/core@~0.10.0-dev.346": "0.10.0-dev.377", - "npm:@optique/run@~0.10.0-dev.346": "0.10.0-dev.377", + "npm:@optique/config@~0.10.0-dev.347": "0.10.0-dev.347_@standard-schema+spec@1.1.0", + "npm:@optique/core@0.9": "0.9.0", + "npm:@optique/core@~0.10.0-dev.347": "0.10.0-dev.347", + "npm:@optique/run@0.9": "0.9.0", + "npm:@optique/run@~0.10.0-dev.347": "0.10.0-dev.347", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", "npm:@preact/signals@^2.2.1": "2.5.1_preact@10.19.6", "npm:@preact/signals@^2.3.2": "2.5.1_preact@10.19.6", "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", + "npm:@standard-schema/spec@^1.1.0": "1.1.0", "npm:@sveltejs/kit@2": "2.49.4_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", "npm:@types/amqplib@*": "0.10.8", "npm:@types/amqplib@~0.10.7": "0.10.8", @@ -276,15 +283,21 @@ "@logtape/logtape@2.0.0": { "integrity": "c4f2d7684a8239ad9b3fc2fd4ade6eec9f04cdb3a1741bae83f370b4b34253b2" }, - "@optique/core@0.9.0": { - "integrity": "97b94e43f70b2d13f37c113461d4e5cf73288d212911c594dc950e65ca5b21ec" - }, - "@optique/run@0.9.0": { - "integrity": "d71b0a05a1342e874fe1718a01d10384ca6b3de3245ae485f6565d6e2f0c16ad", + "@optique/config@0.10.0-dev.347+14bbe4ef": { + "integrity": "bb13747533b7d667d9213dfbd0d7be5f0ecac6eceef031ce6afdea7db1acb9ef", "dependencies": [ - "jsr:@optique/core@0.9" + "npm:@standard-schema/spec" ] }, + "@optique/core@0.10.0-dev.333+076fceae": { + "integrity": "1ebe1782740f08d568ae0c5258786933a8502d1e137feb49b2d8ab06d204b11a" + }, + "@optique/core@0.10.0-dev.347+14bbe4ef": { + "integrity": "fbb90bcf73156f3f5e32b2fb7aa4f70d006977edc68d94bfa951944f0f3d9bdc" + }, + "@optique/run@0.10.0-dev.347+14bbe4ef": { + "integrity": "7b8c3d3804e873ee8d124bf26eca4adcd1fa55b6d30ca6b457b43e34bac52b50" + }, "@std/assert@0.224.0": { "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", "dependencies": [ @@ -2089,20 +2102,23 @@ "@opentelemetry/semantic-conventions@1.39.0": { "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==" }, - "@optique/config@0.10.0-dev.377_@standard-schema+spec@1.1.0": { - "integrity": "sha512-wBZ+GQnuhLU70VvagHJ+4mRdrOxVMOzom5cdJ7teYl2ikVFGHU073vE/2vEg8ELVPc4fbNgqYyNxKB1trQ/oCw==", + "@optique/config@0.10.0-dev.347_@standard-schema+spec@1.1.0": { + "integrity": "sha512-WBtkp22O/adD6bZpK2Izw5gw4eMBOwsVVo5duI51Cn0D58sqGXUuVtbGP3+uC79iQ2AfTzBwpiEqj/L8X08a2A==", "dependencies": [ - "@optique/core", + "@optique/core@0.9.2", "@standard-schema/spec" ] }, - "@optique/core@0.10.0-dev.377": { - "integrity": "sha512-3Nrn62wbKzs+C8oMsDtIawkNiaWvUWMhTI6hTJex0KpGr7/PmYyTQE5EP9q4MKeNCxZyEC2nLXyYlsO0dMTtlA==" + "@optique/core@0.10.0-dev.347": { + "integrity": "sha512-VVNLLT2AspoWCy3rp/XIi07bWWWgVBUgnU+kF86le9Qzs3m25DaCSTnmj7jZ+HAvOx5NDSzhL3UGYZbr8kt3Fw==" }, - "@optique/run@0.10.0-dev.377": { - "integrity": "sha512-0whyOg0o+VBV7ziKxwhu2Jph+KUqswExmWIUmxJNI5RmI/XjXMdq1G2Ko5yX1egPsJiLNxjTYylv0e/Lww0Xmg==", + "@optique/core@0.9.2": { + "integrity": "sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==" + }, + "@optique/run@0.10.0-dev.347": { + "integrity": "sha512-rZ2GZ1zjzZkvR62/AVdWyLKOujgrOhk4eiFg2Bc9hpS1rg+4/ElMjOp3ULBc2tKuWgfjHLUyy197c5QZ+bm52g==", "dependencies": [ - "@optique/core" + "@optique/core@0.10.0-dev.347" ] }, "@oxc-project/types@0.103.0": { @@ -5906,8 +5922,6 @@ "jsr:@hono/hono@^4.8.3", "jsr:@logtape/file@2", "jsr:@logtape/logtape@2", - "jsr:@optique/core@0.9", - "jsr:@optique/run@0.9", "jsr:@std/assert@^1.0.13", "jsr:@std/async@^1.0.13", "jsr:@std/encoding@^1.0.10", @@ -5927,7 +5941,6 @@ "npm:@types/node@^22.16.0", "npm:amqplib@~0.10.9", "npm:byte-encodings@^1.0.11", - "npm:chalk@^5.6.2", "npm:es-toolkit@^1.43.0", "npm:h3@^1.15.0", "npm:ioredis@^5.8.2", @@ -5977,9 +5990,9 @@ "dependencies": [ "jsr:@hongminhee/localtunnel@0.3", "jsr:@hono/hono@^4.8.3", - "jsr:@optique/config@~0.10.0-dev.346", - "jsr:@optique/core@~0.10.0-dev.346", - "jsr:@optique/run@~0.10.0-dev.346", + "jsr:@optique/config@~0.10.0-dev.347", + "jsr:@optique/core@~0.10.0-dev.347", + "jsr:@optique/run@~0.10.0-dev.347", "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", @@ -6003,9 +6016,9 @@ "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", - "npm:@optique/config@~0.10.0-dev.346", - "npm:@optique/core@~0.10.0-dev.346", - "npm:@optique/run@~0.10.0-dev.346", + "npm:@optique/config@~0.10.0-dev.347", + "npm:@optique/core@~0.10.0-dev.347", + "npm:@optique/run@~0.10.0-dev.347", "npm:@poppanator/http-constants@^1.1.1", "npm:chalk@^5.6.2", "npm:cli-highlight@^2.1.11", @@ -6084,18 +6097,6 @@ "jsr:@std/assert@^1.0.13" ] }, - "packages/init": { - "dependencies": [ - "npm:@inquirer/prompts@^7.8.4", - "npm:inquirer-toggle@^1.0.1" - ], - "packageJson": { - "dependencies": [ - "npm:@inquirer/prompts@^7.8.4", - "npm:inquirer-toggle@^1.0.1" - ] - } - }, "packages/koa": { "dependencies": [ "npm:koa@2" diff --git a/packages/cli/deno.json b/packages/cli/deno.json index db7f8f574..b41567356 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -8,10 +8,10 @@ "@inquirer/prompts": "npm:@inquirer/prompts@^7.8.4", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", - "@optique/config": "jsr:@optique/config@^0.10.0-dev.346", - "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.346/run", - "@optique/core": "jsr:@optique/core@^0.10.0-dev.346", - "@optique/run": "jsr:@optique/run@^0.10.0-dev.346", + "@optique/config": "jsr:@optique/config@^0.10.0-dev.347", + "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.347/run", + "@optique/core": "jsr:@optique/core@^0.10.0-dev.347", + "@optique/run": "jsr:@optique/run@^0.10.0-dev.347", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index 00739f904..e2f5908ff 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -59,9 +59,9 @@ "@js-temporal/polyfill": "catalog:", "@logtape/file": "catalog:", "@logtape/logtape": "catalog:", - "@optique/config": "^0.10.0-dev.346", - "@optique/core": "^0.10.0-dev.346", - "@optique/run": "^0.10.0-dev.346", + "@optique/config": "^0.10.0-dev.347", + "@optique/core": "^0.10.0-dev.347", + "@optique/run": "^0.10.0-dev.347", "@poppanator/http-constants": "^1.1.1", "byte-encodings": "catalog:", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bbde0106..0d4b66b25 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,12 +48,6 @@ catalogs: '@opentelemetry/semantic-conventions': specifier: ^1.39.0 version: 1.39.0 - '@optique/core': - specifier: ^0.9.0 - version: 0.9.0 - '@optique/run': - specifier: ^0.9.0 - version: 0.9.0 '@std/assert': specifier: jsr:^1.0.13 version: 1.0.13 @@ -90,9 +84,6 @@ catalogs: byte-encodings: specifier: ^1.0.11 version: 1.0.11 - chalk: - specifier: ^5.6.2 - version: 5.6.2 elysia: specifier: ^1.3.8 version: 1.3.8 @@ -747,9 +738,6 @@ importers: '@fedify/fedify': specifier: workspace:* version: link:../fedify - '@fedify/init': - specifier: workspace:* - version: link:../init '@fedify/relay': specifier: workspace:* version: link:../relay @@ -774,6 +762,9 @@ importers: '@hongminhee/localtunnel': specifier: ^0.3.0 version: 0.3.0 + '@inquirer/prompts': + specifier: ^7.8.4 + version: 7.10.1(@types/node@22.19.1) '@jimp/core': specifier: ^1.6.0 version: 1.6.0 @@ -789,12 +780,15 @@ importers: '@logtape/logtape': specifier: 'catalog:' version: 2.0.0 + '@optique/config': + specifier: ^0.10.0-dev.347 + version: 0.10.0-dev.347(@standard-schema/spec@1.0.0) '@optique/core': - specifier: 'catalog:' - version: 0.9.0 + specifier: ^0.10.0-dev.347 + version: 0.10.0-dev.347 '@optique/run': - specifier: 'catalog:' - version: 0.9.0 + specifier: ^0.10.0-dev.347 + version: 0.10.0-dev.347 '@poppanator/http-constants': specifier: ^1.1.1 version: 1.1.1 @@ -802,7 +796,7 @@ importers: specifier: 'catalog:' version: 1.0.11 chalk: - specifier: 'catalog:' + specifier: ^5.6.2 version: 5.6.2 cli-highlight: specifier: ^2.1.11 @@ -810,6 +804,9 @@ importers: cli-table3: specifier: ^0.6.5 version: 0.6.5 + enquirer: + specifier: ^2.4.1 + version: 2.4.1 env-paths: specifier: ^3.0.0 version: 3.0.0 @@ -825,6 +822,12 @@ importers: icojs: specifier: ^0.19.5 version: 0.19.5(@jimp/custom@0.22.12) + inquirer: + specifier: ^12.9.4 + version: 12.11.1(@types/node@22.19.1) + inquirer-toggle: + specifier: ^1.0.1 + version: 1.0.1 jimp: specifier: ^1.6.0 version: 1.6.0 @@ -834,9 +837,15 @@ importers: shiki: specifier: ^1.6.4 version: 1.29.2 + smol-toml: + specifier: ^1.6.0 + version: 1.6.0 srvx: specifier: ^0.8.7 version: 0.8.16 + valibot: + specifier: ^1.2.0 + version: 1.2.0(typescript@5.9.3) devDependencies: '@types/bun': specifier: 'catalog:' @@ -851,31 +860,6 @@ importers: specifier: 'catalog:' version: 5.9.3 - packages/create: - dependencies: - '@fedify/init': - specifier: workspace:* - version: link:../init - '@optique/core': - specifier: 'catalog:' - version: 0.9.0 - '@optique/run': - specifier: 'catalog:' - version: 0.9.0 - es-toolkit: - specifier: 'catalog:' - version: 1.43.0 - devDependencies: - '@types/node': - specifier: 'catalog:' - version: 22.19.1 - tsdown: - specifier: 'catalog:' - version: 0.12.9(typescript@5.9.3) - typescript: - specifier: 'catalog:' - version: 5.9.3 - packages/debugger: dependencies: '@fedify/fedify': @@ -1124,43 +1108,6 @@ importers: specifier: 'catalog:' version: 5.9.3 - packages/init: - dependencies: - '@fxts/core': - specifier: 'catalog:' - version: 1.20.0 - '@inquirer/prompts': - specifier: ^7.8.4 - version: 7.10.1(@types/node@22.19.1) - '@logtape/logtape': - specifier: 'catalog:' - version: 2.0.0 - '@optique/core': - specifier: 'catalog:' - version: 0.9.0 - '@optique/run': - specifier: 'catalog:' - version: 0.9.0 - chalk: - specifier: 'catalog:' - version: 5.6.2 - es-toolkit: - specifier: 'catalog:' - version: 1.43.0 - inquirer-toggle: - specifier: ^1.0.1 - version: 1.0.1 - devDependencies: - '@types/node': - specifier: 'catalog:' - version: 22.19.1 - tsdown: - specifier: 'catalog:' - version: 0.12.9(typescript@5.9.3) - typescript: - specifier: 'catalog:' - version: 5.9.3 - packages/koa: dependencies: '@fedify/fedify': @@ -3647,12 +3594,22 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@optique/core@0.9.0': - resolution: {integrity: sha512-PN5SwVRK9BPmFUKzcdNYDCV4Q18HGfR4H/1MG1yQYmA1RDNVKTuCV146dTIqI2H8F4lD/WMTiNsTl2wbGr9u1Q==} + '@optique/config@0.10.0-dev.347': + resolution: {integrity: sha512-WBtkp22O/adD6bZpK2Izw5gw4eMBOwsVVo5duI51Cn0D58sqGXUuVtbGP3+uC79iQ2AfTzBwpiEqj/L8X08a2A==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + peerDependencies: + '@standard-schema/spec': ^1.1.0 + + '@optique/core@0.10.0-dev.347': + resolution: {integrity: sha512-VVNLLT2AspoWCy3rp/XIi07bWWWgVBUgnU+kF86le9Qzs3m25DaCSTnmj7jZ+HAvOx5NDSzhL3UGYZbr8kt3Fw==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + + '@optique/core@0.9.2': + resolution: {integrity: sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - '@optique/run@0.9.0': - resolution: {integrity: sha512-S9hZfXPICeyIq3HArJ61yeSaadZQTnTKc4g03wcYRXLPYd6h/K7tCeVQnOkJ4k3b01TuiuHrartxwwxr3j/dnA==} + '@optique/run@0.10.0-dev.347': + resolution: {integrity: sha512-rZ2GZ1zjzZkvR62/AVdWyLKOujgrOhk4eiFg2Bc9hpS1rg+4/ElMjOp3ULBc2tKuWgfjHLUyy197c5QZ+bm52g==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@oxc-project/runtime@0.75.0': @@ -5002,6 +4959,10 @@ packages: resolution: {integrity: sha512-jwSftI4QjS3mizvnSnOrPGYiUnm1vI2OP1iXeOUz5pb74Ua0nbf6nPyyTzuiCLEE3fMpaJORXh2K/TQ08H5xGA==} engines: {node: '>=10'} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -5814,6 +5775,10 @@ packages: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -6504,6 +6469,15 @@ packages: inquirer-toggle@1.0.1: resolution: {integrity: sha512-0cReq29SpyO4JnoVmGBZJPoBv8sBzsGXw3MDjNxilOzhAFxIvC8mOFj34bCMtlFYKfkBKNYVLmmnP/qmrVuVMg==} + inquirer@12.11.1: + resolution: {integrity: sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -8060,6 +8034,10 @@ packages: roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} + run-async@4.0.6: + resolution: {integrity: sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==} + engines: {node: '>=0.12.0'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -8221,6 +8199,10 @@ packages: slow-redact@0.3.0: resolution: {integrity: sha512-cf723wn9JeRIYP9tdtd86GuqoR5937u64Io+CYjlm2i7jvu7g0H+Cp0l0ShAf/4ZL+ISUTVT+8Qzz7RZmp9FjA==} + smol-toml@1.6.0: + resolution: {integrity: sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==} + engines: {node: '>= 18'} + sonic-boom@4.2.0: resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} @@ -8794,6 +8776,14 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true + valibot@1.2.0: + resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==} + peerDependencies: + typescript: '>=5' + peerDependenciesMeta: + typescript: + optional: true + varint@6.0.0: resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} @@ -11160,11 +11150,18 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@optique/core@0.9.0': {} + '@optique/config@0.10.0-dev.347(@standard-schema/spec@1.0.0)': + dependencies: + '@optique/core': 0.9.2 + '@standard-schema/spec': 1.0.0 + + '@optique/core@0.10.0-dev.347': {} + + '@optique/core@0.9.2': {} - '@optique/run@0.9.0': + '@optique/run@0.10.0-dev.347': dependencies: - '@optique/core': 0.9.0 + '@optique/core': 0.10.0-dev.347 '@oxc-project/runtime@0.75.0': {} @@ -12791,6 +12788,8 @@ snapshots: buffer-more-ints: 1.0.0 url-parse: 1.5.10 + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -13591,6 +13590,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.2.2 + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + entities@4.5.0: {} env-paths@3.0.0: {} @@ -13824,8 +13828,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13844,8 +13848,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13868,22 +13872,22 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 - eslint: 8.57.1 + eslint: 9.32.0(jiti@2.5.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -13894,7 +13898,22 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.1 + eslint: 8.57.1 + get-tsconfig: 4.10.1 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.15 + unrs-resolver: 1.11.1 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -13909,25 +13928,25 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -13960,7 +13979,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -13971,7 +13990,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13989,7 +14008,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -14000,7 +14019,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -14784,6 +14803,18 @@ snapshots: dependencies: '@inquirer/core': 8.2.4 + inquirer@12.11.1(@types/node@22.19.1): + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/core': 10.3.2(@types/node@22.19.1) + '@inquirer/prompts': 7.10.1(@types/node@22.19.1) + '@inquirer/type': 3.0.10(@types/node@22.19.1) + mute-stream: 2.0.0 + run-async: 4.0.6 + rxjs: 7.8.2 + optionalDependencies: + '@types/node': 22.19.1 + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -16529,6 +16560,8 @@ snapshots: points-on-curve: 0.2.0 points-on-path: 0.2.1 + run-async@4.0.6: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -16780,6 +16813,8 @@ snapshots: slow-redact@0.3.0: {} + smol-toml@1.6.0: {} + sonic-boom@4.2.0: dependencies: atomic-sleep: 1.0.0 @@ -17428,6 +17463,10 @@ snapshots: uuid@11.1.0: {} + valibot@1.2.0(typescript@5.9.3): + optionalDependencies: + typescript: 5.9.3 + varint@6.0.0: {} vary@1.1.2: {} From 76c524644269cb783ea0b12b431cb1832138f203 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 18:39:17 +0900 Subject: [PATCH 11/35] Update CLI config schema to match issue spec Refine config schema to only support fields listed in the issue spec: - Global settings: debug, userAgent, logFile, tunnelService - webfinger: allowPrivateAddress, maxRedirection - lookup: authorizedFetch, firstKnock, traverse, suppressErrors, defaultFormat, separator, timeout - inbox: actorName, actorSummary, authorizedFetch, noTunnel, follow, acceptFollow - relay: protocol, port, name, persistent, noTunnel, acceptFollow, rejectFollow - nodeinfo: raw, bestEffort, showFavicon, showMetadata Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/config.ts | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index e53f02a1c..a44ca5705 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -2,6 +2,7 @@ import { createConfigContext } from "@optique/config"; import { readFileSync } from "node:fs"; import { parse as parseToml } from "smol-toml"; import { + array, boolean, type InferOutput, number, @@ -15,7 +16,6 @@ import { * Schema for the webfinger command configuration. */ const webfingerSchema = object({ - userAgent: optional(string()), allowPrivateAddress: optional(boolean()), maxRedirection: optional(number()), }); @@ -32,7 +32,6 @@ const lookupSchema = object({ suppressErrors: optional(boolean()), defaultFormat: optional(picklist(["default", "raw", "compact", "expand"])), separator: optional(string()), - userAgent: optional(string()), timeout: optional(number()), }); @@ -40,13 +39,12 @@ const lookupSchema = object({ * Schema for the inbox command configuration. */ const inboxSchema = object({ - tunnel: optional(boolean()), - tunnelService: optional( - picklist(["localhost.run", "serveo.net", "pinggy.io"]), - ), actorName: optional(string()), actorSummary: optional(string()), authorizedFetch: optional(boolean()), + noTunnel: optional(boolean()), + follow: optional(array(string())), + acceptFollow: optional(array(string())), }); /** @@ -56,31 +54,20 @@ const relaySchema = object({ protocol: optional(picklist(["mastodon", "litepub"])), port: optional(number()), name: optional(string()), - tunnel: optional(boolean()), - tunnelService: optional( - picklist(["localhost.run", "serveo.net", "pinggy.io"]), - ), persistent: optional(string()), - acceptFollow: optional(string()), - rejectFollow: optional(string()), + noTunnel: optional(boolean()), + acceptFollow: optional(array(string())), + rejectFollow: optional(array(string())), }); /** * Schema for the nodeinfo command configuration. */ const nodeinfoSchema = object({ - userAgent: optional(string()), raw: optional(boolean()), bestEffort: optional(boolean()), - noFavicon: optional(boolean()), - metadata: optional(boolean()), -}); - -/** - * Schema for the tunnel command configuration. - */ -const tunnelSchema = object({ - service: optional(picklist(["localhost.run", "serveo.net", "pinggy.io"])), + showFavicon: optional(boolean()), + showMetadata: optional(boolean()), }); /** @@ -89,6 +76,11 @@ const tunnelSchema = object({ export const configSchema = object({ // Global settings debug: optional(boolean()), + userAgent: optional(string()), + logFile: optional(string()), + tunnelService: optional( + picklist(["localhost.run", "serveo.net", "pinggy.io"]), + ), // Command-specific sections webfinger: optional(webfingerSchema), @@ -96,7 +88,6 @@ export const configSchema = object({ inbox: optional(inboxSchema), relay: optional(relaySchema), nodeinfo: optional(nodeinfoSchema), - tunnel: optional(tunnelSchema), }); /** From 71d801db5d6859f2f1a4e598ffc2cc2785f0a06d Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 18:43:26 +0900 Subject: [PATCH 12/35] Bind all inbox command options with config - Bind follow and acceptFollow arrays with config defaults - Fix actorName/actorSummary to use ?? fallback instead of type cast - Fix authorizedFetch to have proper boolean default - Use createTunnelOption("inbox") for tunnel options Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/inbox.tsx | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/inbox.tsx b/packages/cli/src/inbox.tsx index f7f149653..e7a94d080 100644 --- a/packages/cli/src/inbox.tsx +++ b/packages/cli/src/inbox.tsx @@ -33,21 +33,20 @@ import { multiple, object, option, - optional, string, } from "@optique/core"; -import { configContext } from "./config.ts"; import Table from "cli-table3"; import { type Context as HonoContext, Hono } from "hono"; import type { BlankEnv, BlankInput } from "hono/types"; import process from "node:process"; import ora from "ora"; import metadata from "../deno.json" with { type: "json" }; +import { configContext } from "./config.ts"; import { getDocumentLoader } from "./docloader.ts"; import type { ActivityEntry } from "./inbox/entry.ts"; import { ActivityEntryPage, ActivityListPage } from "./inbox/view.tsx"; import { configureLogging, recordingSink } from "./log.ts"; -import { debugOption, tunnelOption } from "./options.ts"; +import { createTunnelOption, debugOption } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; @@ -71,24 +70,33 @@ export const inboxCommand = command( merge( object("Inbox options", { command: constant("inbox"), - follow: optional( + follow: bindConfig( multiple( option("-f", "--follow", string({ metavar: "URI" }), { description: message`Follow the given actor. The argument can be either an actor URI or a handle. Can be specified multiple times.`, }), ), + { + context: configContext, + key: (config) => config.inbox?.follow ?? [], + default: [], + }, ), - acceptFollow: optional( + acceptFollow: bindConfig( multiple( option("-a", "--accept-follow", string({ metavar: "URI" }), { description: message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.`, }), ), + { + context: configContext, + key: (config) => config.inbox?.acceptFollow ?? [], + default: [], + }, ), }), - tunnelOption, object({ actorName: bindConfig( option("--actor-name", string({ metavar: "NAME" }), { @@ -96,7 +104,7 @@ export const inboxCommand = command( }), { context: configContext, - key: (config) => config.inbox?.actorName as string, + key: (config) => config.inbox?.actorName ?? "Fedify Ephemeral Inbox", default: "Fedify Ephemeral Inbox", }, ), @@ -106,25 +114,29 @@ export const inboxCommand = command( }), { context: configContext, - key: (config) => config.inbox?.actorSummary as string, + key: (config) => + config.inbox?.actorSummary ?? + "An ephemeral ActivityPub inbox for testing purposes.", default: "An ephemeral ActivityPub inbox for testing purposes.", }, ), authorizedFetch: bindConfig( - optional(option( + option( "-A", "--authorized-fetch", { description: message`Enable authorized fetch mode. Incoming requests without valid HTTP signatures will be rejected with 401 Unauthorized.`, }, - )), + ), { context: configContext, - key: (config) => config.inbox?.authorizedFetch, + key: (config) => config.inbox?.authorizedFetch ?? false, + default: false, }, ), }), + createTunnelOption("inbox"), debugOption, ), { From fb7dd385d01cc860c6351254b6ea8c6a80e69e52 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 19:10:17 +0900 Subject: [PATCH 13/35] Bind webfinger command options with config - Bind userAgent to global config.userAgent (optional) - Bind allowPrivateAddresses with default false - Bind maxRedirection without default (optional) - Remove type casts in favor of proper undefined handling Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/webfinger/command.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 42c94d4ee..65f64b376 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -11,32 +11,34 @@ import { multiple, object, option, - optional, string, } from "@optique/core"; +import { getUserAgent } from "../../../vocab-runtime/src/request.ts"; import { configContext } from "../config.ts"; import { debugOption } from "../options.ts"; const userAgent = bindConfig( - optional(option( + option( "-u", "--user-agent", string({ metavar: "USER_AGENT" }), { description: message`The custom User-Agent header value.` }, - )), + ), { context: configContext, - key: (config) => config.webfinger?.userAgent, + key: (config) => config.userAgent ?? getUserAgent(), + default: getUserAgent(), }, ); const allowPrivateAddresses = bindConfig( - optional(flag("-p", "--allow-private-address", { + flag("-p", "--allow-private-address", { description: message`Allow private IP addresses in the URL.`, - })), + }), { context: configContext, - key: (config) => config.webfinger?.allowPrivateAddress, + key: (config) => config.webfinger?.allowPrivateAddress ?? false, + default: false, }, ); @@ -49,7 +51,7 @@ const maxRedirection = bindConfig( { context: configContext, key: (config) => config.webfinger?.maxRedirection as number, - default: 5, + default: 0, }, ); From 236233cea37633bae3ab21136a7332267214be06 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 21:10:44 +0900 Subject: [PATCH 14/35] Refactor userAgentOption --- packages/cli/src/options.ts | 71 ++++++++++++++++++++------- packages/cli/src/webfinger/command.ts | 19 +------ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index a3bcbec38..ca7915f3d 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -1,3 +1,5 @@ +import { getUserAgent } from "@fedify/vocab-runtime"; +import { bindConfig } from "@optique/config"; import { choice, constant, @@ -6,12 +8,12 @@ import { message, object, option, - optional, or, string, valueSet, withDefault, } from "@optique/core"; +import { type Config, configContext } from "./config.ts"; /** * Available tunneling services for exposing local servers to the public internet. @@ -29,9 +31,9 @@ export type TunnelService = typeof TUNNEL_SERVICES[number]; /** * Option for selecting a tunneling service. - * Use this when tunneling is implicit (e.g., in `lookup` with `-a`). + * Uses the global `tunnelService` config setting. */ -export const tunnelServiceOption = optional( +export const tunnelServiceOption = bindConfig( option( "--tunnel-service", choice(TUNNEL_SERVICES, { metavar: "SERVICE" }), @@ -41,30 +43,47 @@ export const tunnelServiceOption = optional( }.`, }, ), + { + context: configContext, + key: (config) => config.tunnelService ?? "localhost.run", + default: "localhost.run" as const, + }, ); /** - * Combined option for enabling/disabling tunneling with service selection. + * Config sections that support the noTunnel option. + */ +type TunnelConfigSection = "inbox" | "relay"; + +/** + * Creates a tunnel option that binds to a specific config section's noTunnel field. * Use this when tunneling can be disabled (e.g., in `inbox` and `relay`). * - * Returns either: - * - `{ tunnel: false }` when `--no-tunnel` is specified - * - `{ tunnel: true, tunnelService?: TunnelService }` otherwise + * @param section - The config section to read noTunnel from ("inbox" or "relay") + * @returns An option object with `tunnel` (boolean) and `tunnelService` fields */ -export const tunnelOption = or( - object({ - tunnel: map( - flag("-T", "--no-tunnel", { - description: message`Do not tunnel the server to the public Internet.`, - }), - () => false as const, +export function createTunnelOption(section: S) { + return object({ + tunnel: bindConfig( + withDefault( + map( + flag("-T", "--no-tunnel", { + description: + message`Do not tunnel the server to the public Internet.`, + }), + () => false as const, + ), + true, + ), + { + context: configContext, + key: (config: Config) => !(config[section]?.noTunnel ?? false), + default: true, + }, ), - }), - object({ - tunnel: constant(true), tunnelService: tunnelServiceOption, - }), -); + }); +} export const debugOption = object("Global options", { debug: option("-d", "--debug", { @@ -72,6 +91,20 @@ export const debugOption = object("Global options", { }), }); +export const userAgentOption = bindConfig( + option( + "-u", + "--user-agent", + string({ metavar: "USER_AGENT" }), + { description: message`The custom User-Agent header value.` }, + ), + { + context: configContext, + key: (config) => config.userAgent ?? getUserAgent(), + default: getUserAgent(), + }, +); + /** * Configuration file options. * diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 65f64b376..828153268 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -13,23 +13,8 @@ import { option, string, } from "@optique/core"; -import { getUserAgent } from "../../../vocab-runtime/src/request.ts"; import { configContext } from "../config.ts"; -import { debugOption } from "../options.ts"; - -const userAgent = bindConfig( - option( - "-u", - "--user-agent", - string({ metavar: "USER_AGENT" }), - { description: message`The custom User-Agent header value.` }, - ), - { - context: configContext, - key: (config) => config.userAgent ?? getUserAgent(), - default: getUserAgent(), - }, -); +import { debugOption, userAgentOption } from "../options.ts"; const allowPrivateAddresses = bindConfig( flag("-p", "--allow-private-address", { @@ -66,7 +51,7 @@ export const webFingerCommand = command( }), { min: 1 }, ), - userAgent, + userAgentOption, allowPrivateAddresses, maxRedirection, }), From e800faacb1c7dbd212752f2b721277a71d1260c3 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 22:01:17 +0900 Subject: [PATCH 15/35] Bind lookup command options with config - Bind authorizedFetch, firstKnock, traverse, suppressErrors with defaults - Bind format (defaultFormat) and separator with defaults - Bind timeout without default (optional) - Add shared userAgentOption from options.ts - Replace type casts with ?? fallbacks for type safety Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/lookup.ts | 160 +++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 87 deletions(-) diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 9571ec6c9..6d4dba304 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -34,7 +34,6 @@ import { optionNames, or, string, - withDefault, } from "@optique/core"; import { path, print, printError } from "@optique/run"; import { createWriteStream, type WriteStream } from "node:fs"; @@ -44,69 +43,74 @@ import { configContext } from "./config.ts"; import { getContextLoader, getDocumentLoader } from "./docloader.ts"; import { renderImages } from "./imagerenderer.ts"; import { configureLogging } from "./log.ts"; -import { debugOption, tunnelServiceOption } from "./options.ts"; +import { + debugOption, + tunnelServiceOption, + userAgentOption, +} from "./options.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colorEnabled, colors, formatObject } from "./utils.ts"; const logger = getLogger(["fedify", "cli", "lookup"]); -export const authorizedFetchOption = withDefault( - object({ - authorizedFetch: bindConfig( - map( - flag("-a", "--authorized-fetch", { - description: message`Sign the request with an one-time key.`, - }), - () => true as const, - ), +export const authorizedFetchOption = object({ + authorizedFetch: bindConfig( + map( + flag("-a", "--authorized-fetch", { + description: message`Sign the request with an one-time key.`, + }), + () => true as const, + ), + { + context: configContext, + key: (config) => config.lookup?.authorizedFetch ?? false, + default: false, + }, + ), + firstKnock: bindConfig( + option( + "--first-knock", + choice(["draft-cavage-http-signatures-12", "rfc9421"]), { - context: configContext, - key: (config) => config.lookup?.authorizedFetch as boolean, - default: false, + description: message`The first-knock spec for ${ + optionNames(["-a", "--authorized-fetch"]) + }. It is used for the double-knocking technique.`, }, ), - firstKnock: withDefault( - 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.`, - }, - ), - "draft-cavage-http-signatures-12" as const, - ), - tunnelService: tunnelServiceOption, - }), - { authorizedFetch: false } as const, -); + { + context: configContext, + key: (config) => + (config.lookup?.firstKnock ?? + "draft-cavage-http-signatures-12") as + | "draft-cavage-http-signatures-12" + | "rfc9421", + default: "draft-cavage-http-signatures-12" as const, + }, + ), + tunnelService: tunnelServiceOption, +}); const traverseOption = object({ traverse: bindConfig( - withDefault( - flag("-t", "--traverse", { - description: - message`Traverse the given collection(s) to fetch all items.`, - }), - false, - ), + flag("-t", "--traverse", { + description: + message`Traverse the given collection(s) to fetch all items.`, + }), { context: configContext, - key: (config) => config.lookup?.traverse as boolean, + key: (config) => config.lookup?.traverse ?? false, default: false, }, ), suppressErrors: bindConfig( - optional( - option("-S", "--suppress-errors", { - description: - message`Suppress partial errors while traversing the collection.`, - }), - ), + option("-S", "--suppress-errors", { + description: + message`Suppress partial errors while traversing the collection.`, + }), { context: configContext, - key: (config) => config.lookup?.suppressErrors, + key: (config) => config.lookup?.suppressErrors ?? false, + default: false, }, ), }); @@ -127,51 +131,33 @@ export const lookupCommand = command( { min: 1 }, ), format: bindConfig( - withDefault( - or( - map( - option("-r", "--raw", { - description: message`Print the fetched JSON-LD document as is.`, - }), - () => "raw" as const, - ), - map( - option("-C", "--compact", { - description: message`Compact the fetched JSON-LD document.`, - }), - () => "compact" as const, - ), - map( - option("-e", "--expand", { - description: message`Expand the fetched JSON-LD document.`, - }), - () => "expand" as const, - ), + or( + map( + option("-r", "--raw", { + description: message`Print the fetched JSON-LD document as is.`, + }), + () => "raw" as const, + ), + map( + option("-C", "--compact", { + description: message`Compact the fetched JSON-LD document.`, + }), + () => "compact" as const, + ), + map( + option("-e", "--expand", { + description: message`Expand the fetched JSON-LD document.`, + }), + () => "expand" as const, ), - "default" as const, ), { context: configContext, - key: (config) => - config.lookup?.defaultFormat as - | "default" - | "raw" - | "compact" - | "expand", + key: (config) => config.lookup?.defaultFormat ?? "default", default: "default", }, ), - userAgent: bindConfig( - optional( - option("-u", "--user-agent", string({ metavar: "USER_AGENT" }), { - description: message`The custom User-Agent header value.`, - }), - ), - { - context: configContext, - key: (config) => config.lookup?.userAgent, - }, - ), + userAgent: userAgentOption, separator: bindConfig( option("-s", "--separator", string({ metavar: "SEPARATOR" }), { description: @@ -179,7 +165,7 @@ export const lookupCommand = command( }), { context: configContext, - key: (config) => config.lookup?.separator as string, + key: (config) => config.lookup?.separator ?? "----", default: "----", }, ), @@ -194,14 +180,14 @@ export const lookupCommand = command( { description: message`Specify the output file path.` }, )), timeout: bindConfig( - optional(option( + option( "-T", "--timeout", float({ min: 0, metavar: "SECONDS" }), { description: message`Set timeout for network requests in seconds.`, }, - )), + ), { context: configContext, key: (config) => config.lookup?.timeout, @@ -426,7 +412,7 @@ export async function runLookup(command: InferValue) { { specDeterminer: { determineSpec() { - return command.firstKnock; + return command.firstKnock ?? "draft-cavage-http-signatures-12"; }, rememberSpec() { }, From bfbaff56e672f50ca18f84de253aa37cb5cc8a11 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 22:54:18 +0900 Subject: [PATCH 16/35] Wrap userAgentOption with object and update usages Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/lookup.ts | 2 +- packages/cli/src/nodeinfo.ts | 44 +++++++++++---------------- packages/cli/src/options.ts | 39 +++++++++++++++--------- packages/cli/src/webfinger/command.ts | 2 +- 4 files changed, 43 insertions(+), 44 deletions(-) diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 6d4dba304..823379ee9 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -123,6 +123,7 @@ export const lookupCommand = command( traverseOption, authorizedFetchOption, debugOption, + userAgentOption, object({ urls: multiple( argument(string({ metavar: "URL_OR_HANDLE" }), { @@ -157,7 +158,6 @@ export const lookupCommand = command( default: "default", }, ), - userAgent: userAgentOption, separator: bindConfig( option("-s", "--separator", string({ metavar: "SEPARATOR" }), { description: diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index 5e7367e8c..bc20f7ca2 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -13,8 +13,6 @@ import { merge, message, object, - option, - optional, string, text, } from "@optique/core"; @@ -26,7 +24,7 @@ import os from "node:os"; import process from "node:process"; import ora from "ora"; import { configContext } from "./config.ts"; -import { debugOption } from "./options.ts"; +import { debugOption, userAgentOption } from "./options.ts"; import { colors, formatObject } from "./utils.ts"; const logger = getLogger(["fedify", "cli", "nodeinfo"]); @@ -38,53 +36,45 @@ export const Jimp = createJimp({ const nodeInfoOption = object({ raw: bindConfig( - optional(flag("-r", "--raw", { + flag("-r", "--raw", { description: message`Show NodeInfo document in the raw JSON format`, - })), + }), { context: configContext, - key: (config) => config.nodeinfo?.raw, + key: (config) => config.nodeinfo?.raw ?? false, + default: false, }, ), bestEffort: bindConfig( - optional(flag("-b", "--best-effort", { + flag("-b", "--best-effort", { description: message`Parse the NodeInfo document with best effort. If the NodeInfo document is not well-formed, the option will try to parse it as much as possible.`, - })), + }), { context: configContext, - key: (config) => config.nodeinfo?.bestEffort, + key: (config) => config.nodeinfo?.bestEffort ?? false, + default: false, }, ), noFavicon: bindConfig( - optional(flag("--no-favicon", { + flag("--no-favicon", { description: message`Disable fetching the favicon of the instance`, - })), + }), { context: configContext, - key: (config) => config.nodeinfo?.noFavicon, + key: (config) => config.nodeinfo?.showFavicon ?? false, + default: false, }, ), metadata: bindConfig( - optional(flag("-m", "--metadata", { + flag("-m", "--metadata", { description: message`Show the extra metadata of the NodeInfo, i.e., the metadata field of the document.`, - })), - { - context: configContext, - key: (config) => config.nodeinfo?.metadata, - }, - ), -}); - -const userAgentOption = object({ - userAgent: bindConfig( - optional(option("-u", "--user-agent", string(), { - description: message`The custom User-Agent header value.`, - })), + }), { context: configContext, - key: (config) => config.nodeinfo?.userAgent, + key: (config) => config.nodeinfo?.showMetadata ?? false, + default: false, }, ), }); diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index ca7915f3d..461c02e29 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -86,24 +86,33 @@ export function createTunnelOption(section: S) { } export const debugOption = object("Global options", { - debug: option("-d", "--debug", { - description: message`Enable debug mode.`, - }), + debug: bindConfig( + option("-d", "--debug", { + description: message`Enable debug mode.`, + }), + { + context: configContext, + key: (config) => config.debug ?? false, + default: false, + }, + ), }); -export const userAgentOption = bindConfig( - option( - "-u", - "--user-agent", - string({ metavar: "USER_AGENT" }), - { description: message`The custom User-Agent header value.` }, +export const userAgentOption = object({ + userAgent: bindConfig( + option( + "-u", + "--user-agent", + string({ metavar: "USER_AGENT" }), + { description: message`The custom User-Agent header value.` }, + ), + { + context: configContext, + key: (config) => config.userAgent ?? getUserAgent(), + default: getUserAgent(), + }, ), - { - context: configContext, - key: (config) => config.userAgent ?? getUserAgent(), - default: getUserAgent(), - }, -); +}); /** * Configuration file options. diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 828153268..f702677bb 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -51,10 +51,10 @@ export const webFingerCommand = command( }), { min: 1 }, ), - userAgentOption, allowPrivateAddresses, maxRedirection, }), + userAgentOption, debugOption, ), { From 52928f811ce8640b72dc6bf60f9e2764ade08b4a Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 23:00:34 +0900 Subject: [PATCH 17/35] Remove tunnel-specific config binding from tunnel command Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/tunnel.ts | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/packages/cli/src/tunnel.ts b/packages/cli/src/tunnel.ts index b7867a582..500ca7bbc 100644 --- a/packages/cli/src/tunnel.ts +++ b/packages/cli/src/tunnel.ts @@ -1,5 +1,4 @@ import { openTunnel, type Tunnel } from "@hongminhee/localtunnel"; -import { bindConfig } from "@optique/config"; import { argument, command, @@ -17,9 +16,9 @@ import { choice } from "@optique/core/valueparser"; import { print, printError } from "@optique/run"; import process from "node:process"; import ora from "ora"; -import { configContext } from "./config.ts"; import { configureLogging } from "./log.ts"; import { debugOption, TUNNEL_SERVICES } from "./options.ts"; + export const tunnelCommand = command( "tunnel", merge( @@ -31,26 +30,20 @@ export const tunnelCommand = command( port: argument(integer({ metavar: "PORT", min: 0, max: 65535 }), { description: message`The local port number to expose.`, }), - service: bindConfig( - optional( - option( - "-s", - "--service", - "--tunnel-service", - choice(TUNNEL_SERVICES, { - metavar: "SERVICE", - }), - { - description: message`The tunneling service to use: ${ - valueSet(TUNNEL_SERVICES) - }.`, - }, - ), + service: optional( + option( + "-s", + "--service", + "--tunnel-service", + choice(TUNNEL_SERVICES, { + metavar: "SERVICE", + }), + { + description: message`The tunneling service to use: ${ + valueSet(TUNNEL_SERVICES) + }.`, + }, ), - { - context: configContext, - key: (config) => config.tunnel?.service, - }, ), }), debugOption, From 7cdf58517f83229cba812e7061e27d19f1c9ccb0 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 23:09:06 +0900 Subject: [PATCH 18/35] Bind relay command options with config Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/relay.ts | 46 +++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index 8672a6947..cfad99dcb 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -25,7 +25,7 @@ import { DatabaseSync } from "node:sqlite"; import ora from "ora"; import { configContext } from "./config.ts"; import { configureLogging } from "./log.ts"; -import { debugOption, tunnelOption } from "./options.ts"; +import { createTunnelOption, debugOption } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; @@ -52,7 +52,7 @@ export const relayCommand = command( ), { context: configContext, - key: (config) => config.relay?.protocol as string, + key: (config) => config.relay?.protocol ?? "mastodon", default: "mastodon", }, ), @@ -89,24 +89,38 @@ export const relayCommand = command( }), { context: configContext, - key: (config) => config.relay?.name as string, + key: (config) => config.relay?.name ?? "Fedify Relay", default: "Fedify Relay", }, ), - acceptFollow: optional(multiple( - option("-a", "--accept-follow", string({ metavar: "URI" }), { - description: - message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.`, - }), - )), - rejectFollow: optional(multiple( - option("-r", "--reject-follow", string({ metavar: "URI" }), { - description: - message`Reject follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be rejected.`, - }), - )), + acceptFollow: bindConfig( + multiple( + option("-a", "--accept-follow", string({ metavar: "URI" }), { + description: + message`Accept follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be accepted.`, + }), + ), + { + context: configContext, + key: (config) => config.relay?.acceptFollow ?? [], + default: [], + }, + ), + rejectFollow: bindConfig( + multiple( + option("-r", "--reject-follow", string({ metavar: "URI" }), { + description: + message`Reject follow requests from the given actor. The argument can be either an actor URI or a handle, or a wildcard (${"*"}). Can be specified multiple times. If a wildcard is specified, all follow requests will be rejected.`, + }), + ), + { + context: configContext, + key: (config) => config.relay?.rejectFollow ?? [], + default: [], + }, + ), }), - tunnelOption, + createTunnelOption("relay"), debugOption, ), { From 0b769d52018550c6b5cad5769527ecf0fad281a7 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Mon, 9 Feb 2026 23:35:57 +0900 Subject: [PATCH 19/35] Add configuration file documentation to CLI docs Co-Authored-By: Claude Opus 4.5 --- docs/cli.md | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/docs/cli.md b/docs/cli.md index ec7ceaddb..ac09ca544 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -102,6 +102,104 @@ the appropriate executable for your platform and put it in your `PATH`. [releases]: https://github.com/fedify-dev/fedify/releases +Configuration file +------------------ + +*This feature is available since Fedify 2.0.0.* + +The `fedify` command supports configuration files to set default values for +command options. Configuration files are written in [TOML] format. + +[TOML]: https://toml.io/ + +### Configuration file locations + +Configuration files are loaded from the following locations in order, with +later files taking precedence over earlier ones: + +1. `/etc/fedify/config.toml` (system-wide) +2. */fedify/config.toml* (user-level) +3. `.fedify.toml` in the current working directory (project-level) +4. Custom path via `--config` option (explicit) + +The user config directory varies by operating system: + + - **Linux**: *~/.config/fedify/config.toml* + - **macOS**: *~/Library/Application Support/fedify/config.toml* + - **Windows**: *%APPDATA%\\fedify\\config.toml* + +### `--config`: Load an additional configuration file + +You can specify an additional configuration file to load using the `--config` +option: + +~~~~ sh +fedify --config ./my-config.toml lookup @user@example.com +~~~~ + +This file is loaded after all standard configuration files and takes the +highest precedence. + +### `--ignore-config`: Ignore all configuration files + +The `--ignore-config` option skips loading all configuration files. This is +useful for CI environments or when you want reproducible behavior: + +~~~~ sh +fedify --ignore-config lookup @user@example.com +~~~~ + +### Configuration file structure + +Below is an example configuration file showing all available options: + +~~~~ toml +# Global settings (apply to all commands) +debug = false +userAgent = "MyApp/1.0" +tunnelService = "localhost.run" # "localhost.run", "serveo.net", or "pinggy.io" + +[webfinger] +allowPrivateAddress = false +maxRedirection = 5 + +[lookup] +authorizedFetch = false +firstKnock = "draft-cavage-http-signatures-12" # or "rfc9421" +traverse = false +suppressErrors = false +defaultFormat = "default" # "default", "raw", "compact", or "expand" +separator = "----" +timeout = 30 # seconds + +[inbox] +actorName = "Fedify Ephemeral Actor" +actorSummary = "An ephemeral actor for testing purposes." +authorizedFetch = false +noTunnel = false +follow = ["@user@example.com"] +acceptFollow = ["*"] + +[relay] +protocol = "mastodon" # or "litepub" +port = 8000 +name = "Fedify Relay" +persistent = "/path/to/relay.db" # optional, uses in-memory if not specified +noTunnel = false +acceptFollow = ["*"] +rejectFollow = [] + +[nodeinfo] +raw = false +bestEffort = false +showFavicon = true +showMetadata = false +~~~~ + +All configuration options are optional. Command-line arguments always take +precedence over configuration file values. + + `fedify init`: Initializing a Fedify project -------------------------------------------- From 8f190530b759d26af41e315ce52e5cd96e580257 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Tue, 10 Feb 2026 22:20:32 +0900 Subject: [PATCH 20/35] Update CLI tests for bindConfig compatibility Upgrade @optique/config, @optique/core, @optique/run to 0.10.0-dev.348 which fixes a bug where bindConfig.complete crashed with undefined state when no CLI args were consumed. Update test expectations to reflect bindConfig behavior: - userAgent now returns default value instead of undefined - Invalid option values fall back to default instead of failing See: https://github.com/dahlia/optique/issues/94 Co-Authored-By: Claude Opus 4.5 --- deno.lock | 1038 ++++++++++++------------ packages/cli/deno.json | 8 +- packages/cli/package.json | 69 +- packages/cli/src/lookup.test.ts | 33 +- packages/cli/src/webfinger/mod.test.ts | 42 +- pnpm-lock.yaml | 81 +- 6 files changed, 628 insertions(+), 643 deletions(-) diff --git a/deno.lock b/deno.lock index eaa78e8dc..f482b0e7c 100644 --- a/deno.lock +++ b/deno.lock @@ -6,44 +6,45 @@ "jsr:@david/dax@~0.43.2": "0.43.2", "jsr:@david/path@0.2": "0.2.0", "jsr:@david/which@~0.4.1": "0.4.1", - "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.0", - "jsr:@deno/loader@~0.3.2": "0.3.9", - "jsr:@deno/loader@~0.3.3": "0.3.9", + "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.1", + "jsr:@deno/loader@~0.3.10": "0.3.12", + "jsr:@deno/loader@~0.3.2": "0.3.12", "jsr:@fresh/build-id@1": "1.0.1", "jsr:@fresh/core@2": "2.2.0", "jsr:@fresh/core@^2.1.4": "2.2.0", - "jsr:@fresh/plugin-vite@^1.0.7": "1.0.7", + "jsr:@fresh/core@^2.2.0": "2.2.0", + "jsr:@fresh/plugin-vite@^1.0.7": "1.0.8", "jsr:@hongminhee/localtunnel@0.3": "0.3.0", - "jsr:@hono/hono@^4.7.1": "4.11.3", + "jsr:@hono/hono@^4.7.1": "4.11.4", "jsr:@hono/hono@^4.8.3": "4.11.4", - "jsr:@logtape/file@2": "2.0.0", - "jsr:@logtape/logtape@2": "2.0.0", - "jsr:@logtape/logtape@^1.0.4": "1.3.6", - "jsr:@optique/config@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", - "jsr:@optique/core@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", - "jsr:@optique/run@~0.10.0-dev.347": "0.10.0-dev.347+14bbe4ef", + "jsr:@logtape/file@2": "2.0.2", + "jsr:@logtape/logtape@2": "2.0.2", + "jsr:@logtape/logtape@^1.0.4": "1.3.7", + "jsr:@logtape/logtape@^2.0.2": "2.0.2", + "jsr:@optique/config@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", + "jsr:@optique/core@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", + "jsr:@optique/run@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", "jsr:@std/assert@0.224": "0.224.0", "jsr:@std/assert@0.226": "0.226.0", - "jsr:@std/assert@^1.0.13": "1.0.16", + "jsr:@std/assert@^1.0.13": "1.0.18", "jsr:@std/async@^1.0.13": "1.0.16", - "jsr:@std/bytes@^1.0.5": "1.0.6", "jsr:@std/bytes@^1.0.6": "1.0.6", "jsr:@std/dotenv@~0.225.5": "0.225.6", "jsr:@std/encoding@^1.0.10": "1.0.10", "jsr:@std/fmt@0.224": "0.224.0", - "jsr:@std/fmt@1": "1.0.8", - "jsr:@std/fmt@^1.0.7": "1.0.8", - "jsr:@std/fmt@^1.0.8": "1.0.8", + "jsr:@std/fmt@1": "1.0.9", + "jsr:@std/fmt@^1.0.7": "1.0.9", + "jsr:@std/fmt@^1.0.8": "1.0.9", "jsr:@std/fs@0.224": "0.224.0", - "jsr:@std/fs@1": "1.0.21", - "jsr:@std/fs@^1.0.19": "1.0.21", - "jsr:@std/fs@^1.0.3": "1.0.21", + "jsr:@std/fs@1": "1.0.22", + "jsr:@std/fs@^1.0.19": "1.0.22", + "jsr:@std/fs@^1.0.3": "1.0.22", "jsr:@std/html@^1.0.5": "1.0.5", - "jsr:@std/http@^1.0.21": "1.0.23", + "jsr:@std/http@^1.0.21": "1.0.24", "jsr:@std/internal@0.224": "0.224.0", "jsr:@std/internal@1": "1.0.12", "jsr:@std/internal@^1.0.12": "1.0.12", - "jsr:@std/io@0.225": "0.225.2", + "jsr:@std/io@0.225": "0.225.3", "jsr:@std/json@^1.0.2": "1.0.2", "jsr:@std/jsonc@^1.0.2": "1.0.2", "jsr:@std/media-types@^1.1.0": "1.1.0", @@ -54,57 +55,47 @@ "jsr:@std/path@^1.1.1": "1.1.4", "jsr:@std/path@^1.1.2": "1.1.4", "jsr:@std/path@^1.1.4": "1.1.4", - "jsr:@std/semver@^1.0.6": "1.0.7", + "jsr:@std/semver@^1.0.6": "1.0.8", "jsr:@std/testing@0.224": "0.224.0", "jsr:@std/uuid@^1.0.9": "1.1.0", "jsr:@std/yaml@^1.0.8": "1.0.10", "npm:@alinea/suite@~0.6.3": "0.6.3", - "npm:@babel/core@^7.28.0": "7.28.6", - "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.28.6", + "npm:@babel/core@^7.28.0": "7.29.0", + "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0", "npm:@cfworker/json-schema@^4.1.1": "4.1.1", - "npm:@cloudflare/vitest-pool-workers@~0.8.31": "0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.3__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260109.0_tsx@4.21.0_yaml@2.8.2", - "npm:@cloudflare/workers-types@^4.20250529.0": "4.20260109.0", - "npm:@cloudflare/workers-types@^4.20250906.0": "4.20260109.0", - "npm:@fxts/core@^1.21.1": "1.23.0", + "npm:@cloudflare/vitest-pool-workers@~0.8.31": "0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.10__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.10_@cloudflare+workers-types@4.20260210.0_tsx@4.21.0_yaml@2.8.2", + "npm:@cloudflare/workers-types@^4.20250529.0": "4.20260210.0", + "npm:@cloudflare/workers-types@^4.20250906.0": "4.20260210.0", + "npm:@fxts/core@^1.21.1": "1.25.0", "npm:@hongminhee/localtunnel@0.3": "0.3.0", - "npm:@inquirer/prompts@^7.8.4": "7.10.1_@types+node@22.19.3", + "npm:@inquirer/prompts@^7.8.4": "7.10.1_@types+node@22.19.10", "npm:@jimp/core@^1.6.0": "1.6.0", "npm:@jimp/wasm-webp@^1.6.0": "1.6.0", "npm:@js-temporal/polyfill@~0.5.1": "0.5.1", "npm:@mjackson/node-fetch-server@0.7": "0.7.0", "npm:@multiformats/base-x@^4.0.1": "4.0.1", - "npm:@nestjs/common@^11.0.1": "11.1.11_reflect-metadata@0.2.2_rxjs@7.8.2", - "npm:@opentelemetry/api@1.9.0": "1.9.0", + "npm:@nestjs/common@^11.0.1": "11.1.13_reflect-metadata@0.2.2_rxjs@7.8.2", "npm:@opentelemetry/api@^1.9.0": "1.9.0", - "npm:@opentelemetry/context-async-hooks@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/context-async-hooks@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/core@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/core@2": "2.3.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/core@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/sdk-trace-base@1.30.1": "1.30.1_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/sdk-trace-base@2": "2.3.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/semantic-conventions@^1.27.0": "1.38.0", - "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", - "npm:@optique/config@~0.10.0-dev.347": "0.10.0-dev.347_@standard-schema+spec@1.1.0", - "npm:@optique/core@0.9": "0.9.0", - "npm:@optique/core@~0.10.0-dev.347": "0.10.0-dev.347", - "npm:@optique/run@0.9": "0.9.0", - "npm:@optique/run@~0.10.0-dev.347": "0.10.0-dev.347", + "npm:@opentelemetry/core@2": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/sdk-trace-base@2": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/semantic-conventions@^1.27.0": "1.39.0", + "npm:@optique/config@0.10.0-dev.348": "0.10.0-dev.348_@standard-schema+spec@1.1.0", + "npm:@optique/core@0.10.0-dev.348": "0.10.0-dev.348", + "npm:@optique/run@0.10.0-dev.348": "0.10.0-dev.348", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", - "npm:@preact/signals@^2.2.1": "2.5.1_preact@10.19.6", - "npm:@preact/signals@^2.3.2": "2.5.1_preact@10.19.6", - "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", + "npm:@preact/signals@^2.2.1": "2.7.1_preact@10.19.6", + "npm:@preact/signals@^2.3.2": "2.7.1_preact@10.19.6", + "npm:@prefresh/vite@^2.4.8": "2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2", "npm:@standard-schema/spec@^1.1.0": "1.1.0", - "npm:@sveltejs/kit@2": "2.49.4_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2", + "npm:@sveltejs/kit@2": "2.50.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2", "npm:@types/amqplib@*": "0.10.8", "npm:@types/amqplib@~0.10.7": "0.10.8", "npm:@types/eslint@9": "9.6.1", "npm:@types/estree@^1.0.8": "1.0.8", - "npm:@types/node@^22.16.0": "22.19.3", - "npm:@types/node@^24.2.1": "24.10.4", - "npm:@typescript-eslint/parser@^8.49.0": "8.52.0_eslint@9.39.2_typescript@5.9.3", - "npm:@typescript-eslint/utils@8": "8.52.0_eslint@9.39.2_typescript@5.9.3", + "npm:@types/node@^22.16.0": "22.19.10", + "npm:@types/node@^24.2.1": "24.10.12", + "npm:@typescript-eslint/parser@^8.49.0": "8.55.0_eslint@9.39.2_typescript@5.9.3", + "npm:@typescript-eslint/utils@8": "8.55.0_eslint@9.39.2_typescript@5.9.3", "npm:amqplib@~0.10.9": "0.10.9", "npm:asn1js@^3.0.6": "3.0.7", "npm:asn1js@^3.0.7": "3.0.7", @@ -127,15 +118,15 @@ "npm:express@4": "4.22.1", "npm:fast-check@^3.22.0": "3.23.2", "npm:fastify-plugin@^5.0.1": "5.1.0", - "npm:fastify@^5.2.0": "5.6.2", + "npm:fastify@^5.2.0": "5.7.4", "npm:fetch-mock@^12.5.2": "12.6.0", "npm:fetch-mock@^12.5.4": "12.6.0", - "npm:h3@^1.15.0": "1.15.4", + "npm:h3@^1.15.0": "1.15.5", "npm:hono@^4.8.3": "4.11.3", "npm:icojs@~0.19.5": "0.19.5", "npm:inquirer-toggle@^1.0.1": "1.0.1", - "npm:inquirer@^12.9.4": "12.11.1_@types+node@22.19.3", - "npm:ioredis@^5.8.2": "5.9.1", + "npm:inquirer@^12.9.4": "12.11.1_@types+node@22.19.10", + "npm:ioredis@^5.8.2": "5.9.2", "npm:jimp@^1.6.0": "1.6.0", "npm:json-canon@^1.0.1": "1.0.1", "npm:json-preserve-indent@^1.1.3": "1.1.3", @@ -149,9 +140,9 @@ "npm:postgres@^3.4.7": "3.4.8", "npm:preact-render-to-string@^6.6.3": "6.6.5_preact@10.19.6", "npm:preact@10.19.6": "10.19.6", - "npm:preact@^10.27.0": "10.28.2", - "npm:preact@^10.27.2": "10.28.2", - "npm:rollup@^4.50.0": "4.55.1", + "npm:preact@^10.27.0": "10.28.3", + "npm:preact@^10.27.2": "10.28.3", + "npm:rollup@^4.50.0": "4.57.1", "npm:shiki@^1.6.4": "1.29.2", "npm:smol-toml@^1.6.0": "1.6.0", "npm:srvx@~0.8.7": "0.8.16", @@ -161,11 +152,11 @@ "npm:uri-template-router@1": "1.0.0", "npm:url-template@^3.1.1": "3.1.1", "npm:valibot@^1.2.0": "1.2.0", - "npm:vite@^7.1.3": "7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vite@^7.1.4": "7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", - "npm:vitest@3.2": "3.2.4_@types+node@22.19.3_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", - "npm:wrangler@^4.17.0": "4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", - "npm:wrangler@^4.21.1": "4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", + "npm:vite@^7.1.3": "7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", + "npm:vite@^7.1.4": "7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3", + "npm:vitest@3.2": "3.2.4_@types+node@22.19.10_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2", + "npm:wrangler@^4.17.0": "4.35.0_@cloudflare+workers-types@4.20260210.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", + "npm:wrangler@^4.21.1": "4.35.0_@cloudflare+workers-types@4.20260210.0_unenv@2.0.0-rc.21_workerd@1.20250906.0", "npm:yaml@^2.8.1": "2.8.2" }, "jsr": { @@ -197,16 +188,16 @@ "@david/which@0.4.1": { "integrity": "896a682b111f92ab866cc70c5b4afab2f5899d2f9bde31ed00203b9c250f225e" }, - "@deno/esbuild-plugin@1.2.0": { - "integrity": "04ddd0fca9416d8a2866263928a53b9d5ed08dfca064d64504a0aaf9800c709e", + "@deno/esbuild-plugin@1.2.1": { + "integrity": "df629467913adc1f960149fdfa3a3430ba8c20381c310fba096db244e6c3c9f6", "dependencies": [ - "jsr:@deno/loader@~0.3.3", + "jsr:@deno/loader@~0.3.10", "jsr:@std/path@^1.1.1", "npm:esbuild@~0.25.5" ] }, - "@deno/loader@0.3.9": { - "integrity": "703d44656f7da0fa4a4a7f8a5105b5b41320821286508c2967b4252a00a2506f" + "@deno/loader@0.3.12": { + "integrity": "52d3b3be0a32192efe07b0a4f1b3047077d2f2bba0f693e32f47421507f9fdb6" }, "@fresh/build-id@1.0.1": { "integrity": "12a2ec25fd52ae9ec68c26848a5696cd1c9b537f7c983c7e56e4fb1e7e816c20", @@ -229,7 +220,7 @@ "jsr:@std/path@^1.1.2", "jsr:@std/semver", "jsr:@std/uuid", - "npm:@opentelemetry/api@^1.9.0", + "npm:@opentelemetry/api", "npm:@preact/signals@^2.2.1", "npm:esbuild-wasm", "npm:esbuild@0.25.7", @@ -238,12 +229,12 @@ "npm:preact@^10.27.2" ] }, - "@fresh/plugin-vite@1.0.7": { - "integrity": "0dd7048f7c5d5cf7f62b29b4653a18cfa4dc81e074c4c0ab9e8166cce639cbeb", + "@fresh/plugin-vite@1.0.8": { + "integrity": "5780d842ed82e4cbccd93dd8ba2d54bf59dff5aee65921134aab15a4cd457c56", "dependencies": [ "jsr:@deno/loader@~0.3.2", "jsr:@fresh/core@2", - "jsr:@fresh/core@^2.1.4", + "jsr:@fresh/core@^2.2.0", "jsr:@std/dotenv", "jsr:@std/fmt@^1.0.7", "jsr:@std/path@1", @@ -267,10 +258,10 @@ "@hono/hono@4.11.4": { "integrity": "aaf7b9d5a6b2422b0778c091b712ee1f018bc7e82138067d21eb27d7c2e1f5be" }, - "@logtape/file@2.0.0": { - "integrity": "beb77f53a5792f4a3e22a8cbdb0f78d2c92c62700ccbff42eac7cf42cb3dac42", + "@logtape/file@2.0.2": { + "integrity": "a912459fe0d27213e05c95e6fadf716000f27eafa27e67c2737820ba24097fdc", "dependencies": [ - "jsr:@logtape/logtape@2", + "jsr:@logtape/logtape@^2.0.2", "jsr:@std/path@^1.1.0" ] }, @@ -280,11 +271,14 @@ "@logtape/logtape@1.3.6": { "integrity": "d9a038ed8f85981d7c1cd43d931402ef52bc036cfd14bc9be5bdfc7ec8136b6f" }, - "@logtape/logtape@2.0.0": { - "integrity": "c4f2d7684a8239ad9b3fc2fd4ade6eec9f04cdb3a1741bae83f370b4b34253b2" + "@logtape/logtape@1.3.7": { + "integrity": "d9dc1f8c7e2e1e4e3998006ea84eaf4054e40ad39325b056b3f517c013286bed" }, - "@optique/config@0.10.0-dev.347+14bbe4ef": { - "integrity": "bb13747533b7d667d9213dfbd0d7be5f0ecac6eceef031ce6afdea7db1acb9ef", + "@logtape/logtape@2.0.2": { + "integrity": "546fcd514e66f2b841c6f261fa3a3d905b52d876dc1bba8ffe1a087d9275c4c9" + }, + "@optique/config@0.10.0-dev.348+3a6d010a": { + "integrity": "5bb164e52625179cf012a129ee19d4d1ec3cabde07fe9faa055e1af3ddca8519", "dependencies": [ "npm:@standard-schema/spec" ] @@ -292,11 +286,11 @@ "@optique/core@0.10.0-dev.333+076fceae": { "integrity": "1ebe1782740f08d568ae0c5258786933a8502d1e137feb49b2d8ab06d204b11a" }, - "@optique/core@0.10.0-dev.347+14bbe4ef": { - "integrity": "fbb90bcf73156f3f5e32b2fb7aa4f70d006977edc68d94bfa951944f0f3d9bdc" + "@optique/core@0.10.0-dev.348+3a6d010a": { + "integrity": "5ab1e09d13c3a6b7e28a8a110f170e03d25ae064fe7d6aee5d346bb5cc0878cf" }, - "@optique/run@0.10.0-dev.347+14bbe4ef": { - "integrity": "7b8c3d3804e873ee8d124bf26eca4adcd1fa55b6d30ca6b457b43e34bac52b50" + "@optique/run@0.10.0-dev.348+3a6d010a": { + "integrity": "56c797164fed0576b28262cdc2b7152084b6b40b9c1d6bfa83c7762a44829901" }, "@std/assert@0.224.0": { "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", @@ -311,8 +305,8 @@ "jsr:@std/internal@1" ] }, - "@std/assert@1.0.16": { - "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", + "@std/assert@1.0.18": { + "integrity": "270245e9c2c13b446286de475131dc688ca9abcd94fc5db41d43a219b34d1c78", "dependencies": [ "jsr:@std/internal@^1.0.12" ] @@ -332,8 +326,8 @@ "@std/fmt@0.224.0": { "integrity": "e20e9a2312a8b5393272c26191c0a68eda8d2c4b08b046bad1673148f1d69851" }, - "@std/fmt@1.0.8": { - "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" + "@std/fmt@1.0.9": { + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" }, "@std/fs@0.224.0": { "integrity": "52a5ec89731ac0ca8f971079339286f88c571a4d61686acf75833f03a89d8e69", @@ -341,8 +335,8 @@ "jsr:@std/path@0.224" ] }, - "@std/fs@1.0.21": { - "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd", + "@std/fs@1.0.22": { + "integrity": "de0f277a58a867147a8a01bc1b181d0dfa80bfddba8c9cf2bacd6747bcec9308", "dependencies": [ "jsr:@std/internal@^1.0.12", "jsr:@std/path@^1.1.4" @@ -351,8 +345,8 @@ "@std/html@1.0.5": { "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" }, - "@std/http@1.0.23": { - "integrity": "6634e9e034c589bf35101c1b5ee5bbf052a5987abca20f903e58bdba85c80dee", + "@std/http@1.0.24": { + "integrity": "4dd59afd7cfd6e2e96e175b67a5a829b449ae55f08575721ec691e5d85d886d4", "dependencies": [ "jsr:@std/encoding" ] @@ -366,10 +360,10 @@ "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" }, - "@std/io@0.225.2": { - "integrity": "3c740cd4ee4c082e6cfc86458f47e2ab7cb353dc6234d5e9b1f91a2de5f4d6c7", + "@std/io@0.225.3": { + "integrity": "27b07b591384d12d7b568f39e61dff966b8230559122df1e9fd11cc068f7ddd1", "dependencies": [ - "jsr:@std/bytes@^1.0.5" + "jsr:@std/bytes" ] }, "@std/json@1.0.2": { @@ -393,8 +387,8 @@ "jsr:@std/internal@^1.0.12" ] }, - "@std/semver@1.0.7": { - "integrity": "7d5f65391762dc4358abde80fc3354086ddb40101f140295e60f290c138887d0" + "@std/semver@1.0.8": { + "integrity": "dc830e8b8b6a380c895d53fbfd1258dc253704ca57bbe1629ac65fd7830179b7" }, "@std/testing@0.224.0": { "integrity": "371b8a929aa7132240d5dd766a439be8f780ef5c176ab194e0bcab72370c761e", @@ -408,7 +402,7 @@ "@std/uuid@1.1.0": { "integrity": "6268db2ccf172849c9be80763354ca305d49ef4af41fe995623d44fcc3f7457c", "dependencies": [ - "jsr:@std/bytes@^1.0.6" + "jsr:@std/bytes" ] }, "@std/yaml@1.0.10": { @@ -419,19 +413,19 @@ "@alinea/suite@0.6.3": { "integrity": "sha512-4oGhbwAGq3rQeuuq9ylmybMkIT1mAl6e+DiiTLwwmwNzHFQiVihishgOpkIGrs0fGVSD4T8jOLyNTuQ30RtVuQ==" }, - "@babel/code-frame@7.28.6": { - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "@babel/code-frame@7.29.0": { + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dependencies": [ "@babel/helper-validator-identifier", "js-tokens@4.0.0", "picocolors" ] }, - "@babel/compat-data@7.28.6": { - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==" + "@babel/compat-data@7.29.0": { + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==" }, - "@babel/core@7.28.6": { - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "@babel/core@7.29.0": { + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dependencies": [ "@babel/code-frame", "@babel/generator", @@ -450,8 +444,8 @@ "semver@6.3.1" ] }, - "@babel/generator@7.28.6": { - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "@babel/generator@7.29.1": { + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dependencies": [ "@babel/parser", "@babel/types", @@ -486,7 +480,7 @@ "@babel/types" ] }, - "@babel/helper-module-transforms@7.28.6_@babel+core@7.28.6": { + "@babel/helper-module-transforms@7.28.6_@babel+core@7.29.0": { "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dependencies": [ "@babel/core", @@ -514,35 +508,35 @@ "@babel/types" ] }, - "@babel/parser@7.28.6": { - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "@babel/parser@7.29.0": { + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", "dependencies": [ "@babel/types" ], "bin": true }, - "@babel/plugin-syntax-jsx@7.28.6_@babel+core@7.28.6": { + "@babel/plugin-syntax-jsx@7.28.6_@babel+core@7.29.0": { "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.28.6": { + "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.29.0": { "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", "dependencies": [ "@babel/core", "@babel/helper-plugin-utils" ] }, - "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.28.6": { + "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.29.0": { "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", "dependencies": [ "@babel/core", "@babel/plugin-transform-react-jsx" ] }, - "@babel/plugin-transform-react-jsx@7.28.6_@babel+core@7.28.6": { + "@babel/plugin-transform-react-jsx@7.28.6_@babel+core@7.29.0": { "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==", "dependencies": [ "@babel/core", @@ -553,7 +547,7 @@ "@babel/types" ] }, - "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.28.6": { + "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.29.0": { "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", "dependencies": [ "@babel/core", @@ -561,7 +555,7 @@ "@babel/helper-plugin-utils" ] }, - "@babel/preset-react@7.28.5_@babel+core@7.28.6": { + "@babel/preset-react@7.28.5_@babel+core@7.29.0": { "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", "dependencies": [ "@babel/core", @@ -581,8 +575,8 @@ "@babel/types" ] }, - "@babel/traverse@7.28.6": { - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "@babel/traverse@7.29.0": { + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dependencies": [ "@babel/code-frame", "@babel/generator", @@ -593,8 +587,8 @@ "debug@4.4.3" ] }, - "@babel/types@7.28.6": { - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "@babel/types@7.29.0": { + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dependencies": [ "@babel/helper-string-parser", "@babel/helper-validator-identifier" @@ -625,7 +619,7 @@ "workerd" ] }, - "@cloudflare/vitest-pool-workers@0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.3__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.3_@cloudflare+workers-types@4.20260109.0_tsx@4.21.0_yaml@2.8.2": { + "@cloudflare/vitest-pool-workers@0.8.71_@vitest+runner@3.2.4_@vitest+snapshot@3.2.4_vitest@3.2.4__@types+node@22.19.10__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__tsx@4.21.0__yaml@2.8.2_@types+node@22.19.10_@cloudflare+workers-types@4.20260210.0_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-keu2HCLQfRNwbmLBCDXJgCFpANTaYnQpE01fBOo4CNwiWHUT7SZGN7w64RKiSWRHyYppStXBuE5Ng7F42+flpg==", "dependencies": [ "@vitest/runner", @@ -634,7 +628,7 @@ "cjs-module-lexer", "devalue", "miniflare", - "semver@7.7.3", + "semver@7.7.4", "vitest", "wrangler", "zod@3.25.76" @@ -665,8 +659,8 @@ "os": ["win32"], "cpu": ["x64"] }, - "@cloudflare/workers-types@4.20260109.0": { - "integrity": "sha512-90vx2lVm+fhQyE8FKqNhT8JBI8GuY0biAwxTzvzeRIdWVo2ArCpUfYMYq4kzaGTfA6NwCmXmBFSgnqfG6OFxLw==" + "@cloudflare/workers-types@4.20260210.0": { + "integrity": "sha512-zHaF0RZVYUQwNCJCECnNAJdMur72Lk3FMiD6wU78Dx3Bv7DQRcuXNmPNuJmsGnosVZCcWintHlPTQ/4BEiDG5w==" }, "@colors/colors@1.5.0": { "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" @@ -718,8 +712,8 @@ "os": ["aix"], "cpu": ["ppc64"] }, - "@esbuild/aix-ppc64@0.27.2": { - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "@esbuild/aix-ppc64@0.27.3": { + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", "os": ["aix"], "cpu": ["ppc64"] }, @@ -738,8 +732,8 @@ "os": ["android"], "cpu": ["arm64"] }, - "@esbuild/android-arm64@0.27.2": { - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "@esbuild/android-arm64@0.27.3": { + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", "os": ["android"], "cpu": ["arm64"] }, @@ -758,8 +752,8 @@ "os": ["android"], "cpu": ["arm"] }, - "@esbuild/android-arm@0.27.2": { - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "@esbuild/android-arm@0.27.3": { + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", "os": ["android"], "cpu": ["arm"] }, @@ -778,8 +772,8 @@ "os": ["android"], "cpu": ["x64"] }, - "@esbuild/android-x64@0.27.2": { - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "@esbuild/android-x64@0.27.3": { + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", "os": ["android"], "cpu": ["x64"] }, @@ -798,8 +792,8 @@ "os": ["darwin"], "cpu": ["arm64"] }, - "@esbuild/darwin-arm64@0.27.2": { - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "@esbuild/darwin-arm64@0.27.3": { + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", "os": ["darwin"], "cpu": ["arm64"] }, @@ -818,8 +812,8 @@ "os": ["darwin"], "cpu": ["x64"] }, - "@esbuild/darwin-x64@0.27.2": { - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "@esbuild/darwin-x64@0.27.3": { + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", "os": ["darwin"], "cpu": ["x64"] }, @@ -838,8 +832,8 @@ "os": ["freebsd"], "cpu": ["arm64"] }, - "@esbuild/freebsd-arm64@0.27.2": { - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "@esbuild/freebsd-arm64@0.27.3": { + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", "os": ["freebsd"], "cpu": ["arm64"] }, @@ -858,8 +852,8 @@ "os": ["freebsd"], "cpu": ["x64"] }, - "@esbuild/freebsd-x64@0.27.2": { - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "@esbuild/freebsd-x64@0.27.3": { + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", "os": ["freebsd"], "cpu": ["x64"] }, @@ -878,8 +872,8 @@ "os": ["linux"], "cpu": ["arm64"] }, - "@esbuild/linux-arm64@0.27.2": { - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "@esbuild/linux-arm64@0.27.3": { + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", "os": ["linux"], "cpu": ["arm64"] }, @@ -898,8 +892,8 @@ "os": ["linux"], "cpu": ["arm"] }, - "@esbuild/linux-arm@0.27.2": { - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "@esbuild/linux-arm@0.27.3": { + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", "os": ["linux"], "cpu": ["arm"] }, @@ -918,8 +912,8 @@ "os": ["linux"], "cpu": ["ia32"] }, - "@esbuild/linux-ia32@0.27.2": { - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "@esbuild/linux-ia32@0.27.3": { + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", "os": ["linux"], "cpu": ["ia32"] }, @@ -938,8 +932,8 @@ "os": ["linux"], "cpu": ["loong64"] }, - "@esbuild/linux-loong64@0.27.2": { - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "@esbuild/linux-loong64@0.27.3": { + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", "os": ["linux"], "cpu": ["loong64"] }, @@ -958,8 +952,8 @@ "os": ["linux"], "cpu": ["mips64el"] }, - "@esbuild/linux-mips64el@0.27.2": { - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "@esbuild/linux-mips64el@0.27.3": { + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", "os": ["linux"], "cpu": ["mips64el"] }, @@ -978,8 +972,8 @@ "os": ["linux"], "cpu": ["ppc64"] }, - "@esbuild/linux-ppc64@0.27.2": { - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "@esbuild/linux-ppc64@0.27.3": { + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", "os": ["linux"], "cpu": ["ppc64"] }, @@ -998,8 +992,8 @@ "os": ["linux"], "cpu": ["riscv64"] }, - "@esbuild/linux-riscv64@0.27.2": { - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "@esbuild/linux-riscv64@0.27.3": { + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", "os": ["linux"], "cpu": ["riscv64"] }, @@ -1018,8 +1012,8 @@ "os": ["linux"], "cpu": ["s390x"] }, - "@esbuild/linux-s390x@0.27.2": { - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "@esbuild/linux-s390x@0.27.3": { + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", "os": ["linux"], "cpu": ["s390x"] }, @@ -1038,8 +1032,8 @@ "os": ["linux"], "cpu": ["x64"] }, - "@esbuild/linux-x64@0.27.2": { - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "@esbuild/linux-x64@0.27.3": { + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", "os": ["linux"], "cpu": ["x64"] }, @@ -1058,8 +1052,8 @@ "os": ["netbsd"], "cpu": ["arm64"] }, - "@esbuild/netbsd-arm64@0.27.2": { - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "@esbuild/netbsd-arm64@0.27.3": { + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", "os": ["netbsd"], "cpu": ["arm64"] }, @@ -1078,8 +1072,8 @@ "os": ["netbsd"], "cpu": ["x64"] }, - "@esbuild/netbsd-x64@0.27.2": { - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "@esbuild/netbsd-x64@0.27.3": { + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", "os": ["netbsd"], "cpu": ["x64"] }, @@ -1098,8 +1092,8 @@ "os": ["openbsd"], "cpu": ["arm64"] }, - "@esbuild/openbsd-arm64@0.27.2": { - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "@esbuild/openbsd-arm64@0.27.3": { + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", "os": ["openbsd"], "cpu": ["arm64"] }, @@ -1118,8 +1112,8 @@ "os": ["openbsd"], "cpu": ["x64"] }, - "@esbuild/openbsd-x64@0.27.2": { - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "@esbuild/openbsd-x64@0.27.3": { + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", "os": ["openbsd"], "cpu": ["x64"] }, @@ -1133,8 +1127,8 @@ "os": ["openharmony"], "cpu": ["arm64"] }, - "@esbuild/openharmony-arm64@0.27.2": { - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "@esbuild/openharmony-arm64@0.27.3": { + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", "os": ["openharmony"], "cpu": ["arm64"] }, @@ -1153,8 +1147,8 @@ "os": ["sunos"], "cpu": ["x64"] }, - "@esbuild/sunos-x64@0.27.2": { - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "@esbuild/sunos-x64@0.27.3": { + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", "os": ["sunos"], "cpu": ["x64"] }, @@ -1173,8 +1167,8 @@ "os": ["win32"], "cpu": ["arm64"] }, - "@esbuild/win32-arm64@0.27.2": { - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "@esbuild/win32-arm64@0.27.3": { + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", "os": ["win32"], "cpu": ["arm64"] }, @@ -1193,8 +1187,8 @@ "os": ["win32"], "cpu": ["ia32"] }, - "@esbuild/win32-ia32@0.27.2": { - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "@esbuild/win32-ia32@0.27.3": { + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", "os": ["win32"], "cpu": ["ia32"] }, @@ -1213,8 +1207,8 @@ "os": ["win32"], "cpu": ["x64"] }, - "@esbuild/win32-x64@0.27.2": { - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "@esbuild/win32-x64@0.27.3": { + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", "os": ["win32"], "cpu": ["x64"] }, @@ -1308,8 +1302,8 @@ "ipaddr.js@2.3.0" ] }, - "@fxts/core@1.23.0": { - "integrity": "sha512-URaV1oAhU64s4zfhzMIAB444aDB1fyLHcS7tEw3TrHll7YExbks/FimjrJN2MXrHVB0jXBtGeTTpW5k40R7NXg==", + "@fxts/core@1.25.0": { + "integrity": "sha512-olXPKT/LuNCVwKfVmE4G0lDFMndv+jl7k3mQkBv8ZbXqQvdQJq3nCi2wiUaZHms4eeCimWeZ5uLemW0thlnVUw==", "dependencies": [ "tslib" ] @@ -1460,38 +1454,38 @@ "@inquirer/ansi@1.0.2": { "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==" }, - "@inquirer/checkbox@4.3.2_@types+node@22.19.3": { + "@inquirer/checkbox@4.3.2_@types+node@22.19.10": { "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/confirm@5.1.21_@types+node@22.19.3": { + "@inquirer/confirm@5.1.21_@types+node@22.19.10": { "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3" + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/core@10.3.2_@types+node@22.19.3": { + "@inquirer/core@10.3.2_@types+node@22.19.10": { "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", "dependencies": [ "@inquirer/ansi", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "cli-width", "mute-stream@2.0.0", "signal-exit", @@ -1499,7 +1493,7 @@ "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, "@inquirer/core@8.2.4": { @@ -1508,7 +1502,7 @@ "@inquirer/figures", "@inquirer/type@1.5.5", "@types/mute-stream", - "@types/node@20.19.27", + "@types/node@20.19.33", "@types/wrap-ansi", "ansi-escapes", "cli-spinners", @@ -1520,79 +1514,79 @@ "wrap-ansi@6.2.0" ] }, - "@inquirer/editor@4.2.23_@types+node@22.19.3": { + "@inquirer/editor@4.2.23_@types+node@22.19.10": { "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", "@inquirer/external-editor", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3" + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/expand@4.0.23_@types+node@22.19.3": { + "@inquirer/expand@4.0.23_@types+node@22.19.10": { "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/external-editor@1.0.3_@types+node@22.19.3": { + "@inquirer/external-editor@1.0.3_@types+node@22.19.10": { "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "dependencies": [ - "@types/node@22.19.3", + "@types/node@22.19.10", "chardet", "iconv-lite@0.7.2" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, "@inquirer/figures@1.0.15": { "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==" }, - "@inquirer/input@4.3.1_@types+node@22.19.3": { + "@inquirer/input@4.3.1_@types+node@22.19.10": { "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3" + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/number@3.0.23_@types+node@22.19.3": { + "@inquirer/number@3.0.23_@types+node@22.19.10": { "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3" + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/password@4.0.23_@types+node@22.19.3": { + "@inquirer/password@4.0.23_@types+node@22.19.10": { "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3" + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/prompts@7.10.1_@types+node@22.19.3": { + "@inquirer/prompts@7.10.1_@types+node@22.19.10": { "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", "dependencies": [ "@inquirer/checkbox", @@ -1605,49 +1599,49 @@ "@inquirer/rawlist", "@inquirer/search", "@inquirer/select", - "@types/node@22.19.3" + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/rawlist@4.1.11_@types+node@22.19.3": { + "@inquirer/rawlist@4.1.11_@types+node@22.19.10": { "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/search@3.2.2_@types+node@22.19.3": { + "@inquirer/search@3.2.2_@types+node@22.19.10": { "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", "dependencies": [ - "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "@inquirer/select@4.4.2_@types+node@22.19.3": { + "@inquirer/select@4.4.2_@types+node@22.19.10": { "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", "@inquirer/figures", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "yoctocolors-cjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, "@inquirer/type@1.5.5": { @@ -1656,13 +1650,13 @@ "mute-stream@1.0.0" ] }, - "@inquirer/type@3.0.10_@types+node@22.19.3": { + "@inquirer/type@3.0.10_@types+node@22.19.10": { "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", "dependencies": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, "@ioredis/commands@1.5.0": { @@ -2018,10 +2012,10 @@ "@tybys/wasm-util" ] }, - "@nestjs/common@11.1.11_reflect-metadata@0.2.2_rxjs@7.8.2": { - "integrity": "sha512-R/+A8XFqLgN8zNs2twhrOaE7dJbRQhdPX3g46am4RT/x8xGLqDphrXkUIno4cGUZHxbczChBAaAPTdPv73wDZA==", + "@nestjs/common@11.1.13_reflect-metadata@0.2.2_rxjs@7.8.2": { + "integrity": "sha512-ieqWtipT+VlyDWLz5Rvz0f3E5rXcVAnaAi+D53DEHLjc1kmFxCgZ62qVfTX2vwkywwqNkTNXvBgGR72hYqV//Q==", "dependencies": [ - "file-type@21.2.0", + "file-type@21.3.0", "iterare", "load-esm", "reflect-metadata", @@ -2036,96 +2030,57 @@ "@opentelemetry/api@1.9.0": { "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, - "@opentelemetry/context-async-hooks@1.30.1_@opentelemetry+api@1.9.0": { - "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", - "dependencies": [ - "@opentelemetry/api" - ] - }, - "@opentelemetry/context-async-hooks@2.5.0_@opentelemetry+api@1.9.0": { - "integrity": "sha512-uOXpVX0ZjO7heSVjhheW2XEPrhQAWr2BScDPoZ9UDycl5iuHG+Usyc3AIfG6kZeC1GyLpMInpQ6X5+9n69yOFw==", - "dependencies": [ - "@opentelemetry/api" - ] - }, - "@opentelemetry/core@1.30.1_@opentelemetry+api@1.9.0": { - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "dependencies": [ - "@opentelemetry/api", - "@opentelemetry/semantic-conventions@1.28.0" - ] - }, "@opentelemetry/core@2.5.0_@opentelemetry+api@1.9.0": { "integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==", "dependencies": [ "@opentelemetry/api", - "@opentelemetry/semantic-conventions@1.39.0" - ] - }, - "@opentelemetry/resources@1.30.1_@opentelemetry+api@1.9.0": { - "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", - "dependencies": [ - "@opentelemetry/api", - "@opentelemetry/core@1.30.1_@opentelemetry+api@1.9.0", - "@opentelemetry/semantic-conventions@1.28.0" + "@opentelemetry/semantic-conventions" ] }, "@opentelemetry/resources@2.5.0_@opentelemetry+api@1.9.0": { "integrity": "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==", "dependencies": [ "@opentelemetry/api", - "@opentelemetry/core@2.5.0_@opentelemetry+api@1.9.0", - "@opentelemetry/semantic-conventions@1.39.0" - ] - }, - "@opentelemetry/sdk-trace-base@1.30.1_@opentelemetry+api@1.9.0": { - "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", - "dependencies": [ - "@opentelemetry/api", - "@opentelemetry/core@1.30.1_@opentelemetry+api@1.9.0", - "@opentelemetry/resources@1.30.1_@opentelemetry+api@1.9.0", - "@opentelemetry/semantic-conventions@1.28.0" + "@opentelemetry/core", + "@opentelemetry/semantic-conventions" ] }, "@opentelemetry/sdk-trace-base@2.5.0_@opentelemetry+api@1.9.0": { "integrity": "sha512-VzRf8LzotASEyNDUxTdaJ9IRJ1/h692WyArDBInf5puLCjxbICD6XkHgpuudis56EndyS7LYFmtTMny6UABNdQ==", "dependencies": [ "@opentelemetry/api", - "@opentelemetry/core@2.5.0_@opentelemetry+api@1.9.0", - "@opentelemetry/resources@2.5.0_@opentelemetry+api@1.9.0", - "@opentelemetry/semantic-conventions@1.39.0" + "@opentelemetry/core", + "@opentelemetry/resources", + "@opentelemetry/semantic-conventions" ] }, - "@opentelemetry/semantic-conventions@1.28.0": { - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==" - }, "@opentelemetry/semantic-conventions@1.39.0": { "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==" }, - "@optique/config@0.10.0-dev.347_@standard-schema+spec@1.1.0": { - "integrity": "sha512-WBtkp22O/adD6bZpK2Izw5gw4eMBOwsVVo5duI51Cn0D58sqGXUuVtbGP3+uC79iQ2AfTzBwpiEqj/L8X08a2A==", + "@optique/config@0.10.0-dev.348_@standard-schema+spec@1.1.0": { + "integrity": "sha512-7zHBguVzRiost0cYK52FCnJgvzw0+Utyp/JuX5h4/yyfqApBmPrg6HuAy3cZOAYINudKDvrPYbVu/KxyT4hOBQ==", "dependencies": [ "@optique/core@0.9.2", "@standard-schema/spec" ] }, - "@optique/core@0.10.0-dev.347": { - "integrity": "sha512-VVNLLT2AspoWCy3rp/XIi07bWWWgVBUgnU+kF86le9Qzs3m25DaCSTnmj7jZ+HAvOx5NDSzhL3UGYZbr8kt3Fw==" + "@optique/core@0.10.0-dev.348": { + "integrity": "sha512-SQCtkDc8/39Snfv+G7TCw55KsTjmIFH7O1/QS/tJRtEeFcIBQz8mOff4pNT6g06Z3q9aFZtS4ATzyCQHbSfDoQ==" }, "@optique/core@0.9.2": { "integrity": "sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==" }, - "@optique/run@0.10.0-dev.347": { - "integrity": "sha512-rZ2GZ1zjzZkvR62/AVdWyLKOujgrOhk4eiFg2Bc9hpS1rg+4/ElMjOp3ULBc2tKuWgfjHLUyy197c5QZ+bm52g==", + "@optique/run@0.10.0-dev.348": { + "integrity": "sha512-qEbEz0UeaGcw6gQuIglWKFMtgpnq3VKEZRpRpd5LfZAsU7Fhl+fTVBOdXuKcympP1DCFSHVyEY4wNN2+Fnztiw==", "dependencies": [ - "@optique/core@0.10.0-dev.347" + "@optique/core@0.10.0-dev.348" ] }, "@oxc-project/types@0.103.0": { "integrity": "sha512-bkiYX5kaXWwUessFRSoXFkGIQTmc6dLGdxuRTrC+h8PSnIdZyuXHHlLAeTmOue5Br/a0/a7dHH0Gca6eXn9MKg==" }, - "@oxc-project/types@0.107.0": { - "integrity": "sha512-QFDRbYfV2LVx8tyqtyiah3jQPUj1mK2+RYwxyFWyGoys6XJnwTdlzO6rdNNHOPorHAu5Uo34oWRKcvNpbJarmQ==" + "@oxc-project/types@0.112.0": { + "integrity": "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ==" }, "@pinojs/redact@0.4.0": { "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==" @@ -2153,11 +2108,11 @@ "@poppinss/exception@1.2.3": { "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==" }, - "@preact/signals-core@1.12.1": { - "integrity": "sha512-BwbTXpj+9QutoZLQvbttRg5x3l5468qaV2kufh+51yha1c53ep5dY4kTuZR35+3pAZxpfQerGJiQqg34ZNZ6uA==" + "@preact/signals-core@1.13.0": { + "integrity": "sha512-slT6XeTCAbdql61GVLlGU4x7XHI7kCZV5Um5uhE4zLX4ApgiiXc0UYFvVOKq06xcovzp7p+61l68oPi563ARKg==" }, - "@preact/signals@2.5.1_preact@10.19.6": { - "integrity": "sha512-VPjk5YFt7i11Fi4UK0tzaEe5xLwfhUxXL3l89ocxQ5aPz7bRo8M5+N73LjBMPklyXKYKz6YsNo4Smp8n6nplng==", + "@preact/signals@2.7.1_preact@10.19.6": { + "integrity": "sha512-mP2+wMYHqDXVKFGzjqkL6CiHj3okB8eVTTJUZBrSVGozi/XfA+zZRCEALKKZYRoSoqLyT4J6qM4lhwT9155s1Q==", "dependencies": [ "@preact/signals-core", "preact@10.19.6" @@ -2175,7 +2130,7 @@ "@prefresh/utils@1.2.1": { "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" }, - "@prefresh/vite@2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "@prefresh/vite@2.4.11_preact@10.19.6_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-/XjURQqdRiCG3NpMmWqE9kJwrg9IchIOWHzulCfqg2sRe/8oQ1g5De7xrk9lbqPIQLn7ntBkKdqWXIj4E9YXyg==", "dependencies": [ "@babel/core", @@ -2198,8 +2153,8 @@ "os": ["android"], "cpu": ["arm64"] }, - "@rolldown/binding-android-arm64@1.0.0-beta.59": { - "integrity": "sha512-6yLLgyswYwiCfls9+hoNFY9F8TQdwo15hpXDHzlAR0X/GojeKF+AuNcXjYNbOJ4zjl/5D6lliE8CbpB5t1OWIQ==", + "@rolldown/binding-android-arm64@1.0.0-rc.3": { + "integrity": "sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ==", "os": ["android"], "cpu": ["arm64"] }, @@ -2208,8 +2163,8 @@ "os": ["darwin"], "cpu": ["arm64"] }, - "@rolldown/binding-darwin-arm64@1.0.0-beta.59": { - "integrity": "sha512-hqGXRc162qCCIOAcHN2Cw4eXiVTwYsMFLOhAy1IG2CxY+dwc/l4Ga+dLPkLor3Ikqy5WDn+7kxHbbh6EmshEpQ==", + "@rolldown/binding-darwin-arm64@1.0.0-rc.3": { + "integrity": "sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A==", "os": ["darwin"], "cpu": ["arm64"] }, @@ -2218,8 +2173,8 @@ "os": ["darwin"], "cpu": ["x64"] }, - "@rolldown/binding-darwin-x64@1.0.0-beta.59": { - "integrity": "sha512-ezvvGuhteE15JmMhJW0wS7BaXmhwLy1YHeEwievYaPC1PgGD86wgBKfOpHr9tSKllAXbCe0BeeMvasscWLhKdA==", + "@rolldown/binding-darwin-x64@1.0.0-rc.3": { + "integrity": "sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw==", "os": ["darwin"], "cpu": ["x64"] }, @@ -2228,8 +2183,8 @@ "os": ["freebsd"], "cpu": ["x64"] }, - "@rolldown/binding-freebsd-x64@1.0.0-beta.59": { - "integrity": "sha512-4fhKVJiEYVd5n6no/mrL3LZ9kByfCGwmONOrdtvx8DJGDQhehH/q3RfhG3V/4jGKhpXgbDjpIjkkFdybCTcgew==", + "@rolldown/binding-freebsd-x64@1.0.0-rc.3": { + "integrity": "sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww==", "os": ["freebsd"], "cpu": ["x64"] }, @@ -2238,8 +2193,8 @@ "os": ["linux"], "cpu": ["arm"] }, - "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59": { - "integrity": "sha512-T3Y52sW6JAhvIqArBw+wtjNU1Ieaz4g0NBxyjSJoW971nZJBZygNlSYx78G4cwkCmo1dYTciTPDOnQygLV23pA==", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3": { + "integrity": "sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag==", "os": ["linux"], "cpu": ["arm"] }, @@ -2248,8 +2203,8 @@ "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59": { - "integrity": "sha512-NIW40jQDSQap2KDdmm9z3B/4OzWJ6trf8dwx3FD74kcQb3v34ThsBFTtzE5KjDuxnxgUlV+DkAu+XgSMKrgufw==", + "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3": { + "integrity": "sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw==", "os": ["linux"], "cpu": ["arm64"] }, @@ -2258,8 +2213,8 @@ "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-arm64-musl@1.0.0-beta.59": { - "integrity": "sha512-CCKEk+H+8c0WGe/8n1E20n85Tq4Pv+HNAbjP1KfUXW+01aCWSMjU56ChNrM2tvHnXicfm7QRNoZyfY8cWh7jLQ==", + "@rolldown/binding-linux-arm64-musl@1.0.0-rc.3": { + "integrity": "sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA==", "os": ["linux"], "cpu": ["arm64"] }, @@ -2268,8 +2223,8 @@ "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-linux-x64-gnu@1.0.0-beta.59": { - "integrity": "sha512-VlfwJ/HCskPmQi8R0JuAFndySKVFX7yPhE658o27cjSDWWbXVtGkSbwaxstii7Q+3Rz87ZXN+HLnb1kd4R9Img==", + "@rolldown/binding-linux-x64-gnu@1.0.0-rc.3": { + "integrity": "sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ==", "os": ["linux"], "cpu": ["x64"] }, @@ -2278,8 +2233,8 @@ "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-linux-x64-musl@1.0.0-beta.59": { - "integrity": "sha512-kuO92hTRyGy0Ts3Nsqll0rfO8eFsEJe9dGQGktkQnZ2hrJrDVN0y419dMgKy/gB2S2o7F2dpWhpfQOBehZPwVA==", + "@rolldown/binding-linux-x64-musl@1.0.0-rc.3": { + "integrity": "sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw==", "os": ["linux"], "cpu": ["x64"] }, @@ -2288,8 +2243,8 @@ "os": ["openharmony"], "cpu": ["arm64"] }, - "@rolldown/binding-openharmony-arm64@1.0.0-beta.59": { - "integrity": "sha512-PXAebvNL4sYfCqi8LdY4qyFRacrRoiPZLo3NoUmiTxm7MPtYYR8CNtBGNokqDmMuZIQIecRaD/jbmFAIDz7DxQ==", + "@rolldown/binding-openharmony-arm64@1.0.0-rc.3": { + "integrity": "sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ==", "os": ["openharmony"], "cpu": ["arm64"] }, @@ -2300,8 +2255,8 @@ ], "cpu": ["wasm32"] }, - "@rolldown/binding-wasm32-wasi@1.0.0-beta.59": { - "integrity": "sha512-yJoklQg7XIZq8nAg0bbkEXcDK6sfpjxQGxpg2Nd6ERNtvg+eOaEBRgPww0BVTrYFQzje1pB5qPwC2VnJHT3koQ==", + "@rolldown/binding-wasm32-wasi@1.0.0-rc.3": { + "integrity": "sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g==", "dependencies": [ "@napi-rs/wasm-runtime" ], @@ -2312,8 +2267,8 @@ "os": ["win32"], "cpu": ["arm64"] }, - "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59": { - "integrity": "sha512-ljZ4+McmCbIuZwEBaoGtiG8Rq2nJjaXEnLEIx+usWetXn1ECjXY0LAhkELxOV6ytv4ensEmoJJ8nXg47hRMjlw==", + "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3": { + "integrity": "sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg==", "os": ["win32"], "cpu": ["arm64"] }, @@ -2322,16 +2277,16 @@ "os": ["win32"], "cpu": ["x64"] }, - "@rolldown/binding-win32-x64-msvc@1.0.0-beta.59": { - "integrity": "sha512-bMY4tTIwbdZljW+xe/ln1hvs0SRitahQSXfWtvgAtIzgSX9Ar7KqJzU7lRm33YTRFIHLULRi53yNjw9nJGd6uQ==", + "@rolldown/binding-win32-x64-msvc@1.0.0-rc.3": { + "integrity": "sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A==", "os": ["win32"], "cpu": ["x64"] }, "@rolldown/pluginutils@1.0.0-beta.57": { "integrity": "sha512-aQNelgx14tGA+n2tNSa9x6/jeoCL9fkDeCei7nOKnHx0fEFRRMu5ReiITo+zZD5TzWDGGRjbSYCs93IfRIyTuQ==" }, - "@rolldown/pluginutils@1.0.0-beta.59": { - "integrity": "sha512-aoh6LAJRyhtazs98ydgpNOYstxUlsOV1KJXcpf/0c0vFcUA8uyd/hwKRhqE/AAPNqAho9RliGsvitCoOzREoVA==" + "@rolldown/pluginutils@1.0.0-rc.3": { + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==" }, "@rollup/pluginutils@4.2.1": { "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", @@ -2340,128 +2295,128 @@ "picomatch@2.3.1" ] }, - "@rollup/rollup-android-arm-eabi@4.55.1": { - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "@rollup/rollup-android-arm-eabi@4.57.1": { + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", "os": ["android"], "cpu": ["arm"] }, - "@rollup/rollup-android-arm64@4.55.1": { - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "@rollup/rollup-android-arm64@4.57.1": { + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", "os": ["android"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-arm64@4.55.1": { - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "@rollup/rollup-darwin-arm64@4.57.1": { + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rollup/rollup-darwin-x64@4.55.1": { - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "@rollup/rollup-darwin-x64@4.57.1": { + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", "os": ["darwin"], "cpu": ["x64"] }, - "@rollup/rollup-freebsd-arm64@4.55.1": { - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "@rollup/rollup-freebsd-arm64@4.57.1": { + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", "os": ["freebsd"], "cpu": ["arm64"] }, - "@rollup/rollup-freebsd-x64@4.55.1": { - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "@rollup/rollup-freebsd-x64@4.57.1": { + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rollup/rollup-linux-arm-gnueabihf@4.55.1": { - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "@rollup/rollup-linux-arm-gnueabihf@4.57.1": { + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm-musleabihf@4.55.1": { - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "@rollup/rollup-linux-arm-musleabihf@4.57.1": { + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", "os": ["linux"], "cpu": ["arm"] }, - "@rollup/rollup-linux-arm64-gnu@4.55.1": { - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "@rollup/rollup-linux-arm64-gnu@4.57.1": { + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-arm64-musl@4.55.1": { - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "@rollup/rollup-linux-arm64-musl@4.57.1": { + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", "os": ["linux"], "cpu": ["arm64"] }, - "@rollup/rollup-linux-loong64-gnu@4.55.1": { - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "@rollup/rollup-linux-loong64-gnu@4.57.1": { + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", "os": ["linux"], "cpu": ["loong64"] }, - "@rollup/rollup-linux-loong64-musl@4.55.1": { - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "@rollup/rollup-linux-loong64-musl@4.57.1": { + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", "os": ["linux"], "cpu": ["loong64"] }, - "@rollup/rollup-linux-ppc64-gnu@4.55.1": { - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "@rollup/rollup-linux-ppc64-gnu@4.57.1": { + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rollup/rollup-linux-ppc64-musl@4.55.1": { - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "@rollup/rollup-linux-ppc64-musl@4.57.1": { + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rollup/rollup-linux-riscv64-gnu@4.55.1": { - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "@rollup/rollup-linux-riscv64-gnu@4.57.1": { + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-riscv64-musl@4.55.1": { - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "@rollup/rollup-linux-riscv64-musl@4.57.1": { + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", "os": ["linux"], "cpu": ["riscv64"] }, - "@rollup/rollup-linux-s390x-gnu@4.55.1": { - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "@rollup/rollup-linux-s390x-gnu@4.57.1": { + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", "os": ["linux"], "cpu": ["s390x"] }, - "@rollup/rollup-linux-x64-gnu@4.55.1": { - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "@rollup/rollup-linux-x64-gnu@4.57.1": { + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-linux-x64-musl@4.55.1": { - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "@rollup/rollup-linux-x64-musl@4.57.1": { + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", "os": ["linux"], "cpu": ["x64"] }, - "@rollup/rollup-openbsd-x64@4.55.1": { - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "@rollup/rollup-openbsd-x64@4.57.1": { + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", "os": ["openbsd"], "cpu": ["x64"] }, - "@rollup/rollup-openharmony-arm64@4.55.1": { - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "@rollup/rollup-openharmony-arm64@4.57.1": { + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-arm64-msvc@4.55.1": { - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "@rollup/rollup-win32-arm64-msvc@4.57.1": { + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", "os": ["win32"], "cpu": ["arm64"] }, - "@rollup/rollup-win32-ia32-msvc@4.55.1": { - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "@rollup/rollup-win32-ia32-msvc@4.57.1": { + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", "os": ["win32"], "cpu": ["ia32"] }, - "@rollup/rollup-win32-x64-gnu@4.55.1": { - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "@rollup/rollup-win32-x64-gnu@4.57.1": { + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", "os": ["win32"], "cpu": ["x64"] }, - "@rollup/rollup-win32-x64-msvc@4.55.1": { - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "@rollup/rollup-win32-x64-msvc@4.57.1": { + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", "os": ["win32"], "cpu": ["x64"] }, @@ -2531,8 +2486,8 @@ "acorn@8.15.0" ] }, - "@sveltejs/kit@2.49.4_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-JFtOqDoU0DI/+QSG8qnq5bKcehVb3tCHhOG4amsSYth5/KgO4EkJvi42xSAiyKmXAAULW1/Zdb6lkgGEgSxdZg==", + "@sveltejs/kit@2.50.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_acorn@8.15.0_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==", "dependencies": [ "@opentelemetry/api", "@standard-schema/spec", @@ -2547,7 +2502,7 @@ "magic-string", "mrmime", "sade", - "set-cookie-parser", + "set-cookie-parser@3.0.1", "sirv", "svelte", "vite" @@ -2557,7 +2512,7 @@ ], "bin": true }, - "@sveltejs/vite-plugin-svelte-inspector@5.0.2_@sveltejs+vite-plugin-svelte@6.2.3__svelte@5.46.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.3___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "@sveltejs/vite-plugin-svelte-inspector@5.0.2_@sveltejs+vite-plugin-svelte@6.2.4__svelte@5.50.1___acorn@8.15.0__vite@7.3.1___@types+node@22.19.10___tsx@4.21.0___yaml@2.8.2___picomatch@4.0.3__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", "dependencies": [ "@sveltejs/vite-plugin-svelte", @@ -2566,8 +2521,8 @@ "vite" ] }, - "@sveltejs/vite-plugin-svelte@6.2.3_svelte@5.46.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { - "integrity": "sha512-a+uxqQ9j6Lxmq4plbGaNdM9hgDCZyxAv/yvuyF5iWoA2H5icZkqD3rdK155ZQgFLX2lc3NvahHG4OgKpYqYPiQ==", + "@sveltejs/vite-plugin-svelte@6.2.4_svelte@5.50.1__acorn@8.15.0_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { + "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "dependencies": [ "@sveltejs/vite-plugin-svelte-inspector", "deepmerge", @@ -2597,7 +2552,7 @@ "@types/amqplib@0.10.8": { "integrity": "sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==", "dependencies": [ - "@types/node@24.10.4" + "@types/node@24.10.12" ] }, "@types/chai@5.2.3": { @@ -2644,26 +2599,26 @@ "@types/mute-stream@0.0.4": { "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", "dependencies": [ - "@types/node@24.10.4" + "@types/node@24.10.12" ] }, "@types/node@16.9.1": { "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" }, - "@types/node@20.19.27": { - "integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==", + "@types/node@20.19.33": { + "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", "dependencies": [ "undici-types@6.21.0" ] }, - "@types/node@22.19.3": { - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "@types/node@22.19.10": { + "integrity": "sha512-tF5VOugLS/EuDlTBijk0MqABfP8UxgYazTLo3uIn3b4yJgg26QRbVYJYsDtHrjdDUIRfP70+VfhTTc+CE1yskw==", "dependencies": [ "undici-types@6.21.0" ] }, - "@types/node@24.10.4": { - "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==", + "@types/node@24.10.12": { + "integrity": "sha512-68e+T28EbdmLSTkPgs3+UacC6rzmqrcWFPQs1C8mwJhI/r5Uxr0yEuQotczNRROd1gq30NGxee+fo0rSIxpyAw==", "dependencies": [ "undici-types@7.16.0" ] @@ -2674,8 +2629,8 @@ "@types/wrap-ansi@3.0.0": { "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==" }, - "@typescript-eslint/parser@8.52.0_eslint@9.39.2_typescript@5.9.3": { - "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", + "@typescript-eslint/parser@8.55.0_eslint@9.39.2_typescript@5.9.3": { + "integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==", "dependencies": [ "@typescript-eslint/scope-manager", "@typescript-eslint/types", @@ -2686,8 +2641,8 @@ "typescript" ] }, - "@typescript-eslint/project-service@8.52.0_typescript@5.9.3": { - "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", + "@typescript-eslint/project-service@8.55.0_typescript@5.9.3": { + "integrity": "sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==", "dependencies": [ "@typescript-eslint/tsconfig-utils", "@typescript-eslint/types", @@ -2695,24 +2650,24 @@ "typescript" ] }, - "@typescript-eslint/scope-manager@8.52.0": { - "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", + "@typescript-eslint/scope-manager@8.55.0": { + "integrity": "sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==", "dependencies": [ "@typescript-eslint/types", "@typescript-eslint/visitor-keys" ] }, - "@typescript-eslint/tsconfig-utils@8.52.0_typescript@5.9.3": { - "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", + "@typescript-eslint/tsconfig-utils@8.55.0_typescript@5.9.3": { + "integrity": "sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==", "dependencies": [ "typescript" ] }, - "@typescript-eslint/types@8.52.0": { - "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==" + "@typescript-eslint/types@8.55.0": { + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==" }, - "@typescript-eslint/typescript-estree@8.52.0_typescript@5.9.3": { - "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", + "@typescript-eslint/typescript-estree@8.55.0_typescript@5.9.3": { + "integrity": "sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==", "dependencies": [ "@typescript-eslint/project-service", "@typescript-eslint/tsconfig-utils", @@ -2720,14 +2675,14 @@ "@typescript-eslint/visitor-keys", "debug@4.4.3", "minimatch@9.0.5", - "semver@7.7.3", + "semver@7.7.4", "tinyglobby", "ts-api-utils", "typescript" ] }, - "@typescript-eslint/utils@8.52.0_eslint@9.39.2_typescript@5.9.3": { - "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", + "@typescript-eslint/utils@8.55.0_eslint@9.39.2_typescript@5.9.3": { + "integrity": "sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==", "dependencies": [ "@eslint-community/eslint-utils", "@typescript-eslint/scope-manager", @@ -2737,8 +2692,8 @@ "typescript" ] }, - "@typescript-eslint/visitor-keys@8.52.0": { - "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", + "@typescript-eslint/visitor-keys@8.55.0": { + "integrity": "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==", "dependencies": [ "@typescript-eslint/types", "eslint-visitor-keys@4.2.1" @@ -2757,7 +2712,7 @@ "tinyrainbow" ] }, - "@vitest/mocker@3.2.4_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "@vitest/mocker@3.2.4_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dependencies": [ "@vitest/spy", @@ -2951,8 +2906,8 @@ "base64-js@1.5.1": { "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, - "baseline-browser-mapping@2.9.14": { - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", + "baseline-browser-mapping@2.9.19": { + "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", "bin": true }, "birpc@0.2.14": { @@ -3064,8 +3019,8 @@ "callsites@3.1.0": { "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, - "caniuse-lite@1.0.30001764": { - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==" + "caniuse-lite@1.0.30001769": { + "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==" }, "canonicalize@2.1.0": { "integrity": "sha512-F705O3xrsUtgt98j7leetNhTWPe+5S72rlL5O4jA1pKqBVQ/dT1O1D6PFxmSXvc0SUOinWS57DKx0I3CHrXJHQ==", @@ -3302,8 +3257,8 @@ "detect-libc@2.1.2": { "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" }, - "devalue@5.6.1": { - "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==" + "devalue@5.6.2": { + "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==" }, "devlop@1.1.0": { "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", @@ -3325,8 +3280,8 @@ "ee-first@1.1.1": { "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, - "electron-to-chromium@1.5.267": { - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==" + "electron-to-chromium@1.5.286": { + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==" }, "emoji-regex-xs@1.0.0": { "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==" @@ -3479,35 +3434,35 @@ "scripts": true, "bin": true }, - "esbuild@0.27.2": { - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "esbuild@0.27.3": { + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "optionalDependencies": [ - "@esbuild/aix-ppc64@0.27.2", - "@esbuild/android-arm@0.27.2", - "@esbuild/android-arm64@0.27.2", - "@esbuild/android-x64@0.27.2", - "@esbuild/darwin-arm64@0.27.2", - "@esbuild/darwin-x64@0.27.2", - "@esbuild/freebsd-arm64@0.27.2", - "@esbuild/freebsd-x64@0.27.2", - "@esbuild/linux-arm@0.27.2", - "@esbuild/linux-arm64@0.27.2", - "@esbuild/linux-ia32@0.27.2", - "@esbuild/linux-loong64@0.27.2", - "@esbuild/linux-mips64el@0.27.2", - "@esbuild/linux-ppc64@0.27.2", - "@esbuild/linux-riscv64@0.27.2", - "@esbuild/linux-s390x@0.27.2", - "@esbuild/linux-x64@0.27.2", - "@esbuild/netbsd-arm64@0.27.2", - "@esbuild/netbsd-x64@0.27.2", - "@esbuild/openbsd-arm64@0.27.2", - "@esbuild/openbsd-x64@0.27.2", - "@esbuild/openharmony-arm64@0.27.2", - "@esbuild/sunos-x64@0.27.2", - "@esbuild/win32-arm64@0.27.2", - "@esbuild/win32-ia32@0.27.2", - "@esbuild/win32-x64@0.27.2" + "@esbuild/aix-ppc64@0.27.3", + "@esbuild/android-arm@0.27.3", + "@esbuild/android-arm64@0.27.3", + "@esbuild/android-x64@0.27.3", + "@esbuild/darwin-arm64@0.27.3", + "@esbuild/darwin-x64@0.27.3", + "@esbuild/freebsd-arm64@0.27.3", + "@esbuild/freebsd-x64@0.27.3", + "@esbuild/linux-arm@0.27.3", + "@esbuild/linux-arm64@0.27.3", + "@esbuild/linux-ia32@0.27.3", + "@esbuild/linux-loong64@0.27.3", + "@esbuild/linux-mips64el@0.27.3", + "@esbuild/linux-ppc64@0.27.3", + "@esbuild/linux-riscv64@0.27.3", + "@esbuild/linux-s390x@0.27.3", + "@esbuild/linux-x64@0.27.3", + "@esbuild/netbsd-arm64@0.27.3", + "@esbuild/netbsd-x64@0.27.3", + "@esbuild/openbsd-arm64@0.27.3", + "@esbuild/openbsd-x64@0.27.3", + "@esbuild/openharmony-arm64@0.27.3", + "@esbuild/sunos-x64@0.27.3", + "@esbuild/win32-arm64@0.27.3", + "@esbuild/win32-ia32@0.27.3", + "@esbuild/win32-x64@0.27.3" ], "scripts": true, "bin": true @@ -3591,8 +3546,8 @@ "estraverse" ] }, - "esrap@2.2.1": { - "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", + "esrap@2.2.3": { + "integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==", "dependencies": [ "@jridgewell/sourcemap-codec" ] @@ -3690,8 +3645,8 @@ "fast-json-stable-stringify@2.1.0": { "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "fast-json-stringify@6.1.1_ajv@8.17.1": { - "integrity": "sha512-DbgptncYEXZqDUOEl4krff4mUiVrTZZVI7BBrQR/T3BqMj/eM1flTC1Uk2uUoLcWCxjT95xKulV/Lc6hhOZsBQ==", + "fast-json-stringify@6.3.0_ajv@8.17.1": { + "integrity": "sha512-oRCntNDY/329HJPlmdNLIdogNtt6Vyjb1WuT01Soss3slIdyUp8kAcDU3saQTOquEK8KFVfwIIF7FebxUAu+yA==", "dependencies": [ "@fastify/merge-json-schemas", "ajv@8.17.1", @@ -3716,8 +3671,8 @@ "fastify-plugin@5.1.0": { "integrity": "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==" }, - "fastify@5.6.2": { - "integrity": "sha512-dPugdGnsvYkBlENLhCgX8yhyGCsCPrpA8lFWbTNU428l+YOnLgYHR69hzV8HWPC79n536EqzqQtvhtdaCE0dKg==", + "fastify@5.7.4": { + "integrity": "sha512-e6l5NsRdaEP8rdD8VR0ErJASeyaRbzXYpmkrpr2SuvuMq6Si3lvsaVy5C+7gLanEkvjpMDzBXWE5HPeb/hgTxA==", "dependencies": [ "@fastify/ajv-compiler", "@fastify/error", @@ -3732,7 +3687,7 @@ "process-warning@5.0.0", "rfdc", "secure-json-parse", - "semver@7.7.3", + "semver@7.7.4", "toad-cache" ] }, @@ -3783,8 +3738,8 @@ "uint8array-extras" ] }, - "file-type@21.2.0": { - "integrity": "sha512-vCYBgFOrJQLoTzDyAXAL/RFfKnXXpUYt4+tipVy26nJJhT7ftgGETf2tAQF59EEL61i3MrorV/PG6tf7LJK7eg==", + "file-type@21.3.0": { + "integrity": "sha512-8kPJMIGz1Yt/aPEwOsrR97ZyZaD1Iqm8PClb1nYFclUCkBi0Ma5IsYNQzvSFS9ib51lWyIw5mIT9rWzI/xjpzA==", "dependencies": [ "@tokenizer/inflate", "strtok3@10.3.4", @@ -3884,8 +3839,8 @@ "is-stream" ] }, - "get-tsconfig@4.13.0": { - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "get-tsconfig@4.13.6": { + "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", "dependencies": [ "resolve-pkg-maps" ] @@ -3912,8 +3867,8 @@ "gopd@1.2.0": { "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, - "h3@1.15.4": { - "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", + "h3@1.15.5": { + "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", "dependencies": [ "cookie-es", "crossws", @@ -4062,24 +4017,24 @@ "@inquirer/core@8.2.4" ] }, - "inquirer@12.11.1_@types+node@22.19.3": { + "inquirer@12.11.1_@types+node@22.19.10": { "integrity": "sha512-9VF7mrY+3OmsAfjH3yKz/pLbJ5z22E23hENKw3/LNSaA/sAt3v49bDRY+Ygct1xwuKT+U+cBfTzjCPySna69Qw==", "dependencies": [ "@inquirer/ansi", - "@inquirer/core@10.3.2_@types+node@22.19.3", + "@inquirer/core@10.3.2_@types+node@22.19.10", "@inquirer/prompts", - "@inquirer/type@3.0.10_@types+node@22.19.3", - "@types/node@22.19.3", + "@inquirer/type@3.0.10_@types+node@22.19.10", + "@types/node@22.19.10", "mute-stream@2.0.0", "run-async", "rxjs" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ] }, - "ioredis@5.9.1": { - "integrity": "sha512-BXNqFQ66oOsR82g9ajFFsR8ZKrjVvYCLyeML9IvSMAsP56XH2VXBdZjmI11p65nXXJxTEt1hie3J2QeFJVgrtQ==", + "ioredis@5.9.2": { + "integrity": "sha512-tAAg/72/VxOUW7RQSX1pIxJVucYKcjFjfvj60L57jrZpYCHC3XN0WCQ3sNYL4Gmvv+7GPvTAjc+KSdeNuE8oWQ==", "dependencies": [ "@ioredis/commands", "cluster-key-slot", @@ -4329,7 +4284,7 @@ "dependencies": [ "cookie@1.1.1", "process-warning@4.0.1", - "set-cookie-parser" + "set-cookie-parser@2.7.2" ] }, "load-esm@1.0.3": { @@ -4464,7 +4419,7 @@ "glob-to-regexp", "sharp", "stoppable", - "undici@7.14.0", + "undici@7.18.2", "workerd", "ws", "youch", @@ -4691,17 +4646,17 @@ "picomatch@4.0.3": { "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==" }, - "pino-abstract-transport@2.0.0": { - "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "pino-abstract-transport@3.0.0": { + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", "dependencies": [ "split2" ] }, - "pino-std-serializers@7.0.0": { - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + "pino-std-serializers@7.1.0": { + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==" }, - "pino@10.1.0": { - "integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==", + "pino@10.3.1": { + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", "dependencies": [ "@pinojs/redact", "atomic-sleep", @@ -4771,8 +4726,8 @@ "preact@10.19.6": { "integrity": "sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==" }, - "preact@10.28.2": { - "integrity": "sha512-lbteaWGzGHdlIuiJ0l2Jq454m6kcpI1zNje6d8MlGAFlYvP2GO4ibnat7P74Esfz4sPTdM6UxtTwh/d3pwM9JA==" + "preact@10.28.3": { + "integrity": "sha512-tCmoRkPQLpBeWzpmbhryairGnhW9tKV6c6gr/w+RhoRoKEJwsjzipwp//1oCpGPOchvSLaAPlpcJi9MwMmoPyA==" }, "prelude-ls@1.2.1": { "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" @@ -4968,31 +4923,31 @@ ], "bin": true }, - "rolldown@1.0.0-beta.59": { - "integrity": "sha512-Slm000Gd8/AO9z4Kxl4r8mp/iakrbAuJ1L+7ddpkNxgQ+Vf37WPvY63l3oeyZcfuPD1DRrUYBsRPIXSOhvOsmw==", + "rolldown@1.0.0-rc.3": { + "integrity": "sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw==", "dependencies": [ - "@oxc-project/types@0.107.0", - "@rolldown/pluginutils@1.0.0-beta.59" + "@oxc-project/types@0.112.0", + "@rolldown/pluginutils@1.0.0-rc.3" ], "optionalDependencies": [ - "@rolldown/binding-android-arm64@1.0.0-beta.59", - "@rolldown/binding-darwin-arm64@1.0.0-beta.59", - "@rolldown/binding-darwin-x64@1.0.0-beta.59", - "@rolldown/binding-freebsd-x64@1.0.0-beta.59", - "@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.59", - "@rolldown/binding-linux-arm64-gnu@1.0.0-beta.59", - "@rolldown/binding-linux-arm64-musl@1.0.0-beta.59", - "@rolldown/binding-linux-x64-gnu@1.0.0-beta.59", - "@rolldown/binding-linux-x64-musl@1.0.0-beta.59", - "@rolldown/binding-openharmony-arm64@1.0.0-beta.59", - "@rolldown/binding-wasm32-wasi@1.0.0-beta.59", - "@rolldown/binding-win32-arm64-msvc@1.0.0-beta.59", - "@rolldown/binding-win32-x64-msvc@1.0.0-beta.59" + "@rolldown/binding-android-arm64@1.0.0-rc.3", + "@rolldown/binding-darwin-arm64@1.0.0-rc.3", + "@rolldown/binding-darwin-x64@1.0.0-rc.3", + "@rolldown/binding-freebsd-x64@1.0.0-rc.3", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3", + "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3", + "@rolldown/binding-linux-arm64-musl@1.0.0-rc.3", + "@rolldown/binding-linux-x64-gnu@1.0.0-rc.3", + "@rolldown/binding-linux-x64-musl@1.0.0-rc.3", + "@rolldown/binding-openharmony-arm64@1.0.0-rc.3", + "@rolldown/binding-wasm32-wasi@1.0.0-rc.3", + "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3", + "@rolldown/binding-win32-x64-msvc@1.0.0-rc.3" ], "bin": true }, - "rollup@4.55.1": { - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "rollup@4.57.1": { + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", "dependencies": [ "@types/estree" ], @@ -5074,8 +5029,8 @@ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": true }, - "semver@7.7.3": { - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "semver@7.7.4": { + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "bin": true }, "send@0.19.2": { @@ -5108,6 +5063,9 @@ "set-cookie-parser@2.7.2": { "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==" }, + "set-cookie-parser@3.0.1": { + "integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==" + }, "setimmediate@1.0.5": { "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, @@ -5119,7 +5077,7 @@ "dependencies": [ "color", "detect-libc", - "semver@7.7.3" + "semver@7.7.4" ], "optionalDependencies": [ "@img/sharp-darwin-arm64", @@ -5350,8 +5308,8 @@ "has-flag" ] }, - "svelte@5.46.1_acorn@8.15.0": { - "integrity": "sha512-ynjfCHD3nP2el70kN5Pmg37sSi0EjOm9FgHYQdC4giWG/hzO3AatzXXJJgP305uIhGQxSufJLuYWtkY8uK/8RA==", + "svelte@5.50.1_acorn@8.15.0": { + "integrity": "sha512-/Jlom4ddkISyVHXpM2O5dXP9pYnaiFrVQzPbIL1/pEoOa77ZunCb6nDgUCTNCQ/X3t64z9ukrK6R+BbB3kPR3A==", "dependencies": [ "@jridgewell/remapping", "@jridgewell/sourcemap-codec", @@ -5382,8 +5340,8 @@ "any-promise" ] }, - "thread-stream@3.1.0": { - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "thread-stream@4.0.0": { + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", "dependencies": [ "real-require" ] @@ -5475,7 +5433,7 @@ "picomatch@4.0.3", "rolldown@1.0.0-beta.57", "rolldown-plugin-dts", - "semver@7.7.3", + "semver@7.7.4", "tinyexec@1.0.2", "tinyglobby", "tree-kill", @@ -5493,7 +5451,7 @@ "tsx@4.21.0": { "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dependencies": [ - "esbuild@0.27.2", + "esbuild@0.27.3", "get-tsconfig" ], "optionalDependencies": [ @@ -5521,8 +5479,8 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "bin": true }, - "ufo@1.6.2": { - "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==" + "ufo@1.6.3": { + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==" }, "uid@2.0.2": { "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", @@ -5558,8 +5516,8 @@ "undici@6.23.0": { "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==" }, - "undici@7.14.0": { - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==" + "undici@7.18.2": { + "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==" }, "unenv@2.0.0-rc.21": { "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", @@ -5596,8 +5554,8 @@ "unist-util-is" ] }, - "unist-util-visit@5.0.0": { - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "unist-util-visit@5.1.0": { + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "dependencies": [ "@types/unist", "unist-util-is", @@ -5607,10 +5565,10 @@ "unpipe@1.0.0": { "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, - "unrun@0.2.24": { - "integrity": "sha512-xa4/O5q2jmI6EqxweJ+sOy5cyORZWcsgmi8pmABVSUyg24Fh44qJrneUHavZEMsbJbghHYWKSraFy5hDCb/m4w==", + "unrun@0.2.27": { + "integrity": "sha512-Mmur1UJpIbfxasLOhPRvox/QS4xBiDii71hMP7smfRthGcwFL2OAmYRgduLANOAU4LUkvVamuP+02U+c90jlrw==", "dependencies": [ - "rolldown@1.0.0-beta.59" + "rolldown@1.0.0-rc.3" ], "bin": true }, @@ -5674,7 +5632,7 @@ "vfile-message" ] }, - "vite-node@3.2.4_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "vite-node@3.2.4_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dependencies": [ "cac", @@ -5685,11 +5643,11 @@ ], "bin": true }, - "vite@7.3.1_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3": { + "vite@7.3.1_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2_picomatch@4.0.3": { "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dependencies": [ - "@types/node@22.19.3", - "esbuild@0.27.2", + "@types/node@22.19.10", + "esbuild@0.27.3", "fdir", "picomatch@4.0.3", "postcss", @@ -5702,13 +5660,13 @@ "fsevents" ], "optionalPeers": [ - "@types/node@22.19.3", + "@types/node@22.19.10", "tsx", "yaml" ], "bin": true }, - "vitefu@1.1.1_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.3_tsx@4.21.0_yaml@2.8.2": { + "vitefu@1.1.1_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_@types+node@22.19.10_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", "dependencies": [ "vite" @@ -5717,11 +5675,11 @@ "vite" ] }, - "vitest@3.2.4_@types+node@22.19.3_vite@7.3.1__@types+node@22.19.3__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2": { + "vitest@3.2.4_@types+node@22.19.10_vite@7.3.1__@types+node@22.19.10__tsx@4.21.0__yaml@2.8.2__picomatch@4.0.3_tsx@4.21.0_yaml@2.8.2": { "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dependencies": [ "@types/chai", - "@types/node@22.19.3", + "@types/node@22.19.10", "@vitest/expect", "@vitest/mocker", "@vitest/pretty-format", @@ -5746,7 +5704,7 @@ "why-is-node-running" ], "optionalPeers": [ - "@types/node@22.19.3" + "@types/node@22.19.10" ], "bin": true }, @@ -5796,7 +5754,7 @@ "scripts": true, "bin": true }, - "wrangler@4.35.0_@cloudflare+workers-types@4.20260109.0_unenv@2.0.0-rc.21_workerd@1.20250906.0": { + "wrangler@4.35.0_@cloudflare+workers-types@4.20260210.0_unenv@2.0.0-rc.21_workerd@1.20250906.0": { "integrity": "sha512-HbyXtbrh4Fi3mU8ussY85tVdQ74qpVS1vctUgaPc+bPrXBTqfDLkZ6VRtHAVF/eBhz4SFmhJtCQpN1caY2Ak8A==", "dependencies": [ "@cloudflare/kv-asset-handler", @@ -5919,7 +5877,6 @@ "workspace": { "dependencies": [ "jsr:@david/dax@~0.43.2", - "jsr:@hono/hono@^4.8.3", "jsr:@logtape/file@2", "jsr:@logtape/logtape@2", "jsr:@std/assert@^1.0.13", @@ -5934,10 +5891,8 @@ "npm:@js-temporal/polyfill@~0.5.1", "npm:@nestjs/common@^11.0.1", "npm:@opentelemetry/api@^1.9.0", - "npm:@opentelemetry/context-async-hooks@^2.5.0", - "npm:@opentelemetry/core@^2.5.0", - "npm:@opentelemetry/sdk-trace-base@^2.5.0", - "npm:@opentelemetry/semantic-conventions@^1.39.0", + "npm:@opentelemetry/core@2", + "npm:@opentelemetry/sdk-trace-base@2", "npm:@types/node@^22.16.0", "npm:amqplib@~0.10.9", "npm:byte-encodings@^1.0.11", @@ -5990,9 +5945,9 @@ "dependencies": [ "jsr:@hongminhee/localtunnel@0.3", "jsr:@hono/hono@^4.8.3", - "jsr:@optique/config@~0.10.0-dev.347", - "jsr:@optique/core@~0.10.0-dev.347", - "jsr:@optique/run@~0.10.0-dev.347", + "jsr:@optique/config@~0.10.0-dev.348", + "jsr:@optique/core@~0.10.0-dev.348", + "jsr:@optique/run@~0.10.0-dev.348", "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", @@ -6016,9 +5971,9 @@ "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", - "npm:@optique/config@~0.10.0-dev.347", - "npm:@optique/core@~0.10.0-dev.347", - "npm:@optique/run@~0.10.0-dev.347", + "npm:@optique/config@0.10.0-dev.348", + "npm:@optique/core@0.10.0-dev.348", + "npm:@optique/run@0.10.0-dev.348", "npm:@poppanator/http-constants@^1.1.1", "npm:chalk@^5.6.2", "npm:cli-highlight@^2.1.11", @@ -6060,6 +6015,9 @@ "jsr:@std/assert@0.226", "jsr:@std/url@~0.225.1", "npm:@multiformats/base-x@^4.0.1", + "npm:@opentelemetry/core@2", + "npm:@opentelemetry/sdk-trace-base@2", + "npm:@opentelemetry/semantic-conventions@^1.27.0", "npm:asn1js@^3.0.7", "npm:fast-check@^3.22.0", "npm:fetch-mock@^12.5.2", @@ -6074,6 +6032,7 @@ "packageJson": { "dependencies": [ "npm:@js-temporal/polyfill@~0.5.1", + "npm:@opentelemetry/semantic-conventions@^1.27.0", "npm:@types/node@^24.2.1", "npm:json-canon@^1.0.1", "npm:jsonld@9", @@ -6137,6 +6096,7 @@ }, "packages/vocab": { "dependencies": [ + "npm:@opentelemetry/api@^1.9.0", "npm:fast-check@^3.22.0", "npm:fetch-mock@^12.5.2", "npm:jsonld@9" diff --git a/packages/cli/deno.json b/packages/cli/deno.json index b41567356..b8f52e01f 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -8,10 +8,10 @@ "@inquirer/prompts": "npm:@inquirer/prompts@^7.8.4", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", - "@optique/config": "jsr:@optique/config@^0.10.0-dev.347", - "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.347/run", - "@optique/core": "jsr:@optique/core@^0.10.0-dev.347", - "@optique/run": "jsr:@optique/run@^0.10.0-dev.347", + "@optique/config": "jsr:@optique/config@^0.10.0-dev.348", + "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.348/run", + "@optique/core": "jsr:@optique/core@^0.10.0-dev.348", + "@optique/run": "jsr:@optique/run@^0.10.0-dev.348", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index e2f5908ff..3396350b0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,45 @@ { "name": "@fedify/cli", "version": "2.0.0", + "type": "module", + "files": [ + "README.md", + "package.json", + "src/install.mjs", + "src/run.mjs" + ], + "bin": { + "fedify": "./dist/mod.js" + }, + "scripts": { + "build:self": "tsdown", + "build": "pnpm --filter @fedify/cli... run build:self", + "prepack": "pnpm build", + "prepublish": "pnpm build", + "pretest": "pnpm build", + "test": "node --test --experimental-transform-types 'src/**/*.test.ts' '!src/init/test/**'", + "test-init": "deno task test-init", + "pretest:bun": "pnpm build", + "test:bun": "bun test", + "run": "pnpm build && node dist/mod.js", + "runi": "tsdown && node dist/mod.js", + "run:bun": "pnpm build && bun dist/mod.js", + "runi:bun": "tsdown && bun dist/mod.js" + }, + "engines": { + "node": ">=20.0.0", + "bun": ">=1.2.0", + "denp": ">=2.0.0" + }, + "os": [ + "darwin", + "linux", + "win32" + ], + "cpu": [ + "x64", + "arm64" + ], "description": "CLI toolchain for Fedify and debugging ActivityPub", "keywords": [ "fedify", @@ -27,15 +66,6 @@ "url": "git+https://github.com/fedify-dev/fedify.git", "directory": "packages/cli" }, - "type": "module", - "engines": { - "node": ">=20.0.0", - "bun": ">=1.2.0", - "denp": ">=2.0.0" - }, - "bin": { - "fedify": "./dist/mod.js" - }, "exports": "./dist/mod.js", "imports": { "#kv": { @@ -59,9 +89,9 @@ "@js-temporal/polyfill": "catalog:", "@logtape/file": "catalog:", "@logtape/logtape": "catalog:", - "@optique/config": "^0.10.0-dev.347", - "@optique/core": "^0.10.0-dev.347", - "@optique/run": "^0.10.0-dev.347", + "@optique/config": "0.10.0-dev.348", + "@optique/core": "0.10.0-dev.348", + "@optique/run": "0.10.0-dev.348", "@poppanator/http-constants": "^1.1.1", "byte-encodings": "catalog:", "chalk": "^5.6.2", @@ -87,20 +117,5 @@ "@types/node": "catalog:", "tsdown": "catalog:", "typescript": "catalog:" - }, - "scripts": { - "build:self": "tsdown", - "build": "pnpm --filter @fedify/cli... run build:self", - "prepack": "pnpm build", - "prepublish": "pnpm build", - "pretest": "pnpm build", - "test": "node --test --experimental-transform-types 'src/**/*.test.ts' '!src/init/test/**'", - "test-init": "deno task test-init", - "pretest:bun": "pnpm build", - "test:bun": "bun test", - "run": "pnpm build && node dist/mod.js", - "runi": "tsdown && node dist/mod.js", - "run:bun": "pnpm build && bun dist/mod.js", - "runi:bun": "tsdown && bun dist/mod.js" } } diff --git a/packages/cli/src/lookup.test.ts b/packages/cli/src/lookup.test.ts index 70708727e..13fd32688 100644 --- a/packages/cli/src/lookup.test.ts +++ b/packages/cli/src/lookup.test.ts @@ -1,8 +1,11 @@ import { Activity, Note } from "@fedify/vocab"; +import { clearActiveConfig, setActiveConfig } from "@optique/config"; +import { runWithConfig } from "@optique/config/run"; import { parse } from "@optique/core/parser"; import assert from "node:assert/strict"; import { mkdir, readFile, rm } from "node:fs/promises"; import test from "node:test"; +import { configContext } from "./config.ts"; import { getContextLoader } from "./docloader.ts"; import { authorizedFetchOption, @@ -183,17 +186,21 @@ test("clearTimeoutSignal - cleans up timer properly", async () => { assert.ok(!signal.aborted); }); -test("authorizedFetchOption - parses successfully without -a flag", () => { - const result = parse(authorizedFetchOption, []); - assert.ok(result.success); - if (result.success) { - assert.strictEqual(result.value.authorizedFetch, false); - // When authorizedFetch is false, firstKnock and tunnelService are not available - } +test("authorizedFetchOption - parses successfully without -a flag", async () => { + const result = await runWithConfig(authorizedFetchOption, configContext, { + load: () => ({}), + args: [], + }); + assert.strictEqual(result.authorizedFetch, false); + // When authorizedFetch is false, firstKnock and tunnelService still get defaults + assert.strictEqual(result.firstKnock, "draft-cavage-http-signatures-12"); + assert.strictEqual(result.tunnelService, "localhost.run"); }); test("authorizedFetchOption - parses successfully with -a flag", () => { + setActiveConfig(configContext.id, {}); const result = parse(authorizedFetchOption, ["-a"]); + clearActiveConfig(configContext.id); assert.ok(result.success); if (result.success) { assert.strictEqual(result.value.authorizedFetch, true); @@ -201,30 +208,34 @@ test("authorizedFetchOption - parses successfully with -a flag", () => { result.value.firstKnock, "draft-cavage-http-signatures-12", ); - assert.strictEqual(result.value.tunnelService, undefined); + assert.strictEqual(result.value.tunnelService, "localhost.run"); } }); test("authorizedFetchOption - parses with -a and --first-knock", () => { + setActiveConfig(configContext.id, {}); const result = parse(authorizedFetchOption, [ "-a", "--first-knock", "rfc9421", ]); + clearActiveConfig(configContext.id); assert.ok(result.success); if (result.success) { assert.strictEqual(result.value.authorizedFetch, true); assert.strictEqual(result.value.firstKnock, "rfc9421"); - assert.strictEqual(result.value.tunnelService, undefined); + assert.strictEqual(result.value.tunnelService, "localhost.run"); } }); test("authorizedFetchOption - parses with -a and --tunnel-service", () => { + setActiveConfig(configContext.id, {}); const result = parse(authorizedFetchOption, [ "-a", "--tunnel-service", - "localhost.run", + "serveo.net", ]); + clearActiveConfig(configContext.id); assert.ok(result.success); if (result.success) { assert.strictEqual(result.value.authorizedFetch, true); @@ -232,6 +243,6 @@ test("authorizedFetchOption - parses with -a and --tunnel-service", () => { result.value.firstKnock, "draft-cavage-http-signatures-12", ); - assert.strictEqual(result.value.tunnelService, "localhost.run"); + assert.strictEqual(result.value.tunnelService, "serveo.net"); } }); diff --git a/packages/cli/src/webfinger/mod.test.ts b/packages/cli/src/webfinger/mod.test.ts index 0f647f022..7465767bf 100644 --- a/packages/cli/src/webfinger/mod.test.ts +++ b/packages/cli/src/webfinger/mod.test.ts @@ -15,20 +15,23 @@ const ALIASES = [ "https://hollo.social/@fedify", ]; -test("Test webFingerCommand", () => { +test("Test webFingerCommand - resources only", () => { const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; - assert.deepEqual(parse(webFingerCommand, argsWithResourcesOnly), { - success: true, - value: { - debug: false, - command: COMMAND, - resources: RESOURCES, - allowPrivateAddresses: undefined, - maxRedirection: 5, - userAgent: undefined, - }, - }); + const result = parse(webFingerCommand, argsWithResourcesOnly); + assert.ok(result.success); + if (result.success) { + assert.strictEqual(result.value.debug, false); + assert.strictEqual(result.value.command, COMMAND); + assert.deepEqual(result.value.resources, RESOURCES); + assert.strictEqual(result.value.allowPrivateAddresses, false); + assert.strictEqual(result.value.maxRedirection, 0); + // userAgent has a dynamic default value from getUserAgent() + assert.ok(result.value.userAgent?.startsWith("Fedify/")); + } +}); +test("Test webFingerCommand - with all options", () => { + const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; const maxRedirection = 10; assert.deepEqual( parse(webFingerCommand, [ @@ -52,18 +55,29 @@ test("Test webFingerCommand", () => { }, }, ); +}); +test("Test webFingerCommand - wrong option", () => { + const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; const wrongOptionResult = parse(webFingerCommand, [ ...argsWithResourcesOnly, "-Q", ]); assert.ok(!wrongOptionResult.success); +}); - const wrongOptionValueResult = parse( +test("Test webFingerCommand - invalid option value falls back to default", () => { + const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; + // With bindConfig, invalid values fall back to the default instead of failing + const result = parse( webFingerCommand, [...argsWithResourcesOnly, "--max-redirection", "-10"], ); - assert.ok(!wrongOptionValueResult.success); + assert.ok(result.success); + if (result.success) { + // Falls back to default value of 0 + assert.strictEqual(result.value.maxRedirection, 0); + } }); // ---------------------------------------------------------------------- diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d4b66b25..e0b910d52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -781,14 +781,14 @@ importers: specifier: 'catalog:' version: 2.0.0 '@optique/config': - specifier: ^0.10.0-dev.347 - version: 0.10.0-dev.347(@standard-schema/spec@1.0.0) + specifier: 0.10.0-dev.348 + version: 0.10.0-dev.348(@standard-schema/spec@1.0.0) '@optique/core': - specifier: ^0.10.0-dev.347 - version: 0.10.0-dev.347 + specifier: 0.10.0-dev.348 + version: 0.10.0-dev.348 '@optique/run': - specifier: ^0.10.0-dev.347 - version: 0.10.0-dev.347 + specifier: 0.10.0-dev.348 + version: 0.10.0-dev.348 '@poppanator/http-constants': specifier: ^1.1.1 version: 1.1.1 @@ -3594,22 +3594,22 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@optique/config@0.10.0-dev.347': - resolution: {integrity: sha512-WBtkp22O/adD6bZpK2Izw5gw4eMBOwsVVo5duI51Cn0D58sqGXUuVtbGP3+uC79iQ2AfTzBwpiEqj/L8X08a2A==} + '@optique/config@0.10.0-dev.348': + resolution: {integrity: sha512-7zHBguVzRiost0cYK52FCnJgvzw0+Utyp/JuX5h4/yyfqApBmPrg6HuAy3cZOAYINudKDvrPYbVu/KxyT4hOBQ==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} peerDependencies: '@standard-schema/spec': ^1.1.0 - '@optique/core@0.10.0-dev.347': - resolution: {integrity: sha512-VVNLLT2AspoWCy3rp/XIi07bWWWgVBUgnU+kF86le9Qzs3m25DaCSTnmj7jZ+HAvOx5NDSzhL3UGYZbr8kt3Fw==} + '@optique/core@0.10.0-dev.348': + resolution: {integrity: sha512-SQCtkDc8/39Snfv+G7TCw55KsTjmIFH7O1/QS/tJRtEeFcIBQz8mOff4pNT6g06Z3q9aFZtS4ATzyCQHbSfDoQ==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@optique/core@0.9.2': resolution: {integrity: sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - '@optique/run@0.10.0-dev.347': - resolution: {integrity: sha512-rZ2GZ1zjzZkvR62/AVdWyLKOujgrOhk4eiFg2Bc9hpS1rg+4/ElMjOp3ULBc2tKuWgfjHLUyy197c5QZ+bm52g==} + '@optique/run@0.10.0-dev.348': + resolution: {integrity: sha512-qEbEz0UeaGcw6gQuIglWKFMtgpnq3VKEZRpRpd5LfZAsU7Fhl+fTVBOdXuKcympP1DCFSHVyEY4wNN2+Fnztiw==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@oxc-project/runtime@0.75.0': @@ -11150,18 +11150,18 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@optique/config@0.10.0-dev.347(@standard-schema/spec@1.0.0)': + '@optique/config@0.10.0-dev.348(@standard-schema/spec@1.0.0)': dependencies: '@optique/core': 0.9.2 '@standard-schema/spec': 1.0.0 - '@optique/core@0.10.0-dev.347': {} + '@optique/core@0.10.0-dev.348': {} '@optique/core@0.9.2': {} - '@optique/run@0.10.0-dev.347': + '@optique/run@0.10.0-dev.348': dependencies: - '@optique/core': 0.10.0-dev.347 + '@optique/core': 0.10.0-dev.348 '@oxc-project/runtime@0.75.0': {} @@ -13828,8 +13828,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13848,8 +13848,8 @@ snapshots: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.32.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.32.0(jiti@2.5.1)) @@ -13872,22 +13872,22 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 - eslint: 9.32.0(jiti@2.5.1) + eslint: 8.57.1 get-tsconfig: 4.10.1 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1 @@ -13898,22 +13898,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.1 - eslint: 8.57.1 - get-tsconfig: 4.10.1 - is-bun-module: 2.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 - optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -13928,25 +13913,25 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3) eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.32.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -13979,7 +13964,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -13990,7 +13975,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -14008,7 +13993,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -14019,7 +14004,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.32.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)))(eslint@9.32.0(jiti@2.5.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.32.0(jiti@2.5.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.32.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 From aa6b64f98a7781fed5a4d79433e1bd6feede208b Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Wed, 11 Feb 2026 17:41:04 +0900 Subject: [PATCH 21/35] Fix noFavicon config logic and update changelog command list The noFavicon option was incorrectly reading showFavicon from config. When showFavicon was true, noFavicon would also be true, which is inverted. Changed to use strict equality check (=== false) so noFavicon is only true when showFavicon is explicitly set to false. Also updated CHANGES.md to include inbox and nodeinfo in the list of commands with configuration support. Additionally simplified some bindConfig key functions: - Removed redundant type assertion in lookup.ts firstKnock - Removed redundant nullish coalescing in determineSpec - Changed `as number` to `?? default` for port and maxRedirection Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/lookup.ts | 7 ++----- packages/cli/src/nodeinfo.ts | 2 +- packages/cli/src/relay.ts | 2 +- packages/cli/src/webfinger/command.ts | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 823379ee9..192b2a777 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -80,10 +80,7 @@ export const authorizedFetchOption = object({ { context: configContext, key: (config) => - (config.lookup?.firstKnock ?? - "draft-cavage-http-signatures-12") as - | "draft-cavage-http-signatures-12" - | "rfc9421", + config.lookup?.firstKnock ?? "draft-cavage-http-signatures-12", default: "draft-cavage-http-signatures-12" as const, }, ), @@ -412,7 +409,7 @@ export async function runLookup(command: InferValue) { { specDeterminer: { determineSpec() { - return command.firstKnock ?? "draft-cavage-http-signatures-12"; + return command.firstKnock; }, rememberSpec() { }, diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index bc20f7ca2..208827411 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -62,7 +62,7 @@ const nodeInfoOption = object({ }), { context: configContext, - key: (config) => config.nodeinfo?.showFavicon ?? false, + key: (config) => config.nodeinfo?.showFavicon === false, default: false, }, ), diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index cfad99dcb..e609f5b28 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -79,7 +79,7 @@ export const relayCommand = command( ), { context: configContext, - key: (config) => config.relay?.port as number, + key: (config) => config.relay?.port ?? 8000, default: 8000, }, ), diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index f702677bb..496060f47 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -35,7 +35,7 @@ const maxRedirection = bindConfig( ), { context: configContext, - key: (config) => config.webfinger?.maxRedirection as number, + key: (config) => config.webfinger?.maxRedirection ?? 0, default: 0, }, ); From 89338f7360c4d98bce29e6681a1e92e0573b2208 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 12 Feb 2026 00:58:27 +0900 Subject: [PATCH 22/35] Set webfinger command's default value to 5 and test codes --- packages/cli/src/webfinger/command.ts | 4 ++-- packages/cli/src/webfinger/mod.test.ts | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index 496060f47..c0516791d 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -35,8 +35,8 @@ const maxRedirection = bindConfig( ), { context: configContext, - key: (config) => config.webfinger?.maxRedirection ?? 0, - default: 0, + key: (config) => config.webfinger?.maxRedirection ?? 5, + default: 5, }, ); diff --git a/packages/cli/src/webfinger/mod.test.ts b/packages/cli/src/webfinger/mod.test.ts index 7465767bf..f38997a9e 100644 --- a/packages/cli/src/webfinger/mod.test.ts +++ b/packages/cli/src/webfinger/mod.test.ts @@ -1,6 +1,8 @@ +import { clearActiveConfig, setActiveConfig } from "@optique/config"; import { parse } from "@optique/core/parser"; import assert from "node:assert/strict"; import test from "node:test"; +import { configContext } from "../config.ts"; import { lookupSingleWebFinger } from "./action.ts"; import { webFingerCommand } from "./command.ts"; @@ -15,16 +17,19 @@ const ALIASES = [ "https://hollo.social/@fedify", ]; -test("Test webFingerCommand - resources only", () => { +test("Test webFingerCommand - resources only", async () => { const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; - const result = parse(webFingerCommand, argsWithResourcesOnly); + setActiveConfig(configContext.id, {}); + const result = await parse(webFingerCommand, argsWithResourcesOnly); + clearActiveConfig(configContext.id); + assert.ok(result.success); if (result.success) { assert.strictEqual(result.value.debug, false); assert.strictEqual(result.value.command, COMMAND); assert.deepEqual(result.value.resources, RESOURCES); assert.strictEqual(result.value.allowPrivateAddresses, false); - assert.strictEqual(result.value.maxRedirection, 0); + assert.strictEqual(result.value.maxRedirection, 5); // userAgent has a dynamic default value from getUserAgent() assert.ok(result.value.userAgent?.startsWith("Fedify/")); } @@ -66,17 +71,20 @@ test("Test webFingerCommand - wrong option", () => { assert.ok(!wrongOptionResult.success); }); -test("Test webFingerCommand - invalid option value falls back to default", () => { +test("Test webFingerCommand - invalid option value falls back to default", async () => { const argsWithResourcesOnly = [COMMAND, ...RESOURCES]; // With bindConfig, invalid values fall back to the default instead of failing - const result = parse( + setActiveConfig(configContext.id, {}); + const result = await parse( webFingerCommand, [...argsWithResourcesOnly, "--max-redirection", "-10"], ); + clearActiveConfig(configContext.id); + assert.ok(result.success); if (result.success) { // Falls back to default value of 0 - assert.strictEqual(result.value.maxRedirection, 0); + assert.strictEqual(result.value.maxRedirection, 5); } }); From 270ecb0f96fa6aa70f1eae69ccbb9f5b1f3f77be Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 12 Feb 2026 18:13:22 +0900 Subject: [PATCH 23/35] Fix package versions to 2.0.0 --- deno.lock | 25 +++++++++++++++---------- packages/elysia/deno.json | 2 +- packages/fixture/deno.json | 2 +- packages/fresh/deno.json | 2 +- packages/lint/deno.json | 2 +- packages/lint/package.json | 2 +- packages/relay/deno.json | 2 +- packages/relay/package.json | 2 +- packages/vocab-runtime/deno.json | 2 +- packages/vocab-runtime/package.json | 2 +- packages/vocab-tools/deno.json | 2 +- packages/vocab-tools/package.json | 2 +- packages/vocab/deno.json | 2 +- packages/vocab/package.json | 2 +- packages/webfinger/deno.json | 2 +- packages/webfinger/package.json | 2 +- 16 files changed, 30 insertions(+), 25 deletions(-) diff --git a/deno.lock b/deno.lock index f482b0e7c..c4fc958e3 100644 --- a/deno.lock +++ b/deno.lock @@ -76,9 +76,10 @@ "npm:@multiformats/base-x@^4.0.1": "4.0.1", "npm:@nestjs/common@^11.0.1": "11.1.13_reflect-metadata@0.2.2_rxjs@7.8.2", "npm:@opentelemetry/api@^1.9.0": "1.9.0", - "npm:@opentelemetry/core@2": "2.5.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/sdk-trace-base@2": "2.5.0_@opentelemetry+api@1.9.0", - "npm:@opentelemetry/semantic-conventions@^1.27.0": "1.39.0", + "npm:@opentelemetry/context-async-hooks@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/core@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", + "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", "npm:@optique/config@0.10.0-dev.348": "0.10.0-dev.348_@standard-schema+spec@1.1.0", "npm:@optique/core@0.10.0-dev.348": "0.10.0-dev.348", "npm:@optique/run@0.10.0-dev.348": "0.10.0-dev.348", @@ -2030,6 +2031,12 @@ "@opentelemetry/api@1.9.0": { "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==" }, + "@opentelemetry/context-async-hooks@2.5.0_@opentelemetry+api@1.9.0": { + "integrity": "sha512-uOXpVX0ZjO7heSVjhheW2XEPrhQAWr2BScDPoZ9UDycl5iuHG+Usyc3AIfG6kZeC1GyLpMInpQ6X5+9n69yOFw==", + "dependencies": [ + "@opentelemetry/api" + ] + }, "@opentelemetry/core@2.5.0_@opentelemetry+api@1.9.0": { "integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==", "dependencies": [ @@ -5877,6 +5884,7 @@ "workspace": { "dependencies": [ "jsr:@david/dax@~0.43.2", + "jsr:@hono/hono@^4.8.3", "jsr:@logtape/file@2", "jsr:@logtape/logtape@2", "jsr:@std/assert@^1.0.13", @@ -5891,8 +5899,10 @@ "npm:@js-temporal/polyfill@~0.5.1", "npm:@nestjs/common@^11.0.1", "npm:@opentelemetry/api@^1.9.0", - "npm:@opentelemetry/core@2", - "npm:@opentelemetry/sdk-trace-base@2", + "npm:@opentelemetry/context-async-hooks@^2.5.0", + "npm:@opentelemetry/core@^2.5.0", + "npm:@opentelemetry/sdk-trace-base@^2.5.0", + "npm:@opentelemetry/semantic-conventions@^1.39.0", "npm:@types/node@^22.16.0", "npm:amqplib@~0.10.9", "npm:byte-encodings@^1.0.11", @@ -6015,9 +6025,6 @@ "jsr:@std/assert@0.226", "jsr:@std/url@~0.225.1", "npm:@multiformats/base-x@^4.0.1", - "npm:@opentelemetry/core@2", - "npm:@opentelemetry/sdk-trace-base@2", - "npm:@opentelemetry/semantic-conventions@^1.27.0", "npm:asn1js@^3.0.7", "npm:fast-check@^3.22.0", "npm:fetch-mock@^12.5.2", @@ -6032,7 +6039,6 @@ "packageJson": { "dependencies": [ "npm:@js-temporal/polyfill@~0.5.1", - "npm:@opentelemetry/semantic-conventions@^1.27.0", "npm:@types/node@^24.2.1", "npm:json-canon@^1.0.1", "npm:jsonld@9", @@ -6096,7 +6102,6 @@ }, "packages/vocab": { "dependencies": [ - "npm:@opentelemetry/api@^1.9.0", "npm:fast-check@^3.22.0", "npm:fetch-mock@^12.5.2", "npm:jsonld@9" diff --git a/packages/elysia/deno.json b/packages/elysia/deno.json index 27740031c..d436ea4d6 100644 --- a/packages/elysia/deno.json +++ b/packages/elysia/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/elysia", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/index.ts" diff --git a/packages/fixture/deno.json b/packages/fixture/deno.json index 9706e81ce..6d73f0889 100644 --- a/packages/fixture/deno.json +++ b/packages/fixture/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/fixture", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/fresh/deno.json b/packages/fresh/deno.json index 15904431b..388e0531c 100644 --- a/packages/fresh/deno.json +++ b/packages/fresh/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/fresh", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "imports": { "@fresh/core": "jsr:@fresh/core@^2.1.4", diff --git a/packages/lint/deno.json b/packages/lint/deno.json index b1688d33f..75a4676ec 100644 --- a/packages/lint/deno.json +++ b/packages/lint/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/lint", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/lint/package.json b/packages/lint/package.json index 5ccccc8f4..8667bbdd4 100644 --- a/packages/lint/package.json +++ b/packages/lint/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/lint", - "version": "1.10.3", + "version": "2.0.0", "description": "Fedify linting rules and plugins", "keywords": [ "Fedify", diff --git a/packages/relay/deno.json b/packages/relay/deno.json index 62d453199..f6ccdccf1 100644 --- a/packages/relay/deno.json +++ b/packages/relay/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/relay", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "imports": { "@std/assert": "jsr:@std/assert@^1.0.13" diff --git a/packages/relay/package.json b/packages/relay/package.json index 9b008ccf7..82daa7a91 100644 --- a/packages/relay/package.json +++ b/packages/relay/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/relay", - "version": "1.10.3", + "version": "2.0.0", "description": "ActivityPub relay support for Fedify", "keywords": [ "Fedify", diff --git a/packages/vocab-runtime/deno.json b/packages/vocab-runtime/deno.json index 6a6b53a43..1ff551ff5 100644 --- a/packages/vocab-runtime/deno.json +++ b/packages/vocab-runtime/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-runtime", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/vocab-runtime/package.json b/packages/vocab-runtime/package.json index b0ab86824..665cc3642 100644 --- a/packages/vocab-runtime/package.json +++ b/packages/vocab-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-runtime", - "version": "1.10.3", + "version": "2.0.0", "homepage": "https://fedify.dev/", "repository": { "type": "git", diff --git a/packages/vocab-tools/deno.json b/packages/vocab-tools/deno.json index 7540d49f4..fddebbd3a 100644 --- a/packages/vocab-tools/deno.json +++ b/packages/vocab-tools/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-tools", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/vocab-tools/package.json b/packages/vocab-tools/package.json index ae546fe84..73e496d14 100644 --- a/packages/vocab-tools/package.json +++ b/packages/vocab-tools/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab-tools", - "version": "1.10.3", + "version": "2.0.0", "description": "Code generator for Activity Vocabulary APIs", "homepage": "https://fedify.dev/", "repository": { diff --git a/packages/vocab/deno.json b/packages/vocab/deno.json index 3c376e346..fc8c54fbe 100644 --- a/packages/vocab/deno.json +++ b/packages/vocab/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/vocab/package.json b/packages/vocab/package.json index 9aeb90640..20842be63 100644 --- a/packages/vocab/package.json +++ b/packages/vocab/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/vocab", - "version": "1.10.3", + "version": "2.0.0", "homepage": "https://fedify.dev/", "repository": { "type": "git", diff --git a/packages/webfinger/deno.json b/packages/webfinger/deno.json index 1b140179f..a67c9a5e2 100644 --- a/packages/webfinger/deno.json +++ b/packages/webfinger/deno.json @@ -1,6 +1,6 @@ { "name": "@fedify/webfinger", - "version": "1.10.3", + "version": "2.0.0", "license": "MIT", "exports": { ".": "./src/mod.ts" diff --git a/packages/webfinger/package.json b/packages/webfinger/package.json index 6959d85c8..443b357a5 100644 --- a/packages/webfinger/package.json +++ b/packages/webfinger/package.json @@ -1,6 +1,6 @@ { "name": "@fedify/webfinger", - "version": "1.10.3", + "version": "2.0.0", "homepage": "https://fedify.dev/", "repository": { "type": "git", From faae49b4eaadac79b3cc7f7dd534b69b82c18e98 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 12 Feb 2026 20:32:39 +0900 Subject: [PATCH 24/35] Update optique version to dev.355 --- deno.lock | 60 +++++++++++++++++++-------------------- packages/cli/deno.json | 7 ++--- packages/cli/package.json | 6 ++-- pnpm-lock.yaml | 40 +++++++++++--------------- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/deno.lock b/deno.lock index c4fc958e3..e21d4a5c2 100644 --- a/deno.lock +++ b/deno.lock @@ -16,14 +16,14 @@ "jsr:@fresh/plugin-vite@^1.0.7": "1.0.8", "jsr:@hongminhee/localtunnel@0.3": "0.3.0", "jsr:@hono/hono@^4.7.1": "4.11.4", - "jsr:@hono/hono@^4.8.3": "4.11.4", + "jsr:@hono/hono@^4.8.3": "4.11.9", "jsr:@logtape/file@2": "2.0.2", "jsr:@logtape/logtape@2": "2.0.2", "jsr:@logtape/logtape@^1.0.4": "1.3.7", "jsr:@logtape/logtape@^2.0.2": "2.0.2", - "jsr:@optique/config@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", - "jsr:@optique/core@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", - "jsr:@optique/run@~0.10.0-dev.348": "0.10.0-dev.348+3a6d010a", + "jsr:@optique/config@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", + "jsr:@optique/core@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", + "jsr:@optique/run@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", "jsr:@std/assert@0.224": "0.224.0", "jsr:@std/assert@0.226": "0.226.0", "jsr:@std/assert@^1.0.13": "1.0.18", @@ -80,9 +80,9 @@ "npm:@opentelemetry/core@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", - "npm:@optique/config@0.10.0-dev.348": "0.10.0-dev.348_@standard-schema+spec@1.1.0", - "npm:@optique/core@0.10.0-dev.348": "0.10.0-dev.348", - "npm:@optique/run@0.10.0-dev.348": "0.10.0-dev.348", + "npm:@optique/config@0.10.0-dev.355": "0.10.0-dev.355_@standard-schema+spec@1.1.0", + "npm:@optique/core@0.10.0-dev.355": "0.10.0-dev.355", + "npm:@optique/run@0.10.0-dev.355": "0.10.0-dev.355", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", "npm:@preact/signals@^2.2.1": "2.7.1_preact@10.19.6", "npm:@preact/signals@^2.3.2": "2.7.1_preact@10.19.6", @@ -259,6 +259,9 @@ "@hono/hono@4.11.4": { "integrity": "aaf7b9d5a6b2422b0778c091b712ee1f018bc7e82138067d21eb27d7c2e1f5be" }, + "@hono/hono@4.11.9": { + "integrity": "c82c6b846abc3c1879d921d8365287d77cdef8073019f509ff80bf53033bdcba" + }, "@logtape/file@2.0.2": { "integrity": "a912459fe0d27213e05c95e6fadf716000f27eafa27e67c2737820ba24097fdc", "dependencies": [ @@ -278,8 +281,8 @@ "@logtape/logtape@2.0.2": { "integrity": "546fcd514e66f2b841c6f261fa3a3d905b52d876dc1bba8ffe1a087d9275c4c9" }, - "@optique/config@0.10.0-dev.348+3a6d010a": { - "integrity": "5bb164e52625179cf012a129ee19d4d1ec3cabde07fe9faa055e1af3ddca8519", + "@optique/config@0.10.0-dev.355+7475e7e5": { + "integrity": "10fd42374ae3d558d3bfc1a0db4b665932fbdb3b64ee2b4e9023af45585f5af9", "dependencies": [ "npm:@standard-schema/spec" ] @@ -287,11 +290,11 @@ "@optique/core@0.10.0-dev.333+076fceae": { "integrity": "1ebe1782740f08d568ae0c5258786933a8502d1e137feb49b2d8ab06d204b11a" }, - "@optique/core@0.10.0-dev.348+3a6d010a": { - "integrity": "5ab1e09d13c3a6b7e28a8a110f170e03d25ae064fe7d6aee5d346bb5cc0878cf" + "@optique/core@0.10.0-dev.355+7475e7e5": { + "integrity": "e1ee54f3861b8d85f30fd11bfedaf739822d509c62a6f52b769456f1b430bd23" }, - "@optique/run@0.10.0-dev.348+3a6d010a": { - "integrity": "56c797164fed0576b28262cdc2b7152084b6b40b9c1d6bfa83c7762a44829901" + "@optique/run@0.10.0-dev.355+7475e7e5": { + "integrity": "896094666b885925b4816447bea884c5a2e6f872928fe3462d7af33497aa30fa" }, "@std/assert@0.224.0": { "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", @@ -2064,23 +2067,20 @@ "@opentelemetry/semantic-conventions@1.39.0": { "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==" }, - "@optique/config@0.10.0-dev.348_@standard-schema+spec@1.1.0": { - "integrity": "sha512-7zHBguVzRiost0cYK52FCnJgvzw0+Utyp/JuX5h4/yyfqApBmPrg6HuAy3cZOAYINudKDvrPYbVu/KxyT4hOBQ==", + "@optique/config@0.10.0-dev.355_@standard-schema+spec@1.1.0": { + "integrity": "sha512-BJmZ/iC/TLCVnXXQGRUG6t7MA+Zilg6Sdm2dkaJAghSxFrgBEgdTikwi+stVR2DulC3+GWUxg5NDP6/ruB0K3g==", "dependencies": [ - "@optique/core@0.9.2", + "@optique/core", "@standard-schema/spec" ] }, - "@optique/core@0.10.0-dev.348": { - "integrity": "sha512-SQCtkDc8/39Snfv+G7TCw55KsTjmIFH7O1/QS/tJRtEeFcIBQz8mOff4pNT6g06Z3q9aFZtS4ATzyCQHbSfDoQ==" - }, - "@optique/core@0.9.2": { - "integrity": "sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==" + "@optique/core@0.10.0-dev.355": { + "integrity": "sha512-VlHNHbeUxby3SDOQdCrc99TldReB15wgK1UoxgriAbprxgXz1Lt3iyAjK88I8Z5Rc5AnMqVPaE+xHJXTTAbgxQ==" }, - "@optique/run@0.10.0-dev.348": { - "integrity": "sha512-qEbEz0UeaGcw6gQuIglWKFMtgpnq3VKEZRpRpd5LfZAsU7Fhl+fTVBOdXuKcympP1DCFSHVyEY4wNN2+Fnztiw==", + "@optique/run@0.10.0-dev.355": { + "integrity": "sha512-NSFK/hG3C09QpxV7Ufv3INXP1Xj1OtTJ4+A+PcCwKewYmfzj7EfPswaaBHxogJpNUwHvkKgwkafkLOR+ClShvw==", "dependencies": [ - "@optique/core@0.10.0-dev.348" + "@optique/core" ] }, "@oxc-project/types@0.103.0": { @@ -5955,9 +5955,9 @@ "dependencies": [ "jsr:@hongminhee/localtunnel@0.3", "jsr:@hono/hono@^4.8.3", - "jsr:@optique/config@~0.10.0-dev.348", - "jsr:@optique/core@~0.10.0-dev.348", - "jsr:@optique/run@~0.10.0-dev.348", + "jsr:@optique/config@~0.10.0-dev.355", + "jsr:@optique/core@~0.10.0-dev.355", + "jsr:@optique/run@~0.10.0-dev.355", "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", @@ -5981,9 +5981,9 @@ "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", - "npm:@optique/config@0.10.0-dev.348", - "npm:@optique/core@0.10.0-dev.348", - "npm:@optique/run@0.10.0-dev.348", + "npm:@optique/config@0.10.0-dev.355", + "npm:@optique/core@0.10.0-dev.355", + "npm:@optique/run@0.10.0-dev.355", "npm:@poppanator/http-constants@^1.1.1", "npm:chalk@^5.6.2", "npm:cli-highlight@^2.1.11", diff --git a/packages/cli/deno.json b/packages/cli/deno.json index b8f52e01f..cc54d809d 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -8,10 +8,9 @@ "@inquirer/prompts": "npm:@inquirer/prompts@^7.8.4", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", - "@optique/config": "jsr:@optique/config@^0.10.0-dev.348", - "@optique/config/run": "jsr:@optique/config@^0.10.0-dev.348/run", - "@optique/core": "jsr:@optique/core@^0.10.0-dev.348", - "@optique/run": "jsr:@optique/run@^0.10.0-dev.348", + "@optique/config": "jsr:@optique/config@^0.10.0-dev.355", + "@optique/core": "jsr:@optique/core@^0.10.0-dev.355", + "@optique/run": "jsr:@optique/run@^0.10.0-dev.355", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index 3396350b0..bfaa786de 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -89,9 +89,9 @@ "@js-temporal/polyfill": "catalog:", "@logtape/file": "catalog:", "@logtape/logtape": "catalog:", - "@optique/config": "0.10.0-dev.348", - "@optique/core": "0.10.0-dev.348", - "@optique/run": "0.10.0-dev.348", + "@optique/config": "0.10.0-dev.355", + "@optique/core": "0.10.0-dev.355", + "@optique/run": "0.10.0-dev.355", "@poppanator/http-constants": "^1.1.1", "byte-encodings": "catalog:", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0b910d52..54bfa5c57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -781,14 +781,14 @@ importers: specifier: 'catalog:' version: 2.0.0 '@optique/config': - specifier: 0.10.0-dev.348 - version: 0.10.0-dev.348(@standard-schema/spec@1.0.0) + specifier: 0.10.0-dev.355 + version: 0.10.0-dev.355(@standard-schema/spec@1.0.0) '@optique/core': - specifier: 0.10.0-dev.348 - version: 0.10.0-dev.348 + specifier: 0.10.0-dev.355 + version: 0.10.0-dev.355 '@optique/run': - specifier: 0.10.0-dev.348 - version: 0.10.0-dev.348 + specifier: 0.10.0-dev.355 + version: 0.10.0-dev.355 '@poppanator/http-constants': specifier: ^1.1.1 version: 1.1.1 @@ -3594,22 +3594,18 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@optique/config@0.10.0-dev.348': - resolution: {integrity: sha512-7zHBguVzRiost0cYK52FCnJgvzw0+Utyp/JuX5h4/yyfqApBmPrg6HuAy3cZOAYINudKDvrPYbVu/KxyT4hOBQ==} + '@optique/config@0.10.0-dev.355': + resolution: {integrity: sha512-BJmZ/iC/TLCVnXXQGRUG6t7MA+Zilg6Sdm2dkaJAghSxFrgBEgdTikwi+stVR2DulC3+GWUxg5NDP6/ruB0K3g==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} peerDependencies: '@standard-schema/spec': ^1.1.0 - '@optique/core@0.10.0-dev.348': - resolution: {integrity: sha512-SQCtkDc8/39Snfv+G7TCw55KsTjmIFH7O1/QS/tJRtEeFcIBQz8mOff4pNT6g06Z3q9aFZtS4ATzyCQHbSfDoQ==} + '@optique/core@0.10.0-dev.355': + resolution: {integrity: sha512-VlHNHbeUxby3SDOQdCrc99TldReB15wgK1UoxgriAbprxgXz1Lt3iyAjK88I8Z5Rc5AnMqVPaE+xHJXTTAbgxQ==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - '@optique/core@0.9.2': - resolution: {integrity: sha512-UpDMdV1hdHF1qZJVZKsQpLOnQMajwjBny+DBjP+yyH95fBqJQPnUGrhARn6R/REPnchoxQWjwPRhSjTHnS4rPA==} - engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - - '@optique/run@0.10.0-dev.348': - resolution: {integrity: sha512-qEbEz0UeaGcw6gQuIglWKFMtgpnq3VKEZRpRpd5LfZAsU7Fhl+fTVBOdXuKcympP1DCFSHVyEY4wNN2+Fnztiw==} + '@optique/run@0.10.0-dev.355': + resolution: {integrity: sha512-NSFK/hG3C09QpxV7Ufv3INXP1Xj1OtTJ4+A+PcCwKewYmfzj7EfPswaaBHxogJpNUwHvkKgwkafkLOR+ClShvw==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@oxc-project/runtime@0.75.0': @@ -11150,18 +11146,16 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@optique/config@0.10.0-dev.348(@standard-schema/spec@1.0.0)': + '@optique/config@0.10.0-dev.355(@standard-schema/spec@1.0.0)': dependencies: - '@optique/core': 0.9.2 + '@optique/core': 0.10.0-dev.355 '@standard-schema/spec': 1.0.0 - '@optique/core@0.10.0-dev.348': {} - - '@optique/core@0.9.2': {} + '@optique/core@0.10.0-dev.355': {} - '@optique/run@0.10.0-dev.348': + '@optique/run@0.10.0-dev.355': dependencies: - '@optique/core': 0.10.0-dev.348 + '@optique/core': 0.10.0-dev.355 '@oxc-project/runtime@0.75.0': {} From 1f4ee9f737af4580f912247e85fd199b0e282eec Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 12 Feb 2026 21:27:25 +0900 Subject: [PATCH 25/35] Fix unclosed tag in cli.md --- docs/cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli.md b/docs/cli.md index ac09ca544..ccdbcd45d 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -118,7 +118,7 @@ Configuration files are loaded from the following locations in order, with later files taking precedence over earlier ones: 1. `/etc/fedify/config.toml` (system-wide) -2. */fedify/config.toml* (user-level) +2. *<user-config-dir>/fedify/config.toml* (user-level) 3. `.fedify.toml` in the current working directory (project-level) 4. Custom path via `--config` option (explicit) From 6e6644849e380051be6c9e45a86b3c70e1eb72b3 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Thu, 12 Feb 2026 23:15:55 +0900 Subject: [PATCH 26/35] Add change log --- CHANGES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 08f56245a..bd85bc9a7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -222,6 +222,15 @@ To be released. to the existing `-s`/`--service` option in `fedify tunnel` for consistency. [[#525], [#529], [#531] by Jiwon Kwon] + - Added configuration file support for CLI commands. The CLI now loads + settings from *.fedify.toml* in the current directory. + [[#555], [#566] by Jiwon Kwon] + + - Added `--config` option to specify a custom configuration file path. + - Added `--ignore-config` option to skip configuration file loading. + - All command options (`inbox`, `lookup`, `webfinger`, `nodeinfo`, + `tunnel`, `relay`) can now be configured via the configuration file. + [Elysia]: https://elysiajs.com/ [#374]: https://github.com/fedify-dev/fedify/issues/374 [#397]: https://github.com/fedify-dev/fedify/issues/397 @@ -238,6 +247,8 @@ To be released. [#525]: https://github.com/fedify-dev/fedify/issues/525 [#529]: https://github.com/fedify-dev/fedify/pull/529 [#531]: https://github.com/fedify-dev/fedify/pull/531 +[#555]: https://github.com/fedify-dev/fedify/issues/555 +[#566]: https://github.com/fedify-dev/fedify/pull/566 ### @fedify/debugger From 26d63b9681bd09f88b8be00b06ae51f384cf4138 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 01:09:10 +0900 Subject: [PATCH 27/35] Address PR review feedback for CLI configuration feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolved issues raised by reviewers: - Improved error handling in tryLoadToml() to print warnings for parsing errors instead of silently ignoring all errors (only ENOENT is silent) - Fixed package.json files array to include dist/ instead of non-existent src/*.mjs files - Fixed typo in engines field: denp → deno - Fixed relay.ts persistent option to wrap optional() outside bindConfig() so config file fallback works correctly - Removed unused logFile from config schema - Updated CHANGES.md to document full config precedence chain Co-Authored-By: Claude Opus 4.5 --- CHANGES.md | 18 +++++++++++++----- packages/cli/package.json | 6 ++---- packages/cli/src/config.ts | 19 ++++++++++++++----- packages/cli/src/relay.ts | 12 ++++++------ 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bd85bc9a7..a69b8196b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -223,13 +223,21 @@ To be released. [[#525], [#529], [#531] by Jiwon Kwon] - Added configuration file support for CLI commands. The CLI now loads - settings from *.fedify.toml* in the current directory. - [[#555], [#566] by Jiwon Kwon] - - - Added `--config` option to specify a custom configuration file path. + settings from configuration files at multiple levels, with a well-defined + precedence chain. [[#555], [#566] by Jiwon Kwon] + + - By default, configuration is loaded (in order of increasing precedence) + from a system-wide configuration file (*/etc/fedify/config.toml*), + a user-level configuration file (*~/.config/fedify/config.toml*), + and *.fedify.toml* in the current directory; later files override + earlier ones. + - Added `--config` option to specify a custom configuration file path; + this file has the highest precedence over all other configuration + sources. - Added `--ignore-config` option to skip configuration file loading. - All command options (`inbox`, `lookup`, `webfinger`, `nodeinfo`, - `tunnel`, `relay`) can now be configured via the configuration file. + `tunnel`, `relay`) can now be configured via any of the configuration + files. [Elysia]: https://elysiajs.com/ [#374]: https://github.com/fedify-dev/fedify/issues/374 diff --git a/packages/cli/package.json b/packages/cli/package.json index bfaa786de..30ffed499 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -4,9 +4,7 @@ "type": "module", "files": [ "README.md", - "package.json", - "src/install.mjs", - "src/run.mjs" + "dist/" ], "bin": { "fedify": "./dist/mod.js" @@ -29,7 +27,7 @@ "engines": { "node": ">=20.0.0", "bun": ">=1.2.0", - "denp": ">=2.0.0" + "deno": ">=2.0.0" }, "os": [ "darwin", diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts index a44ca5705..dbdb4057a 100644 --- a/packages/cli/src/config.ts +++ b/packages/cli/src/config.ts @@ -1,4 +1,6 @@ import { createConfigContext } from "@optique/config"; +import { message } from "@optique/core"; +import { printError } from "@optique/run"; import { readFileSync } from "node:fs"; import { parse as parseToml } from "smol-toml"; import { @@ -77,7 +79,6 @@ export const configSchema = object({ // Global settings debug: optional(boolean()), userAgent: optional(string()), - logFile: optional(string()), tunnelService: optional( picklist(["localhost.run", "serveo.net", "pinggy.io"]), ), @@ -102,12 +103,20 @@ export const configContext = createConfigContext({ schema: configSchema }); /** * Try to load and parse a TOML config file. - * Returns an empty object if the file doesn't exist or fails to parse. + * Returns an empty object if the file doesn't exist. + * Logs a warning and returns empty object for other errors (parsing, permissions). */ -export function tryLoadToml(path: string): Record { +export function tryLoadToml(filePath: string): Record { try { - return parseToml(readFileSync(path, "utf-8")); - } catch { + return parseToml(readFileSync(filePath, "utf-8")); + } catch (error) { + if (error instanceof Error && "code" in error && error.code === "ENOENT") { + return {}; // File not found, which is fine. + } + // For other errors (e.g., parsing, permissions), warn the user. + printError( + message`Could not load or parse config file at ${filePath}. It will be ignored.`, + ); return {}; } } diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index e609f5b28..bf8daf19c 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -56,17 +56,17 @@ export const relayCommand = command( default: "mastodon", }, ), - persistent: bindConfig( - optional( + persistent: optional( + bindConfig( option("--persistent", string({ metavar: "PATH" }), { description: message`Path to SQLite database file for persistent storage. If not specified, uses in-memory storage which is lost when the server stops.`, }), + { + context: configContext, + key: (config) => config.relay?.persistent, + }, ), - { - context: configContext, - key: (config) => config.relay?.persistent, - }, ), port: bindConfig( option( From f474b83672c33f70511ca482e70a549304650c60 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 02:48:21 +0900 Subject: [PATCH 28/35] Show user-friendly error for invalid --config file Instead of showing a raw stack trace when the file specified with --config is missing or malformed, display a clean error message using printError and exit gracefully. Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/mod.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index 6505d7d97..72ee4a252 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -1,6 +1,7 @@ #!/usr/bin/env node import { runWithConfig } from "@optique/config/run"; -import { merge, or } from "@optique/core"; +import { merge, message, or } from "@optique/core"; +import { printError } from "@optique/run"; import envPaths from "env-paths"; import { merge as deepMerge } from "es-toolkit"; import { readFileSync } from "node:fs"; @@ -46,10 +47,20 @@ async function main() { const user = tryLoadToml(join(userConfigDir, "config.toml")); const project = tryLoadToml(join(process.cwd(), ".fedify.toml")); - // Custom config via --config throws on error (required file) - const custom = parsed.configPath - ? parseToml(readFileSync(parsed.configPath, "utf-8")) - : {}; + // Custom config via --config exits with error if file is missing or invalid + let custom: Record = {}; + if (parsed.configPath) { + try { + custom = parseToml(readFileSync(parsed.configPath, "utf-8")); + } catch (error) { + printError( + message`Could not load config file at ${parsed.configPath}: ${ + error instanceof Error ? error.message : String(error) + }`, + ); + process.exit(1); + } + } return [system, user, project, custom].reduce( (acc, config) => deepMerge(acc, config), From 4db07072949b88da03ef9f3b7589f888b0532034 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 03:25:12 +0900 Subject: [PATCH 29/35] Fix lookup command option parsing issues The lookup command was broken due to incorrect Optique combinator usage: - Changed suppressErrors from option() to flag() since it takes no value - Changed format flags (-r, -C, -e) from option() to flag() - Wrapped format or() in optional() so bindConfig can provide default when no format flag is specified - Wrapped timeout bindConfig() in optional() since it has no default Co-Authored-By: Claude Opus 4.5 --- packages/cli/src/lookup.ts | 63 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 192b2a777..1613642ab 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -100,7 +100,7 @@ const traverseOption = object({ }, ), suppressErrors: bindConfig( - option("-S", "--suppress-errors", { + flag("-S", "--suppress-errors", { description: message`Suppress partial errors while traversing the collection.`, }), @@ -129,24 +129,26 @@ export const lookupCommand = command( { min: 1 }, ), format: bindConfig( - or( - map( - option("-r", "--raw", { - description: message`Print the fetched JSON-LD document as is.`, - }), - () => "raw" as const, - ), - map( - option("-C", "--compact", { - description: message`Compact the fetched JSON-LD document.`, - }), - () => "compact" as const, - ), - map( - option("-e", "--expand", { - description: message`Expand the fetched JSON-LD document.`, - }), - () => "expand" as const, + optional( + or( + map( + flag("-r", "--raw", { + description: message`Print the fetched JSON-LD document as is.`, + }), + () => "raw" as const, + ), + map( + flag("-C", "--compact", { + description: message`Compact the fetched JSON-LD document.`, + }), + () => "compact" as const, + ), + map( + flag("-e", "--expand", { + description: message`Expand the fetched JSON-LD document.`, + }), + () => "expand" as const, + ), ), ), { @@ -176,19 +178,22 @@ export const lookupCommand = command( }), { description: message`Specify the output file path.` }, )), - timeout: bindConfig( - option( - "-T", - "--timeout", - float({ min: 0, metavar: "SECONDS" }), + timeout: optional( + bindConfig( + option( + "-T", + "--timeout", + float({ min: 0, metavar: "SECONDS" }), + { + description: + message`Set timeout for network requests in seconds.`, + }, + ), { - description: message`Set timeout for network requests in seconds.`, + context: configContext, + key: (config) => config.lookup?.timeout, }, ), - { - context: configContext, - key: (config) => config.lookup?.timeout, - }, ), }), ), From 0ac37f00da7f453a5d4a5031176cd7894ea500d9 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 11:31:57 +0900 Subject: [PATCH 30/35] Use XDG-compliant paths for config and cache directories Update system-wide and user-level config paths to follow XDG Base Directory Specification on Linux/macOS and use appropriate Windows directories: - System config: `$XDG_CONFIG_DIRS` (default: /etc/xdg) on Linux/macOS, `%ProgramData%` on Windows - User config: `$XDG_CONFIG_HOME` (default: ~/.config) on Linux/macOS, `%APPDATA%` on Windows - Cache: `$XDG_CACHE_HOME` (default: ~/.cache) on Linux/macOS, `%LOCALAPPDATA%` on Windows This replaces the env-paths dependency with inline XDG-compliant logic. Co-Authored-By: Claude Opus 4.5 --- docs/cli.md | 24 +++++++++++++--------- packages/cli/src/cache.ts | 22 +++++++++++++++++--- packages/cli/src/mod.ts | 43 +++++++++++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/docs/cli.md b/docs/cli.md index ccdbcd45d..fd26d7e52 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -117,16 +117,20 @@ command options. Configuration files are written in [TOML] format. Configuration files are loaded from the following locations in order, with later files taking precedence over earlier ones: -1. `/etc/fedify/config.toml` (system-wide) -2. *<user-config-dir>/fedify/config.toml* (user-level) -3. `.fedify.toml` in the current working directory (project-level) -4. Custom path via `--config` option (explicit) - -The user config directory varies by operating system: - - - **Linux**: *~/.config/fedify/config.toml* - - **macOS**: *~/Library/Application Support/fedify/config.toml* - - **Windows**: *%APPDATA%\\fedify\\config.toml* +1. System-wide configuration directories (see below) +2. *~/.config/fedify/config.toml* (user-level, or + `$XDG_CONFIG_HOME/fedify/config.toml`) +3. *.fedify.toml* in the current working directory (project-level) +4. Custom path specified via `--config` option (highest precedence) + +The system-wide and user-level config paths vary by operating system: + + - **Linux/macOS (system)**: Directories listed in `$XDG_CONFIG_DIRS` + (default: */etc/xdg/fedify/config.toml*) + - **Linux/macOS (user)**: `$XDG_CONFIG_HOME/fedify/config.toml` + (default: *~/.config/fedify/config.toml*) + - **Windows (system)**: *%ProgramData%\\fedify\\config.toml* + - **Windows (user)**: *%APPDATA%\\fedify\\config.toml* ### `--config`: Load an additional configuration file diff --git a/packages/cli/src/cache.ts b/packages/cli/src/cache.ts index d21c2d60f..17817268e 100644 --- a/packages/cli/src/cache.ts +++ b/packages/cli/src/cache.ts @@ -1,8 +1,24 @@ -import envPaths from "env-paths"; import { mkdir } from "node:fs/promises"; +import { homedir } from "node:os"; +import { join } from "node:path"; +import process from "node:process"; -const paths = envPaths("fedify", { suffix: "" }); -export const DEFAULT_CACHE_DIR = paths.cache; +/** + * Returns the default cache directory path. + * - Linux/macOS: `$XDG_CACHE_HOME/fedify` (default: ~/.cache/fedify) + * - Windows: `%LOCALAPPDATA%\fedify` + */ +function getDefaultCacheDir(): string { + if (process.platform === "win32") { + const localAppData = process.env.LOCALAPPDATA || + join(homedir(), "AppData", "Local"); + return join(localAppData, "fedify"); + } + const xdgCacheHome = process.env.XDG_CACHE_HOME || join(homedir(), ".cache"); + return join(xdgCacheHome, "fedify"); +} + +export const DEFAULT_CACHE_DIR = getDefaultCacheDir(); let currentCacheDir: string = DEFAULT_CACHE_DIR; diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index 72ee4a252..1a95067fd 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -2,8 +2,8 @@ import { runWithConfig } from "@optique/config/run"; import { merge, message, or } from "@optique/core"; import { printError } from "@optique/run"; -import envPaths from "env-paths"; import { merge as deepMerge } from "es-toolkit"; +import { homedir } from "node:os"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import process from "node:process"; @@ -22,6 +22,37 @@ import { relayCommand, runRelay } from "./relay.ts"; import { runTunnel, tunnelCommand } from "./tunnel.ts"; import { runWebFinger, webFingerCommand } from "./webfinger/mod.ts"; +/** + * Returns the system-wide configuration file paths. + * - Linux/macOS: Searches `$XDG_CONFIG_DIRS` (default: /etc/xdg) + * - Windows: Uses `%ProgramData%` (default: C:\ProgramData) + */ +function getSystemConfigPaths(): string[] { + if (process.platform === "win32") { + const programData = process.env.ProgramData || "C:\\ProgramData"; + return [join(programData, "fedify", "config.toml")]; + } + return (process.env.XDG_CONFIG_DIRS || "/etc/xdg") + .split(":") + .map((dir) => join(dir, "fedify", "config.toml")); +} + +/** + * Returns the user-level configuration file path. + * - Linux/macOS: `$XDG_CONFIG_HOME/fedify/config.toml` (default: ~/.config) + * - Windows: `%APPDATA%\fedify\config.toml` + */ +function getUserConfigPath(): string { + if (process.platform === "win32") { + const appData = process.env.APPDATA || + join(homedir(), "AppData", "Roaming"); + return join(appData, "fedify", "config.toml"); + } + const xdgConfigHome = process.env.XDG_CONFIG_HOME || + join(homedir(), ".config"); + return join(xdgConfigHome, "fedify", "config.toml"); +} + const command = merge( or( initCommand, @@ -42,9 +73,13 @@ async function main() { load: (parsed) => { if (parsed.ignoreConfig) return {}; - const userConfigDir = envPaths("fedify", { suffix: "" }).config; - const system = tryLoadToml("/etc/fedify/config.toml"); - const user = tryLoadToml(join(userConfigDir, "config.toml")); + // Load system-wide configs (XDG_CONFIG_DIRS on Linux/macOS, ProgramData on Windows) + const systemConfigs = getSystemConfigPaths().map(tryLoadToml); + const system = systemConfigs.reduce( + (acc, config) => deepMerge(acc, config), + {}, + ); + const user = tryLoadToml(getUserConfigPath()); const project = tryLoadToml(join(process.cwd(), ".fedify.toml")); // Custom config via --config exits with error if file is missing or invalid From 4ce87ed3e1ca6c6d7adf73d1c1da731720f10833 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 11:32:29 +0900 Subject: [PATCH 31/35] Address PR review feedback - Remove env-paths from dependencies (replaced with XDG-compliant logic) - Remove redundant es-toolkit from deno.json (already in package.json catalog) - Use JSR specifier for valibot in deno.json - Fix incorrect test comment about default value (5, not 0) Co-Authored-By: Claude Opus 4.5 --- deno.lock | 32 +++++++++++--------------- packages/cli/deno.json | 4 +--- packages/cli/package.json | 1 - packages/cli/src/webfinger/mod.test.ts | 2 +- pnpm-lock.yaml | 9 -------- 5 files changed, 16 insertions(+), 32 deletions(-) diff --git a/deno.lock b/deno.lock index e21d4a5c2..18e16152f 100644 --- a/deno.lock +++ b/deno.lock @@ -15,7 +15,7 @@ "jsr:@fresh/core@^2.2.0": "2.2.0", "jsr:@fresh/plugin-vite@^1.0.7": "1.0.8", "jsr:@hongminhee/localtunnel@0.3": "0.3.0", - "jsr:@hono/hono@^4.7.1": "4.11.4", + "jsr:@hono/hono@^4.7.1": "4.11.9", "jsr:@hono/hono@^4.8.3": "4.11.9", "jsr:@logtape/file@2": "2.0.2", "jsr:@logtape/logtape@2": "2.0.2", @@ -59,6 +59,7 @@ "jsr:@std/testing@0.224": "0.224.0", "jsr:@std/uuid@^1.0.9": "1.1.0", "jsr:@std/yaml@^1.0.8": "1.0.10", + "jsr:@valibot/valibot@^1.2.0": "1.2.0", "npm:@alinea/suite@~0.6.3": "0.6.3", "npm:@babel/core@^7.28.0": "7.29.0", "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0", @@ -105,13 +106,11 @@ "npm:cli-highlight@^2.1.11": "2.1.11", "npm:cli-table3@~0.6.5": "0.6.5", "npm:enquirer@^2.4.1": "2.4.1", - "npm:env-paths@3": "3.0.0", - "npm:es-toolkit@^1.30.0": "1.43.0", - "npm:es-toolkit@^1.31.0": "1.43.0", - "npm:es-toolkit@^1.39.10": "1.43.0", - "npm:es-toolkit@^1.39.4": "1.43.0", - "npm:es-toolkit@^1.42.0": "1.43.0", - "npm:es-toolkit@^1.43.0": "1.43.0", + "npm:es-toolkit@^1.30.0": "1.44.0", + "npm:es-toolkit@^1.31.0": "1.44.0", + "npm:es-toolkit@^1.39.10": "1.44.0", + "npm:es-toolkit@^1.42.0": "1.44.0", + "npm:es-toolkit@^1.43.0": "1.44.0", "npm:esbuild-wasm@~0.25.11": "0.25.12", "npm:esbuild@0.25.7": "0.25.7", "npm:esbuild@~0.25.5": "0.25.12", @@ -411,6 +410,9 @@ }, "@std/yaml@1.0.10": { "integrity": "245706ea3511cc50c8c6d00339c23ea2ffa27bd2c7ea5445338f8feff31fa58e" + }, + "@valibot/valibot@1.2.0": { + "integrity": "61c118a4d027ed55912caf381c78f0a178f335f46ad0c4bcb136498dc1ef2285" } }, "npm": { @@ -3315,9 +3317,6 @@ "strip-ansi@6.0.1" ] }, - "env-paths@3.0.0": { - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==" - }, "error-stack-parser-es@1.0.5": { "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==" }, @@ -3336,8 +3335,8 @@ "es-errors" ] }, - "es-toolkit@1.43.0": { - "integrity": "sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==" + "es-toolkit@1.44.0": { + "integrity": "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==" }, "esbuild-wasm@0.25.12": { "integrity": "sha512-rZqkjL3Y6FwLpSHzLnaEy8Ps6veCNo1kZa9EOfJvmWtBq5dJH4iVjfmOO6Mlkv9B0tt9WFPFmb/VxlgJOnueNg==", @@ -5958,22 +5957,20 @@ "jsr:@optique/config@~0.10.0-dev.355", "jsr:@optique/core@~0.10.0-dev.355", "jsr:@optique/run@~0.10.0-dev.355", + "jsr:@valibot/valibot@^1.2.0", "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", "npm:@poppanator/http-constants@^1.1.1", "npm:chalk@^5.6.2", "npm:cli-table3@~0.6.5", - "npm:env-paths@3", - "npm:es-toolkit@^1.39.4", "npm:fetch-mock@^12.5.4", "npm:icojs@~0.19.5", "npm:inquirer-toggle@^1.0.1", "npm:ora@^8.2.0", "npm:shiki@^1.6.4", "npm:smol-toml@^1.6.0", - "npm:srvx@~0.8.7", - "npm:valibot@^1.2.0" + "npm:srvx@~0.8.7" ], "packageJson": { "dependencies": [ @@ -5989,7 +5986,6 @@ "npm:cli-highlight@^2.1.11", "npm:cli-table3@~0.6.5", "npm:enquirer@^2.4.1", - "npm:env-paths@3", "npm:hono@^4.8.3", "npm:icojs@~0.19.5", "npm:inquirer-toggle@^1.0.1", diff --git a/packages/cli/deno.json b/packages/cli/deno.json index cc54d809d..449a5530a 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -14,8 +14,6 @@ "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", - "env-paths": "npm:env-paths@^3.0.0", - "es-toolkit": "npm:es-toolkit@^1.39.4", "fetch-mock": "npm:fetch-mock@^12.5.4", "hono": "jsr:@hono/hono@^4.8.3", "icojs": "npm:icojs@^0.19.5", @@ -24,7 +22,7 @@ "shiki": "npm:shiki@^1.6.4", "smol-toml": "npm:smol-toml@^1.6.0", "srvx": "npm:srvx@^0.8.7", - "valibot": "npm:valibot@^1.2.0", + "valibot": "jsr:@valibot/valibot@^1.2.0", "#kv": "./src/kv.node.ts" }, "exclude": [ diff --git a/packages/cli/package.json b/packages/cli/package.json index 30ffed499..8bf38bc54 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -96,7 +96,6 @@ "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", "enquirer": "^2.4.1", - "env-paths": "^3.0.0", "es-toolkit": "catalog:", "fetch-mock": "catalog:", "hono": "^4.8.3", diff --git a/packages/cli/src/webfinger/mod.test.ts b/packages/cli/src/webfinger/mod.test.ts index f38997a9e..6297fc7b6 100644 --- a/packages/cli/src/webfinger/mod.test.ts +++ b/packages/cli/src/webfinger/mod.test.ts @@ -83,7 +83,7 @@ test("Test webFingerCommand - invalid option value falls back to default", async assert.ok(result.success); if (result.success) { - // Falls back to default value of 0 + // Falls back to default value of 5 assert.strictEqual(result.value.maxRedirection, 5); } }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54bfa5c57..8446f815f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -807,9 +807,6 @@ importers: enquirer: specifier: ^2.4.1 version: 2.4.1 - env-paths: - specifier: ^3.0.0 - version: 3.0.0 es-toolkit: specifier: 'catalog:' version: 1.43.0 @@ -5779,10 +5776,6 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - env-paths@3.0.0: - resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - error-stack-parser-es@1.0.5: resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==} @@ -13591,8 +13584,6 @@ snapshots: entities@4.5.0: {} - env-paths@3.0.0: {} - error-stack-parser-es@1.0.5: {} es-abstract@1.24.0: From efc2c9365d9b006dbfd2cd9bb417d51af56cb2be Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sat, 14 Feb 2026 15:08:56 +0900 Subject: [PATCH 32/35] Merge debug and config options into globalOptions Combine debugOption and configOption into a single globalOptions object for a unified "Global options" group in CLI help output. - Commands using command.debug (lookup, tunnel, relay, inbox) now use GlobalOptions type intersection - Commands not using debug (nodeinfo, webfinger, init, generate-vocab) no longer include debugOption - Updated tests to reflect the new option structure Co-Authored-By: Claude Opus 4.5 --- deno.lock | 15 +++++++++++++++ packages/cli/src/inbox.tsx | 5 ++--- packages/cli/src/lookup.ts | 7 ++++--- packages/cli/src/mod.ts | 4 ++-- packages/cli/src/nodeinfo.ts | 3 +-- packages/cli/src/options.ts | 22 +++++++++++++++++++++- packages/cli/src/relay.ts | 5 ++--- packages/cli/src/tunnel.test.ts | 8 +++++--- packages/cli/src/tunnel.ts | 5 ++--- packages/cli/src/webfinger/command.ts | 3 +-- packages/cli/src/webfinger/mod.test.ts | 3 --- 11 files changed, 55 insertions(+), 25 deletions(-) diff --git a/deno.lock b/deno.lock index 18e16152f..b602c0631 100644 --- a/deno.lock +++ b/deno.lock @@ -5886,6 +5886,8 @@ "jsr:@hono/hono@^4.8.3", "jsr:@logtape/file@2", "jsr:@logtape/logtape@2", + "jsr:@optique/core@0.9", + "jsr:@optique/run@0.9", "jsr:@std/assert@^1.0.13", "jsr:@std/async@^1.0.13", "jsr:@std/encoding@^1.0.10", @@ -5905,6 +5907,7 @@ "npm:@types/node@^22.16.0", "npm:amqplib@~0.10.9", "npm:byte-encodings@^1.0.11", + "npm:chalk@^5.6.2", "npm:es-toolkit@^1.43.0", "npm:h3@^1.15.0", "npm:ioredis@^5.8.2", @@ -6058,6 +6061,18 @@ "jsr:@std/assert@^1.0.13" ] }, + "packages/init": { + "dependencies": [ + "npm:@inquirer/prompts@^7.8.4", + "npm:inquirer-toggle@^1.0.1" + ], + "packageJson": { + "dependencies": [ + "npm:@inquirer/prompts@^7.8.4", + "npm:inquirer-toggle@^1.0.1" + ] + } + }, "packages/koa": { "dependencies": [ "npm:koa@2" diff --git a/packages/cli/src/inbox.tsx b/packages/cli/src/inbox.tsx index e7a94d080..ce77ba0d4 100644 --- a/packages/cli/src/inbox.tsx +++ b/packages/cli/src/inbox.tsx @@ -46,7 +46,7 @@ import { getDocumentLoader } from "./docloader.ts"; import type { ActivityEntry } from "./inbox/entry.ts"; import { ActivityEntryPage, ActivityListPage } from "./inbox/view.tsx"; import { configureLogging, recordingSink } from "./log.ts"; -import { createTunnelOption, debugOption } from "./options.ts"; +import { createTunnelOption, type GlobalOptions } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; @@ -137,7 +137,6 @@ export const inboxCommand = command( ), }), createTunnelOption("inbox"), - debugOption, ), { brief: message`Run an ephemeral ActivityPub inbox server.`, @@ -153,7 +152,7 @@ const peers: Record = {}; const followers: Record = {}; export async function runInbox( - command: InferValue, + command: InferValue & GlobalOptions, ) { // Reset module-level state for a clean run activities.length = 0; diff --git a/packages/cli/src/lookup.ts b/packages/cli/src/lookup.ts index 1613642ab..796868028 100644 --- a/packages/cli/src/lookup.ts +++ b/packages/cli/src/lookup.ts @@ -44,7 +44,7 @@ import { getContextLoader, getDocumentLoader } from "./docloader.ts"; import { renderImages } from "./imagerenderer.ts"; import { configureLogging } from "./log.ts"; import { - debugOption, + type GlobalOptions, tunnelServiceOption, userAgentOption, } from "./options.ts"; @@ -119,7 +119,6 @@ export const lookupCommand = command( object({ command: constant("lookup") }), traverseOption, authorizedFetchOption, - debugOption, userAgentOption, object({ urls: multiple( @@ -328,7 +327,9 @@ function handleTimeoutError( ); } -export async function runLookup(command: InferValue) { +export async function runLookup( + command: InferValue & GlobalOptions, +) { if (command.urls.length < 1) { printError(message`At least one URL or actor handle must be provided.`); process.exit(1); diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index 1a95067fd..f66e8b55a 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -17,7 +17,7 @@ import { inboxCommand, runInbox } from "./inbox.tsx"; import { initCommand, runInit } from "./init/mod.ts"; import { lookupCommand, runLookup } from "./lookup.ts"; import { nodeInfoCommand, runNodeInfo } from "./nodeinfo.ts"; -import { configOption } from "./options.ts"; +import { globalOptions } from "./options.ts"; import { relayCommand, runRelay } from "./relay.ts"; import { runTunnel, tunnelCommand } from "./tunnel.ts"; import { runWebFinger, webFingerCommand } from "./webfinger/mod.ts"; @@ -64,7 +64,7 @@ const command = merge( generateVocabCommand, relayCommand, ), - configOption, + globalOptions, ); async function main() { diff --git a/packages/cli/src/nodeinfo.ts b/packages/cli/src/nodeinfo.ts index 208827411..d464c01c6 100644 --- a/packages/cli/src/nodeinfo.ts +++ b/packages/cli/src/nodeinfo.ts @@ -24,7 +24,7 @@ import os from "node:os"; import process from "node:process"; import ora from "ora"; import { configContext } from "./config.ts"; -import { debugOption, userAgentOption } from "./options.ts"; +import { userAgentOption } from "./options.ts"; import { colors, formatObject } from "./utils.ts"; const logger = getLogger(["fedify", "cli", "nodeinfo"]); @@ -88,7 +88,6 @@ export const nodeInfoCommand = Command( description: message`Bare hostname or a full URL of the instance`, }), }), - debugOption, nodeInfoOption, userAgentOption, ), diff --git a/packages/cli/src/options.ts b/packages/cli/src/options.ts index 461c02e29..96dc8dde6 100644 --- a/packages/cli/src/options.ts +++ b/packages/cli/src/options.ts @@ -4,7 +4,9 @@ import { choice, constant, flag, + type InferValue, map, + merge, message, object, option, @@ -126,7 +128,7 @@ export const userAgentOption = object({ * - `{ ignoreConfig: false, configPath: string }` when `--config` is specified * - `{ ignoreConfig: false }` when neither is specified (default) */ -export const configOption = withDefault( +const configOption = withDefault( or( object({ ignoreConfig: map( @@ -145,3 +147,21 @@ export const configOption = withDefault( ), { ignoreConfig: false, configPath: undefined } as const, ); + +/** + * Global options that apply to all commands. + * + * Combines debug mode and configuration file options into a single + * "Global options" group. + */ +export const globalOptions = merge( + "Global options", + debugOption, + configOption, +); + +/** + * Type representing the parsed global options. + * Use this to extend command types with global options in run functions. + */ +export type GlobalOptions = InferValue; diff --git a/packages/cli/src/relay.ts b/packages/cli/src/relay.ts index bf8daf19c..1a30f7729 100644 --- a/packages/cli/src/relay.ts +++ b/packages/cli/src/relay.ts @@ -25,7 +25,7 @@ import { DatabaseSync } from "node:sqlite"; import ora from "ora"; import { configContext } from "./config.ts"; import { configureLogging } from "./log.ts"; -import { createTunnelOption, debugOption } from "./options.ts"; +import { createTunnelOption, type GlobalOptions } from "./options.ts"; import { tableStyle } from "./table.ts"; import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts"; import { colors, matchesActor } from "./utils.ts"; @@ -121,7 +121,6 @@ export const relayCommand = command( ), }), createTunnelOption("relay"), - debugOption, ), { brief: message`Run an ephemeral ActivityPub relay server.`, @@ -135,7 +134,7 @@ export const relayCommand = command( ); export async function runRelay( - command: InferValue, + command: InferValue & GlobalOptions, ): Promise { if (command.debug) { await configureLogging(); diff --git a/packages/cli/src/tunnel.test.ts b/packages/cli/src/tunnel.test.ts index 9bf72ed77..b7ef03f5e 100644 --- a/packages/cli/src/tunnel.test.ts +++ b/packages/cli/src/tunnel.test.ts @@ -7,7 +7,7 @@ import { runTunnel, tunnelCommand } from "./tunnel.ts"; test("tunnel command structure", () => { const testCommandWithOptions = run(tunnelCommand, { - args: ["tunnel", "3001", "-s", "pinggy.io", "-d"], + args: ["tunnel", "3001", "-s", "pinggy.io"], }); const testCommandWithoutOptions = run(tunnelCommand, { args: ["tunnel", "3000"], @@ -16,11 +16,9 @@ test("tunnel command structure", () => { deepEqual(testCommandWithOptions.command, "tunnel"); deepEqual(testCommandWithOptions.port, 3001); deepEqual(testCommandWithOptions.service, "pinggy.io"); - deepEqual(testCommandWithOptions.debug, true); deepEqual(testCommandWithoutOptions.port, 3000); deepEqual(testCommandWithoutOptions.service, undefined); - deepEqual(testCommandWithoutOptions.debug, false); }); test("tunnel successfully creates and manages tunnel", async () => { @@ -29,6 +27,8 @@ test("tunnel successfully creates and manages tunnel", async () => { port: 3001, service: "pinggy.io" as const, debug: true, + ignoreConfig: false as const, + configPath: undefined, }; const mockTunnel: Tunnel = { @@ -97,6 +97,8 @@ test("tunnel fails to create a secure tunnel and handles error", async () => { port: 3001, service: undefined, debug: false, + ignoreConfig: false as const, + configPath: undefined, }; let openTunnelCalled = false; diff --git a/packages/cli/src/tunnel.ts b/packages/cli/src/tunnel.ts index 500ca7bbc..264be2482 100644 --- a/packages/cli/src/tunnel.ts +++ b/packages/cli/src/tunnel.ts @@ -17,7 +17,7 @@ import { print, printError } from "@optique/run"; import process from "node:process"; import ora from "ora"; import { configureLogging } from "./log.ts"; -import { debugOption, TUNNEL_SERVICES } from "./options.ts"; +import { type GlobalOptions, TUNNEL_SERVICES } from "./options.ts"; export const tunnelCommand = command( "tunnel", @@ -46,7 +46,6 @@ export const tunnelCommand = command( ), ), }), - debugOption, ), { brief: @@ -59,7 +58,7 @@ Note that the HTTP requests through the tunnel have X-Forwarded-* headers.`, ); export async function runTunnel( - command: InferValue, + command: InferValue & GlobalOptions, deps: { openTunnel: typeof openTunnel; ora: typeof ora; diff --git a/packages/cli/src/webfinger/command.ts b/packages/cli/src/webfinger/command.ts index c0516791d..b621b9fc8 100644 --- a/packages/cli/src/webfinger/command.ts +++ b/packages/cli/src/webfinger/command.ts @@ -14,7 +14,7 @@ import { string, } from "@optique/core"; import { configContext } from "../config.ts"; -import { debugOption, userAgentOption } from "../options.ts"; +import { userAgentOption } from "../options.ts"; const allowPrivateAddresses = bindConfig( flag("-p", "--allow-private-address", { @@ -55,7 +55,6 @@ export const webFingerCommand = command( maxRedirection, }), userAgentOption, - debugOption, ), { brief: message`Look up WebFinger resources.`, diff --git a/packages/cli/src/webfinger/mod.test.ts b/packages/cli/src/webfinger/mod.test.ts index 6297fc7b6..f08190753 100644 --- a/packages/cli/src/webfinger/mod.test.ts +++ b/packages/cli/src/webfinger/mod.test.ts @@ -25,7 +25,6 @@ test("Test webFingerCommand - resources only", async () => { assert.ok(result.success); if (result.success) { - assert.strictEqual(result.value.debug, false); assert.strictEqual(result.value.command, COMMAND); assert.deepEqual(result.value.resources, RESOURCES); assert.strictEqual(result.value.allowPrivateAddresses, false); @@ -41,7 +40,6 @@ test("Test webFingerCommand - with all options", () => { assert.deepEqual( parse(webFingerCommand, [ ...argsWithResourcesOnly, - "-d", "-u", USER_AGENT, "--max-redirection", @@ -51,7 +49,6 @@ test("Test webFingerCommand - with all options", () => { { success: true, value: { - debug: true, command: COMMAND, resources: RESOURCES, allowPrivateAddresses: true, From f5776d63729c4ca37fcf6aa7079ac8170717830a Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sun, 15 Feb 2026 02:00:15 +0900 Subject: [PATCH 33/35] Upgrade Optique to v0.10.0-dev.376 to fix nested merge bug The previous version (v0.10.0-dev.355) had a bug where `withDefault(or(...))` inside a nested `merge()` would silently lose parsed values during `runWithConfig`'s two-pass parsing. This caused `--config PATH` to always be `undefined` in the `load` callback after the globalOptions refactoring. Co-Authored-By: Claude Opus 4.6 --- deno.lock | 68 ++++++++++++++-------- packages/cli/deno.json | 6 +- packages/cli/package.json | 6 +- pnpm-lock.yaml | 119 ++++++++++++++++++++++++++++++++------ 4 files changed, 152 insertions(+), 47 deletions(-) diff --git a/deno.lock b/deno.lock index b602c0631..64b20dbd7 100644 --- a/deno.lock +++ b/deno.lock @@ -21,9 +21,13 @@ "jsr:@logtape/logtape@2": "2.0.2", "jsr:@logtape/logtape@^1.0.4": "1.3.7", "jsr:@logtape/logtape@^2.0.2": "2.0.2", - "jsr:@optique/config@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", - "jsr:@optique/core@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", - "jsr:@optique/run@~0.10.0-dev.355": "0.10.0-dev.355+7475e7e5", + "jsr:@optique/config@~0.10.0-dev.376": "0.10.0-dev.377+69abd2d5", + "jsr:@optique/core@0.9": "0.9.6", + "jsr:@optique/core@~0.10.0-dev.376": "0.10.0-dev.377+69abd2d5", + "jsr:@optique/core@~0.10.0-dev.377+69abd2d5": "0.10.0-dev.377+69abd2d5", + "jsr:@optique/core@~0.9.6": "0.9.6", + "jsr:@optique/run@0.9": "0.9.6", + "jsr:@optique/run@~0.10.0-dev.376": "0.10.0-dev.377+69abd2d5", "jsr:@std/assert@0.224": "0.224.0", "jsr:@std/assert@0.226": "0.226.0", "jsr:@std/assert@^1.0.13": "1.0.18", @@ -81,9 +85,9 @@ "npm:@opentelemetry/core@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/sdk-trace-base@^2.5.0": "2.5.0_@opentelemetry+api@1.9.0", "npm:@opentelemetry/semantic-conventions@^1.39.0": "1.39.0", - "npm:@optique/config@0.10.0-dev.355": "0.10.0-dev.355_@standard-schema+spec@1.1.0", - "npm:@optique/core@0.10.0-dev.355": "0.10.0-dev.355", - "npm:@optique/run@0.10.0-dev.355": "0.10.0-dev.355", + "npm:@optique/config@0.10.0-dev.376": "0.10.0-dev.376_@standard-schema+spec@1.1.0", + "npm:@optique/core@0.10.0-dev.376": "0.10.0-dev.376", + "npm:@optique/run@0.10.0-dev.376": "0.10.0-dev.376", "npm:@poppanator/http-constants@^1.1.1": "1.1.1", "npm:@preact/signals@^2.2.1": "2.7.1_preact@10.19.6", "npm:@preact/signals@^2.3.2": "2.7.1_preact@10.19.6", @@ -280,20 +284,33 @@ "@logtape/logtape@2.0.2": { "integrity": "546fcd514e66f2b841c6f261fa3a3d905b52d876dc1bba8ffe1a087d9275c4c9" }, - "@optique/config@0.10.0-dev.355+7475e7e5": { - "integrity": "10fd42374ae3d558d3bfc1a0db4b665932fbdb3b64ee2b4e9023af45585f5af9", + "@optique/config@0.10.0-dev.377+69abd2d5": { + "integrity": "ed66824f56e93cae8af632259cc5d0a3cca6315e73b78e9bfa2e285c45d2e52d", "dependencies": [ + "jsr:@optique/core@~0.10.0-dev.377+69abd2d5", "npm:@standard-schema/spec" ] }, + "@optique/core@0.9.6": { + "integrity": "46aa82e9ac8cdea857322acd1aad206eaf42e78f71fb857a0d97d2e67cd4eae2" + }, "@optique/core@0.10.0-dev.333+076fceae": { "integrity": "1ebe1782740f08d568ae0c5258786933a8502d1e137feb49b2d8ab06d204b11a" }, - "@optique/core@0.10.0-dev.355+7475e7e5": { - "integrity": "e1ee54f3861b8d85f30fd11bfedaf739822d509c62a6f52b769456f1b430bd23" + "@optique/core@0.10.0-dev.377+69abd2d5": { + "integrity": "41d87a47ee9e85b0cdb611ebd0b06daaca48ca337884631a992c6f73a0ee4e57" }, - "@optique/run@0.10.0-dev.355+7475e7e5": { - "integrity": "896094666b885925b4816447bea884c5a2e6f872928fe3462d7af33497aa30fa" + "@optique/run@0.9.6": { + "integrity": "0113af8f4983732217316754c2cb80b115f173e1b195c8040053739dbfd97703", + "dependencies": [ + "jsr:@optique/core@~0.9.6" + ] + }, + "@optique/run@0.10.0-dev.377+69abd2d5": { + "integrity": "fcb1150032d0a17f3e527da7cf136f762ad7c8f4315de93b0856816e81d30562", + "dependencies": [ + "jsr:@optique/core@~0.10.0-dev.377+69abd2d5" + ] }, "@std/assert@0.224.0": { "integrity": "8643233ec7aec38a940a8264a6e3eed9bfa44e7a71cc6b3c8874213ff401967f", @@ -317,6 +334,9 @@ "@std/async@1.0.16": { "integrity": "6c9e43035313b67b5de43e2b3ee3eadb39a488a0a0a3143097f112e025d3ee9a" }, + "@std/async@1.1.1": { + "integrity": "8a79beb3378cc229ce65ba2c746cfd03e4855ddd891d1eb6b9e32128e0d5339c" + }, "@std/bytes@1.0.6": { "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" }, @@ -2069,18 +2089,18 @@ "@opentelemetry/semantic-conventions@1.39.0": { "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==" }, - "@optique/config@0.10.0-dev.355_@standard-schema+spec@1.1.0": { - "integrity": "sha512-BJmZ/iC/TLCVnXXQGRUG6t7MA+Zilg6Sdm2dkaJAghSxFrgBEgdTikwi+stVR2DulC3+GWUxg5NDP6/ruB0K3g==", + "@optique/config@0.10.0-dev.376_@standard-schema+spec@1.1.0": { + "integrity": "sha512-eJ6jldeYRDHTYeQykAG1m1VHONkrUMwblwvkAyTFz9+4sI1s+Jddzyufa45jEc25WCeDkEZ+GsTfcuTRWrD7Dw==", "dependencies": [ "@optique/core", "@standard-schema/spec" ] }, - "@optique/core@0.10.0-dev.355": { - "integrity": "sha512-VlHNHbeUxby3SDOQdCrc99TldReB15wgK1UoxgriAbprxgXz1Lt3iyAjK88I8Z5Rc5AnMqVPaE+xHJXTTAbgxQ==" + "@optique/core@0.10.0-dev.376": { + "integrity": "sha512-nGNKIVk28HobnH+Q9T9yzNevnTOA+EoNcgAn0nDPggn3lgsjCWT22htu4PvmqzNRGNqmztFoqstjXTXF15HMbg==" }, - "@optique/run@0.10.0-dev.355": { - "integrity": "sha512-NSFK/hG3C09QpxV7Ufv3INXP1Xj1OtTJ4+A+PcCwKewYmfzj7EfPswaaBHxogJpNUwHvkKgwkafkLOR+ClShvw==", + "@optique/run@0.10.0-dev.376": { + "integrity": "sha512-3lNskdovUVg66GNhn//xULvHALGh0xZW1ZmfuGqQBglVDYRgMydlvetLuQY4olUftH92RwK+MeWY0jT9X3GtdQ==", "dependencies": [ "@optique/core" ] @@ -5957,9 +5977,9 @@ "dependencies": [ "jsr:@hongminhee/localtunnel@0.3", "jsr:@hono/hono@^4.8.3", - "jsr:@optique/config@~0.10.0-dev.355", - "jsr:@optique/core@~0.10.0-dev.355", - "jsr:@optique/run@~0.10.0-dev.355", + "jsr:@optique/config@~0.10.0-dev.376", + "jsr:@optique/core@~0.10.0-dev.376", + "jsr:@optique/run@~0.10.0-dev.376", "jsr:@valibot/valibot@^1.2.0", "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", @@ -5981,9 +6001,9 @@ "npm:@inquirer/prompts@^7.8.4", "npm:@jimp/core@^1.6.0", "npm:@jimp/wasm-webp@^1.6.0", - "npm:@optique/config@0.10.0-dev.355", - "npm:@optique/core@0.10.0-dev.355", - "npm:@optique/run@0.10.0-dev.355", + "npm:@optique/config@0.10.0-dev.376", + "npm:@optique/core@0.10.0-dev.376", + "npm:@optique/run@0.10.0-dev.376", "npm:@poppanator/http-constants@^1.1.1", "npm:chalk@^5.6.2", "npm:cli-highlight@^2.1.11", diff --git a/packages/cli/deno.json b/packages/cli/deno.json index 449a5530a..66b303a92 100644 --- a/packages/cli/deno.json +++ b/packages/cli/deno.json @@ -8,9 +8,9 @@ "@inquirer/prompts": "npm:@inquirer/prompts@^7.8.4", "@jimp/core": "npm:@jimp/core@^1.6.0", "@jimp/wasm-webp": "npm:@jimp/wasm-webp@^1.6.0", - "@optique/config": "jsr:@optique/config@^0.10.0-dev.355", - "@optique/core": "jsr:@optique/core@^0.10.0-dev.355", - "@optique/run": "jsr:@optique/run@^0.10.0-dev.355", + "@optique/config": "jsr:@optique/config@^0.10.0-dev.376", + "@optique/core": "jsr:@optique/core@^0.10.0-dev.376", + "@optique/run": "jsr:@optique/run@^0.10.0-dev.376", "@poppanator/http-constants": "npm:@poppanator/http-constants@^1.1.1", "chalk": "npm:chalk@^5.6.2", "cli-table3": "npm:cli-table3@^0.6.5", diff --git a/packages/cli/package.json b/packages/cli/package.json index 8bf38bc54..d443a6a45 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -87,9 +87,9 @@ "@js-temporal/polyfill": "catalog:", "@logtape/file": "catalog:", "@logtape/logtape": "catalog:", - "@optique/config": "0.10.0-dev.355", - "@optique/core": "0.10.0-dev.355", - "@optique/run": "0.10.0-dev.355", + "@optique/config": "0.10.0-dev.376", + "@optique/core": "0.10.0-dev.376", + "@optique/run": "0.10.0-dev.376", "@poppanator/http-constants": "^1.1.1", "byte-encodings": "catalog:", "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8446f815f..dbcddc76c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,12 @@ catalogs: '@opentelemetry/semantic-conventions': specifier: ^1.39.0 version: 1.39.0 + '@optique/core': + specifier: ^0.9.0 + version: 0.9.6 + '@optique/run': + specifier: ^0.9.0 + version: 0.9.6 '@std/assert': specifier: jsr:^1.0.13 version: 1.0.13 @@ -84,6 +90,9 @@ catalogs: byte-encodings: specifier: ^1.0.11 version: 1.0.11 + chalk: + specifier: ^5.6.2 + version: 5.6.2 elysia: specifier: ^1.3.8 version: 1.3.8 @@ -781,14 +790,14 @@ importers: specifier: 'catalog:' version: 2.0.0 '@optique/config': - specifier: 0.10.0-dev.355 - version: 0.10.0-dev.355(@standard-schema/spec@1.0.0) + specifier: 0.10.0-dev.376 + version: 0.10.0-dev.376(@standard-schema/spec@1.0.0) '@optique/core': - specifier: 0.10.0-dev.355 - version: 0.10.0-dev.355 + specifier: 0.10.0-dev.376 + version: 0.10.0-dev.376 '@optique/run': - specifier: 0.10.0-dev.355 - version: 0.10.0-dev.355 + specifier: 0.10.0-dev.376 + version: 0.10.0-dev.376 '@poppanator/http-constants': specifier: ^1.1.1 version: 1.1.1 @@ -857,6 +866,31 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/create: + dependencies: + '@fedify/init': + specifier: workspace:* + version: link:../init + '@optique/core': + specifier: 'catalog:' + version: 0.9.6 + '@optique/run': + specifier: 'catalog:' + version: 0.9.6 + es-toolkit: + specifier: 'catalog:' + version: 1.43.0 + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 22.19.1 + tsdown: + specifier: 'catalog:' + version: 0.12.9(typescript@5.9.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + packages/debugger: dependencies: '@fedify/fedify': @@ -1105,6 +1139,43 @@ importers: specifier: 'catalog:' version: 5.9.3 + packages/init: + dependencies: + '@fxts/core': + specifier: 'catalog:' + version: 1.20.0 + '@inquirer/prompts': + specifier: ^7.8.4 + version: 7.10.1(@types/node@22.19.1) + '@logtape/logtape': + specifier: 'catalog:' + version: 2.0.0 + '@optique/core': + specifier: 'catalog:' + version: 0.9.6 + '@optique/run': + specifier: 'catalog:' + version: 0.9.6 + chalk: + specifier: 'catalog:' + version: 5.6.2 + es-toolkit: + specifier: 'catalog:' + version: 1.43.0 + inquirer-toggle: + specifier: ^1.0.1 + version: 1.0.1 + devDependencies: + '@types/node': + specifier: 'catalog:' + version: 22.19.1 + tsdown: + specifier: 'catalog:' + version: 0.12.9(typescript@5.9.3) + typescript: + specifier: 'catalog:' + version: 5.9.3 + packages/koa: dependencies: '@fedify/fedify': @@ -3591,18 +3662,26 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@optique/config@0.10.0-dev.355': - resolution: {integrity: sha512-BJmZ/iC/TLCVnXXQGRUG6t7MA+Zilg6Sdm2dkaJAghSxFrgBEgdTikwi+stVR2DulC3+GWUxg5NDP6/ruB0K3g==} + '@optique/config@0.10.0-dev.376': + resolution: {integrity: sha512-eJ6jldeYRDHTYeQykAG1m1VHONkrUMwblwvkAyTFz9+4sI1s+Jddzyufa45jEc25WCeDkEZ+GsTfcuTRWrD7Dw==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} peerDependencies: '@standard-schema/spec': ^1.1.0 - '@optique/core@0.10.0-dev.355': - resolution: {integrity: sha512-VlHNHbeUxby3SDOQdCrc99TldReB15wgK1UoxgriAbprxgXz1Lt3iyAjK88I8Z5Rc5AnMqVPaE+xHJXTTAbgxQ==} + '@optique/core@0.10.0-dev.376': + resolution: {integrity: sha512-nGNKIVk28HobnH+Q9T9yzNevnTOA+EoNcgAn0nDPggn3lgsjCWT22htu4PvmqzNRGNqmztFoqstjXTXF15HMbg==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} - '@optique/run@0.10.0-dev.355': - resolution: {integrity: sha512-NSFK/hG3C09QpxV7Ufv3INXP1Xj1OtTJ4+A+PcCwKewYmfzj7EfPswaaBHxogJpNUwHvkKgwkafkLOR+ClShvw==} + '@optique/core@0.9.6': + resolution: {integrity: sha512-LZwiTSmtNWXRnTfhsfKXY3Ly83Wiy9uMjO1K294nnsBgOIQ67vv1tORT5SpJfCofxGmQpspE0Toig7dGxu0gDg==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + + '@optique/run@0.10.0-dev.376': + resolution: {integrity: sha512-3lNskdovUVg66GNhn//xULvHALGh0xZW1ZmfuGqQBglVDYRgMydlvetLuQY4olUftH92RwK+MeWY0jT9X3GtdQ==} + engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} + + '@optique/run@0.9.6': + resolution: {integrity: sha512-xG7oW9KGqwqQq7krpu+Lh7ji89O/Jl+lJ4ts4dOhlNbdyfRAVwNtBBudkanS3HGEkWTmWmD/6mgMChbMgQOpgQ==} engines: {bun: '>=1.2.0', deno: '>=2.3.0', node: '>=20.0.0'} '@oxc-project/runtime@0.75.0': @@ -11139,16 +11218,22 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) - '@optique/config@0.10.0-dev.355(@standard-schema/spec@1.0.0)': + '@optique/config@0.10.0-dev.376(@standard-schema/spec@1.0.0)': dependencies: - '@optique/core': 0.10.0-dev.355 + '@optique/core': 0.10.0-dev.376 '@standard-schema/spec': 1.0.0 - '@optique/core@0.10.0-dev.355': {} + '@optique/core@0.10.0-dev.376': {} + + '@optique/core@0.9.6': {} + + '@optique/run@0.10.0-dev.376': + dependencies: + '@optique/core': 0.10.0-dev.376 - '@optique/run@0.10.0-dev.355': + '@optique/run@0.9.6': dependencies: - '@optique/core': 0.10.0-dev.355 + '@optique/core': 0.9.6 '@oxc-project/runtime@0.75.0': {} From 53a2390fc7ea21cbfa8ca458523cc9bd1284d365 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sun, 15 Feb 2026 19:10:08 +0900 Subject: [PATCH 34/35] Add onError handler to runWithConfig to exit on parse errors Without this, parse errors (unknown options, missing arguments) would print an error message but continue execution, causing confusing behavior. Co-Authored-By: Claude Opus 4.6 --- packages/cli/src/mod.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/mod.ts b/packages/cli/src/mod.ts index f66e8b55a..8100d5b0c 100644 --- a/packages/cli/src/mod.ts +++ b/packages/cli/src/mod.ts @@ -3,8 +3,8 @@ import { runWithConfig } from "@optique/config/run"; import { merge, message, or } from "@optique/core"; import { printError } from "@optique/run"; import { merge as deepMerge } from "es-toolkit"; -import { homedir } from "node:os"; import { readFileSync } from "node:fs"; +import { homedir } from "node:os"; import { join } from "node:path"; import process from "node:process"; import { parse as parseToml } from "smol-toml"; @@ -107,6 +107,7 @@ async function main() { mode: "both", onShow: () => process.exit(0), }, + onError: () => process.exit(1), }); if (result.command === "init") { await runInit(result); From 003ad6385df817f4023d591641b3706ea27f6997 Mon Sep 17 00:00:00 2001 From: Jiwon Kwon Date: Sun, 15 Feb 2026 21:14:36 +0900 Subject: [PATCH 35/35] Fix config path on change log --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a69b8196b..ad24859f0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -227,7 +227,7 @@ To be released. precedence chain. [[#555], [#566] by Jiwon Kwon] - By default, configuration is loaded (in order of increasing precedence) - from a system-wide configuration file (*/etc/fedify/config.toml*), + from a system-wide configuration file (*/etc/xdg/fedify/config.toml*), a user-level configuration file (*~/.config/fedify/config.toml*), and *.fedify.toml* in the current directory; later files override earlier ones.