Loading .github/workflows/build.yaml +6 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,12 @@ jobs: - run: 'cat "$CHANGES_FILE"' env: CHANGES_FILE: ${{ steps.extract-changelog.outputs.output-file }} - uses: actions/upload-artifact@v4 with: name: dist path: | src/npm/*.tgz cli/fedify-cli-* - if: github.event_name == 'push' && github.ref_type == 'tag' uses: softprops/action-gh-release@v1 with: Loading CHANGES.md +35 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,13 @@ Version 1.2.13 To be released. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. Version 1.2.12 -------------- Loading Loading @@ -269,6 +276,19 @@ Released on October 31, 2024. [#118]: https://github.com/dahlia/fedify/issues/118 Version 1.1.13 -------------- Released on February 19, 2025. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. Version 1.1.12 -------------- Loading Loading @@ -570,6 +590,21 @@ Released on October 20, 2024. [#150]: https://github.com/dahlia/fedify/issues/150 Version 1.0.16 -------------- Released on February 19, 2025. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. [#210]: https://github.com/fedify-dev/fedify/issues/210 Version 1.0.15 -------------- Loading cli/init.ts +34 −13 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ import { basename, dirname, join, normalize } from "@std/path"; import { format, greaterThan, parse } from "@std/semver"; import metadata from "./deno.json" with { type: "json" }; const logger = getLogger(["fedify", "cli", "init"]); type Runtime = "deno" | "bun" | "node"; interface RuntimeDescription { Loading Loading @@ -67,11 +69,11 @@ const packageManagers: Record<PackageManager, PackageManagerDescription> = { }, }; const packageManagerAvailabilities: Record<PackageManager, boolean> = Object .fromEntries( const packageManagerLocations: Record<PackageManager, string | undefined> = Object.fromEntries( await Promise.all( (Object.keys(packageManagers) as PackageManager[]) .map(async (pm) => [pm, await isPackageManagerAvailable(pm)]), .map(async (pm) => [pm, await locatePackageManager(pm)]), ), ); Loading Loading @@ -566,8 +568,6 @@ const messageQueues: Record<MessageQueue, MessageQueueDescription> = { }, } as const; const logger = getLogger(["fedify", "cli", "init"]); export const command = new Command() .type( "runtime", Loading @@ -581,7 +581,7 @@ export const command = new Command() "package-manager", new EnumType( (Object.keys(packageManagers) as PackageManager[]).filter((pm) => packageManagerAvailabilities[pm] packageManagerLocations[pm] ), ), ) Loading Loading @@ -763,7 +763,7 @@ export const command = new Command() ); Deno.exit(1); } if (runtime === "node" && !packageManagerAvailabilities[packageManager]) { if (runtime === "node" && !packageManagerLocations[packageManager]) { console.error(`The ${packageManager} is not available on this system.`); Deno.exit(1); } Loading Loading @@ -1304,10 +1304,18 @@ async function isCommandAvailable( try { const output = await cmd.output(); const stdout = new TextDecoder().decode(output.stdout); logger.debug( "The stdout of the command {command} is: {stdout}", { command: checkCommand, stdout }, ); return outputPattern.exec(stdout.trim()) ? true : false; } catch (e) { if (e instanceof Deno.errors.NotFound) return false; throw e; } catch (error) { logger.debug( "The command {command} failed with the error: {error}", { command: checkCommand, error }, ); if (error instanceof Deno.errors.NotFound) return false; throw error; } } Loading @@ -1315,8 +1323,21 @@ function isRuntimeAvailable(runtime: Runtime): Promise<boolean> { return isCommandAvailable(runtimes[runtime]); } function isPackageManagerAvailable(pm: PackageManager): Promise<boolean> { return isCommandAvailable(packageManagers[pm]); async function locatePackageManager( pm: PackageManager, ): Promise<string | undefined> { if (await isCommandAvailable(packageManagers[pm])) { return packageManagers[pm].checkCommand[0]; } if (Deno.build.os !== "windows") return undefined; const cmd: [string, ...string[]] = [ packageManagers[pm].checkCommand[0] + ".cmd", ...packageManagers[pm].checkCommand.slice(1), ]; if (await isCommandAvailable({ ...packageManagers[pm], checkCommand: cmd })) { return cmd[0]; } return undefined; } async function addDependencies( Loading @@ -1342,7 +1363,7 @@ async function addDependencies( ); if (deps.length < 1) return; const cmd = new Deno.Command( runtime === "node" ? pm : runtime, runtime === "node" ? (packageManagerLocations[pm] ?? pm) : runtime, { args: [ "add", Loading cli/log.ts +14 −3 Original line number Diff line number Diff line import { configure, getConsoleSink, getFileSink, type LogRecord, type Sink, } from "@logtape/logtape"; import { dirname } from "@std/path"; import { AsyncLocalStorage } from "node:async_hooks"; export interface RecordingSink extends Sink { Loading Loading @@ -31,19 +33,28 @@ export function getRecordingSink(): RecordingSink { export const recordingSink = getRecordingSink(); export const logFile = Deno.env.get("FEDIFY_LOG_FILE"); if (logFile != null) { await Deno.mkdir(dirname(logFile), { recursive: true }); } await configure({ sinks: { console: getConsoleSink(), recording: recordingSink }, sinks: { console: getConsoleSink(), recording: recordingSink, file: logFile == null ? () => undefined : getFileSink(logFile), }, filters: {}, loggers: [ { category: "fedify", level: "debug", sinks: ["recording"], sinks: ["recording", "file"], }, { category: ["logtape", "meta"], level: "warning", sinks: ["console"], sinks: ["console", "file"], }, ], contextLocalStorage: new AsyncLocalStorage(), Loading cli/mod.ts +17 −6 Original line number Diff line number Diff line import { Command, CompletionsCommand, HelpCommand } from "@cliffy/command"; import { configure, getConsoleSink } from "@logtape/logtape"; import { configure, getConsoleSink, getFileSink } from "@logtape/logtape"; import { DEFAULT_CACHE_DIR, setCacheDir } from "./cache.ts"; import metadata from "./deno.json" with { type: "json" }; import { command as inbox } from "./inbox.tsx"; import { command as init } from "./init.ts"; import { recordingSink } from "./log.ts"; import { logFile, recordingSink } from "./log.ts"; import { command as lookup } from "./lookup.ts"; import { command as node } from "./node.ts"; import { command as tunnel } from "./tunnel.ts"; Loading @@ -12,26 +12,37 @@ import { command as tunnel } from "./tunnel.ts"; const command = new Command() .name("fedify") .version(metadata.version) .globalEnv( "FEDIFY_LOG_FILE=<file:file>", "An optional file to write logs to. " + "Regardless of -d/--debug option, " + "all levels of logs are written to this file. " + "Note that this does not mute console logs.", ) .globalOption("-d, --debug", "Enable debug mode.", { async action() { await configure({ sinks: { console: getConsoleSink(), recording: recordingSink }, sinks: { console: getConsoleSink(), recording: recordingSink, file: logFile == null ? () => undefined : getFileSink(logFile), }, filters: {}, loggers: [ { category: "fedify", level: "debug", sinks: ["console", "recording"], sinks: ["console", "recording", "file"], }, { category: "localtunnel", level: "debug", sinks: ["console"], sinks: ["console", "file"], }, { category: ["logtape", "meta"], level: "warning", sinks: ["console"], sinks: ["console", "file"], }, ], reset: true, Loading Loading
.github/workflows/build.yaml +6 −0 Original line number Diff line number Diff line Loading @@ -166,6 +166,12 @@ jobs: - run: 'cat "$CHANGES_FILE"' env: CHANGES_FILE: ${{ steps.extract-changelog.outputs.output-file }} - uses: actions/upload-artifact@v4 with: name: dist path: | src/npm/*.tgz cli/fedify-cli-* - if: github.event_name == 'push' && github.ref_type == 'tag' uses: softprops/action-gh-release@v1 with: Loading
CHANGES.md +35 −0 Original line number Diff line number Diff line Loading @@ -8,6 +8,13 @@ Version 1.2.13 To be released. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. Version 1.2.12 -------------- Loading Loading @@ -269,6 +276,19 @@ Released on October 31, 2024. [#118]: https://github.com/dahlia/fedify/issues/118 Version 1.1.13 -------------- Released on February 19, 2025. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. Version 1.1.12 -------------- Loading Loading @@ -570,6 +590,21 @@ Released on October 20, 2024. [#150]: https://github.com/dahlia/fedify/issues/150 Version 1.0.16 -------------- Released on February 19, 2025. - Fixed a bug where the `fedify init` command had failed to locate package managers on Windows. [[#210]] - The `fedify` command became aware of `FEDIFY_LOG_FILE` environment variable to log messages to a file. If the variable is set, the command logs messages to the file specified by the variable. [#210]: https://github.com/fedify-dev/fedify/issues/210 Version 1.0.15 -------------- Loading
cli/init.ts +34 −13 Original line number Diff line number Diff line Loading @@ -8,6 +8,8 @@ import { basename, dirname, join, normalize } from "@std/path"; import { format, greaterThan, parse } from "@std/semver"; import metadata from "./deno.json" with { type: "json" }; const logger = getLogger(["fedify", "cli", "init"]); type Runtime = "deno" | "bun" | "node"; interface RuntimeDescription { Loading Loading @@ -67,11 +69,11 @@ const packageManagers: Record<PackageManager, PackageManagerDescription> = { }, }; const packageManagerAvailabilities: Record<PackageManager, boolean> = Object .fromEntries( const packageManagerLocations: Record<PackageManager, string | undefined> = Object.fromEntries( await Promise.all( (Object.keys(packageManagers) as PackageManager[]) .map(async (pm) => [pm, await isPackageManagerAvailable(pm)]), .map(async (pm) => [pm, await locatePackageManager(pm)]), ), ); Loading Loading @@ -566,8 +568,6 @@ const messageQueues: Record<MessageQueue, MessageQueueDescription> = { }, } as const; const logger = getLogger(["fedify", "cli", "init"]); export const command = new Command() .type( "runtime", Loading @@ -581,7 +581,7 @@ export const command = new Command() "package-manager", new EnumType( (Object.keys(packageManagers) as PackageManager[]).filter((pm) => packageManagerAvailabilities[pm] packageManagerLocations[pm] ), ), ) Loading Loading @@ -763,7 +763,7 @@ export const command = new Command() ); Deno.exit(1); } if (runtime === "node" && !packageManagerAvailabilities[packageManager]) { if (runtime === "node" && !packageManagerLocations[packageManager]) { console.error(`The ${packageManager} is not available on this system.`); Deno.exit(1); } Loading Loading @@ -1304,10 +1304,18 @@ async function isCommandAvailable( try { const output = await cmd.output(); const stdout = new TextDecoder().decode(output.stdout); logger.debug( "The stdout of the command {command} is: {stdout}", { command: checkCommand, stdout }, ); return outputPattern.exec(stdout.trim()) ? true : false; } catch (e) { if (e instanceof Deno.errors.NotFound) return false; throw e; } catch (error) { logger.debug( "The command {command} failed with the error: {error}", { command: checkCommand, error }, ); if (error instanceof Deno.errors.NotFound) return false; throw error; } } Loading @@ -1315,8 +1323,21 @@ function isRuntimeAvailable(runtime: Runtime): Promise<boolean> { return isCommandAvailable(runtimes[runtime]); } function isPackageManagerAvailable(pm: PackageManager): Promise<boolean> { return isCommandAvailable(packageManagers[pm]); async function locatePackageManager( pm: PackageManager, ): Promise<string | undefined> { if (await isCommandAvailable(packageManagers[pm])) { return packageManagers[pm].checkCommand[0]; } if (Deno.build.os !== "windows") return undefined; const cmd: [string, ...string[]] = [ packageManagers[pm].checkCommand[0] + ".cmd", ...packageManagers[pm].checkCommand.slice(1), ]; if (await isCommandAvailable({ ...packageManagers[pm], checkCommand: cmd })) { return cmd[0]; } return undefined; } async function addDependencies( Loading @@ -1342,7 +1363,7 @@ async function addDependencies( ); if (deps.length < 1) return; const cmd = new Deno.Command( runtime === "node" ? pm : runtime, runtime === "node" ? (packageManagerLocations[pm] ?? pm) : runtime, { args: [ "add", Loading
cli/log.ts +14 −3 Original line number Diff line number Diff line import { configure, getConsoleSink, getFileSink, type LogRecord, type Sink, } from "@logtape/logtape"; import { dirname } from "@std/path"; import { AsyncLocalStorage } from "node:async_hooks"; export interface RecordingSink extends Sink { Loading Loading @@ -31,19 +33,28 @@ export function getRecordingSink(): RecordingSink { export const recordingSink = getRecordingSink(); export const logFile = Deno.env.get("FEDIFY_LOG_FILE"); if (logFile != null) { await Deno.mkdir(dirname(logFile), { recursive: true }); } await configure({ sinks: { console: getConsoleSink(), recording: recordingSink }, sinks: { console: getConsoleSink(), recording: recordingSink, file: logFile == null ? () => undefined : getFileSink(logFile), }, filters: {}, loggers: [ { category: "fedify", level: "debug", sinks: ["recording"], sinks: ["recording", "file"], }, { category: ["logtape", "meta"], level: "warning", sinks: ["console"], sinks: ["console", "file"], }, ], contextLocalStorage: new AsyncLocalStorage(), Loading
cli/mod.ts +17 −6 Original line number Diff line number Diff line import { Command, CompletionsCommand, HelpCommand } from "@cliffy/command"; import { configure, getConsoleSink } from "@logtape/logtape"; import { configure, getConsoleSink, getFileSink } from "@logtape/logtape"; import { DEFAULT_CACHE_DIR, setCacheDir } from "./cache.ts"; import metadata from "./deno.json" with { type: "json" }; import { command as inbox } from "./inbox.tsx"; import { command as init } from "./init.ts"; import { recordingSink } from "./log.ts"; import { logFile, recordingSink } from "./log.ts"; import { command as lookup } from "./lookup.ts"; import { command as node } from "./node.ts"; import { command as tunnel } from "./tunnel.ts"; Loading @@ -12,26 +12,37 @@ import { command as tunnel } from "./tunnel.ts"; const command = new Command() .name("fedify") .version(metadata.version) .globalEnv( "FEDIFY_LOG_FILE=<file:file>", "An optional file to write logs to. " + "Regardless of -d/--debug option, " + "all levels of logs are written to this file. " + "Note that this does not mute console logs.", ) .globalOption("-d, --debug", "Enable debug mode.", { async action() { await configure({ sinks: { console: getConsoleSink(), recording: recordingSink }, sinks: { console: getConsoleSink(), recording: recordingSink, file: logFile == null ? () => undefined : getFileSink(logFile), }, filters: {}, loggers: [ { category: "fedify", level: "debug", sinks: ["console", "recording"], sinks: ["console", "recording", "file"], }, { category: "localtunnel", level: "debug", sinks: ["console"], sinks: ["console", "file"], }, { category: ["logtape", "meta"], level: "warning", sinks: ["console"], sinks: ["console", "file"], }, ], reset: true, Loading