-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs!: user manual + 0.3.0-rc.1 #106
Conversation
📝 WalkthroughWalkthroughThis pull request includes extensive modifications across multiple files, primarily focusing on updates to the Changes
Possibly related PRs
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 19
🧹 Outside diff range and nitpick comments (111)
examples/env_vars/ghjk.ts (1)
20-20
: Consider caching the evaluation result.Since this variable is evaluated through a shell command, frequent access could impact performance. If the values of A and B don't change frequently during runtime, consider caching the result.
Example approach:
let cachedC: string | null = null; let lastA: string | null = null; let lastB: string | null = null; .var("C", ($) => { if (cachedC && lastA === $.A && lastB === $.B) { return cachedC; } lastA = $.A; lastB = $.B; cachedC = $`echo C [$A, $B]`.text(); return cachedC; })host/init/template.ts (5)
1-5
: Consider removing@ts-nocheck
in favor of proper type checking.While the file is Deno-based, it's generally better to properly type your code rather than disable type checking entirely. This helps catch potential issues early and improves maintainability.
Also, the commented-out import on line 4 should either be removed if unused or uncommented if needed. Having commented code can lead to confusion about what's actually being used.
6-9
: Document the implications ofenableRuntimes
.The comment about allowing usage of ports that depend on node/python could be more descriptive. Consider adding a more detailed comment explaining:
- What specific runtimes are enabled
- When this flag should be enabled
- Any performance or security implications
- // allows usage of ports that depend on node/python + // When enabled, allows execution of Node.js and Python-dependent ports. + // Enable this if you need to use ports that require these runtimes. + // Note: This may impact startup time and security surface area. // enableRuntimes: true,
11-12
: Enhance the export documentation.While the comment indicates this export is necessary for ts ghjkfiles, it would be helpful to explain what
sophon
is and how it should be used.-// This export is necessary for ts ghjkfiles +// Export sophon instance for TypeScript ghjkfiles. +// sophon provides type-safe access to ghjk's configuration and task management. export const sophon = ghjk.sophon;
14-18
: Clean up or document commented installation code.The commented port installations should either be:
- Removed if they're not intended to be used
- Uncommented if they're required
- Better documented if they're meant to serve as examples
ghjk.install( - // install ports into the main env - // ports.node(), - // ports.cpy_bs(), + // Example port installations: + // ports.node(), // Enables Node.js functionality + // ports.cpy_bs(), // Enables Python bootstrapping );
1-22
: Add JSDoc documentation for the template file.As this is a template file that others will likely use as a reference, consider adding comprehensive JSDoc documentation at the file level to explain its purpose and usage.
+/** + * @fileoverview Template for ghjk initialization. + * This file serves as a starting point for creating ghjk configuration files. + * It demonstrates basic setup, task creation, and port installation. + * + * @example + * // Basic usage: + * import { sophon } from "./template.ts"; + * await ghjk.task("greet").run("world"); + */ // @ts-nocheck: Deno basedmodules/ports/std_runtime.ts (2)
1-2
: Consider using JSDoc style documentation.The current documentation uses
//!
style which is more common in Rust. For better TypeScript/JavaScript compatibility and tooling support, consider using JSDoc style documentation.-//! The list of ports enabled when enableRuntimes is used on a ghjkfile configuration. +/** The list of ports enabled when enableRuntimes is used on a ghjkfile configuration. */
3-6
: Consider optimizing imports.Instead of importing everything with
*
, consider importing only the specific functions needed. This can lead to better tree-shaking and clearer dependencies.-import * as cpy_bs from "../../ports/cpy_bs.ts"; -import * as node from "../../ports/node.ts"; -import * as rust from "../../ports/rust.ts"; -import * as asdf_plugin_git from "../../ports/asdf_plugin_git.ts"; +import { default as cpy_bs } from "../../ports/cpy_bs.ts"; +import { default as node } from "../../ports/node.ts"; +import { default as rust } from "../../ports/rust.ts"; +import { buildDep as asdfPluginGitBuildDep } from "../../ports/asdf_plugin_git.ts";ports/cmake.ts (1)
17-22
: Enhance example with version specification and explanation.While the example is clear, it could be more helpful by:
- Adding a comment explaining what
enableRuntimes
does- Including an example of version specification
Consider updating the example:
* ```typescript + * // Enable both macOS (pip) and non-macOS (asdf) runtime dependencies * ghjk.config({ * enableRuntimes: true, * }); * - * ghjk.install(ports.cmake()); + * // Install specific CMake version + * ghjk.install(ports.cmake({ version: "3.26.0" })); * ```ports/dummy.ts (2)
Line range hint
52-62
: Add Windows compatibility and improve error handlingThe current implementation has several platform-specific assumptions:
- Uses Unix-style shebang (
#!/bin/sh
)- Sets Unix file permissions (0o700)
- No Windows-specific error handling
Consider this implementation:
override async download(args: DownloadArgs) { const conf = confValidator.parse(args.config); - // TODO: windows suport - await $.path(args.downloadPath).join("bin", "dummy").writeText( - `#!/bin/sh -echo ${conf.output ?? "dummy hey"}`, - { - mode: 0o700, - }, - ); + try { + const isWindows = Deno.build.os === "windows"; + const binPath = $.path(args.downloadPath).join("bin"); + const scriptPath = binPath.join(`dummy${isWindows ? ".cmd" : ""}`); + + await binPath.mkdir({ recursive: true }); + + const content = isWindows + ? `@echo off\necho ${conf.output ?? "dummy hey"}` + : `#!/bin/sh\necho ${conf.output ?? "dummy hey"}`; + + await scriptPath.writeText(content); + + if (!isWindows) { + await Deno.chmod(scriptPath.toString(), 0o700); + } + } catch (error) { + throw new Error(`Failed to create dummy script: ${error.message}`); + }
Line range hint
64-68
: Add error handling and path validationThe current implementation lacks error handling and could be subject to race conditions between removal and copy operations.
Consider this safer implementation:
override async install(args: InstallArgs) { - const installPath = $.path(args.installPath); - await $.removeIfExists(installPath); - await std_fs.copy(args.downloadPath, args.installPath); + try { + const installPath = $.path(args.installPath); + const downloadPath = $.path(args.downloadPath); + + // Validate paths + if (!await downloadPath.exists()) { + throw new Error("Download path does not exist"); + } + + // Atomic replacement + if (await installPath.exists()) { + const tempPath = $.path(`${args.installPath}.tmp`); + await std_fs.copy(args.downloadPath, tempPath.toString()); + await $.removeIfExists(installPath); + await Deno.rename(tempPath.toString(), installPath.toString()); + } else { + await std_fs.copy(args.downloadPath, args.installPath); + } + } catch (error) { + throw new Error(`Installation failed: ${error.message}`); + }ports/earthly.ts (3)
Line range hint
34-59
: LGTM! Consider extracting the architecture mapping to a constant.The implementation correctly handles platform-specific naming and permissions. The architecture mapping logic is accurate but could be more maintainable.
Consider extracting the architecture mapping to a constant for better maintainability:
+ const ARCH_MAPPING: Record<string, string> = { + "x86_64": "amd64", + "aarch64": "arm64", + }; override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; - let arch; - switch (platform.arch) { - case "x86_64": - arch = "amd64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported arch: ${platform.arch}`); - } + const arch = ARCH_MAPPING[platform.arch]; + if (!arch) { + throw new Error(`unsupported arch: ${platform.arch}`); + }
Line range hint
60-69
: Add error handling for file operations.While the implementation is correct, it lacks error handling for file operations which could fail due to permissions or disk space issues.
Consider adding error handling:
override async install(args: InstallArgs) { const installPath = $.path(args.installPath); + try { if (await installPath.exists()) { await installPath.remove({ recursive: true }); } await std_fs.copy( args.downloadPath, installPath.join("bin").toString(), ); + } catch (error) { + throw new Error( + `Failed to install Earthly: ${error instanceof Error ? error.message : String(error)}` + ); + } }
Based on the verification results, I can now provide a final response:
downloadUrls
andinstall
methods are correctly implemented withoverride
keyword in most ports, but a few inconsistencies found
terraform.ts
,rustup.ts
, andnode.ts
are missing theoverride
keyword fordownloadUrls
methodpoetry.ts
is missing theoverride
keyword forinstall
method🔗 Analysis chain
Line range hint
34-69
: Verify consistent method implementations across ports.Let's ensure all port files consistently implement these methods with the override keyword.
Let me generate another verification script to check specifically for the
override
keyword usage in these methods, as the previous results don't clearly show this aspect.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for consistent implementation of downloadUrls and install methods across port files # Test 1: Find all port files and check for downloadUrls method implementation echo "Checking downloadUrls implementations:" ast-grep --pattern 'class $_ extends $_ { $$$ downloadUrls($_) { $$$ } $$$ }' # Test 2: Find all port files and check for install method implementation echo -e "\nChecking install implementations:" ast-grep --pattern 'class $_ extends $_ { $$$ install($_) { $$$ } $$$ }'Length of output: 12549
Script:
#!/bin/bash # Check for methods with and without override keyword echo "Checking downloadUrls with override:" ast-grep --pattern 'class $_ extends $_ { $$$ override downloadUrls($_) { $$$ } $$$ }' echo -e "\nChecking downloadUrls without override:" ast-grep --pattern 'class $_ extends $_ { $$$ downloadUrls($_) { $$$ } $$$ }' echo -e "\nChecking install with override:" ast-grep --pattern 'class $_ extends $_ { $$$ override install($_) { $$$ } $$$ }' echo -e "\nChecking install without override:" ast-grep --pattern 'class $_ extends $_ { $$$ install($_) { $$$ } $$$ }'Length of output: 155016
ports/poetry.ts (2)
63-65
: LGTM! Consider adding return type annotation.The
override
keyword addition is correct. For consistency withlatestStable
, consider adding an explicit return type annotation.- override download(args: DownloadArgs) { + override download(args: DownloadArgs): Promise<void> {
Line range hint
29-32
: Consider documenting the config transformation behavior.The
toPipiConfig
function plays a crucial role in transforming configurations. Consider adding JSDoc comments to explain the transformation logic and its purpose.+/** + * Transforms a Poetry configuration into a Pipi-compatible format. + * @param config The Poetry-specific configuration + * @returns A configuration object compatible with Pipi port + */ const toPipiConfig = (config: InstallConfigLiteX) => ({ports/deno_ghrel.ts (1)
Line range hint
63-74
: Consider adding error handling for file operations.While the installation flow is correct, the file operations could benefit from additional error handling to gracefully handle potential failures during unarchiving or directory operations.
Consider wrapping critical operations in try-catch blocks:
override async install(args: InstallArgs) { - const [{ name: fileName }] = this.downloadUrls(args); - const fileDwnPath = std_path.resolve(args.downloadPath, fileName); - await unarchive(fileDwnPath, args.tmpDirPath); - - const installPath = $.path(args.installPath); - if (await installPath.exists()) { - await installPath.remove({ recursive: true }); - } - await $.path(args.tmpDirPath) - .rename(await installPath.join("bin").ensureDir()); + try { + const [{ name: fileName }] = this.downloadUrls(args); + const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + await unarchive(fileDwnPath, args.tmpDirPath); + + const installPath = $.path(args.installPath); + if (await installPath.exists()) { + await installPath.remove({ recursive: true }); + } + await $.path(args.tmpDirPath) + .rename(await installPath.join("bin").ensureDir()); + } catch (error) { + throw new Error(`Failed to install Deno: ${error.message}`); + } }ports/opentofu_ghrel.ts (2)
Line range hint
40-63
: Consider refactoring platform mapping for better maintainability.The architecture mapping could be made more maintainable using a lookup object.
Consider this approach:
- let arch; - switch (platform.arch) { - case "x86_64": - arch = "amd64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported platform: ${platform}`); - } + const archMap: Record<string, string> = { + x86_64: "amd64", + aarch64: "arm64", + }; + const arch = archMap[platform.arch]; + if (!arch) { + throw new Error(`unsupported platform: ${platform}`); + }
Line range hint
68-83
: Consider adding error handling and installation validation.The installation process could benefit from additional error handling and validation.
Consider these improvements:
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + try { await unarchive(fileDwnPath, args.tmpDirPath); const installPath = $.path(args.installPath); if (await installPath.exists()) { await installPath.remove({ recursive: true }); } await std_fs.copy( args.tmpDirPath, installPath.join("bin").toString(), ); + + // Validate installation + const binPath = installPath.join("bin", "tofu"); + if (!(await binPath.exists())) { + throw new Error("Installation validation failed: Binary not found"); + } + } catch (error) { + throw new Error(`Installation failed: ${error.message}`); + } }ports/jq_ghrel.ts (3)
Line range hint
41-66
: Consider improving error handling and file permissions.Two suggestions for improvement:
- The error message for unsupported platforms could be more descriptive by including the list of supported platforms.
- The file mode
0o700
(rwx------) is quite restrictive. Consider using0o755
(rwxr-xr-x) which is more common for executable binaries, allowing other users to execute the binary while maintaining write protection.- throw new Error(`unsupported platform: ${serializePlatform(platform)}`); + throw new Error( + `Unsupported platform: ${serializePlatform(platform)}. ` + + `Supported platforms: linux/darwin (aarch64/x86_64), windows (x86_64)` + ); - .map((out) => ({ ...out, mode: 0o700 })); + .map((out) => ({ ...out, mode: 0o755 }));
Line range hint
67-83
: Add error handling for file operations.The installation process could benefit from additional error handling and validation:
- Add try-catch blocks around file operations
- Validate the successful installation by checking file existence and permissions
- Consider adding cleanup in case of partial installation failure
override async install(args: InstallArgs) { const installPath = $.path(args.installPath); - await $.removeIfExists(installPath); + try { + await $.removeIfExists(installPath); - const [{ name: fileName }] = this.downloadUrls(args); - const fileDwnPath = $.path(args.downloadPath).resolve(fileName); + const [{ name: fileName }] = this.downloadUrls(args); + const fileDwnPath = $.path(args.downloadPath).resolve(fileName); + if (!await fileDwnPath.exists()) { + throw new Error(`Downloaded file not found: ${fileDwnPath}`); + } - await fileDwnPath.copy( - (await installPath - .join("bin") - .ensureDir()) - .join( - args.platform.os == "windows" ? "jq.exe" : "jq", - ), - ); + const binDir = await installPath.join("bin").ensureDir(); + const destPath = binDir.join( + args.platform.os == "windows" ? "jq.exe" : "jq" + ); + await fileDwnPath.copy(destPath); + + // Validate installation + if (!await destPath.exists()) { + throw new Error("Installation failed: Binary not found at destination"); + } + } catch (error) { + // Cleanup on failure + await $.removeIfExists(installPath); + throw new Error(`Installation failed: ${error.message}`); + } }
Line range hint
1-40
: Add class documentation and version compatibility information.Consider adding JSDoc documentation to improve maintainability:
- Document the purpose of the port
- List supported jq versions
- Include usage examples
+/** + * Port implementation for installing jq binary from GitHub releases. + * + * Supports: + * - OS: Linux, macOS, Windows + * - Arch: x86_64 (amd64), aarch64 (arm64) + * - Versions: All official jq releases + * + * @example + * ```ts + * const port = new Port(); + * await port.install({ + * installPath: "/usr/local", + * platform: { os: "linux", arch: "x86_64" }, + * installVersion: "1.6" + * }); + * ``` + */ export class Port extends GithubReleasePort {ports/protoc.ts (3)
Line range hint
36-68
: Fix incorrect architecture mapping for ARM64.The architecture mapping for aarch64 uses "aarch_64" which appears to be incorrect. According to protoc's release artifacts, it should be "aarch64" (without underscore).
Apply this fix:
case "aarch64": - arch = "aarch_64"; + arch = "aarch64"; break;Consider refactoring platform validation for better maintainability.
The current implementation uses nested switch statements for platform validation. This could be simplified using a mapping object.
Consider refactoring to:
const PLATFORM_MAPPING = { os: { linux: "linux", darwin: "osx", }, arch: { x86_64: "x86_64", aarch64: "aarch64", }, } as const; override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; const os = PLATFORM_MAPPING.os[platform.os]; if (!os) { throw new Error(`Unsupported OS: ${platform.os}. Supported: ${Object.keys(PLATFORM_MAPPING.os).join(", ")}`); } const arch = PLATFORM_MAPPING.arch[platform.arch]; if (!arch) { throw new Error(`Unsupported architecture: ${platform.arch}. Supported: ${Object.keys(PLATFORM_MAPPING.arch).join(", ")}`); } return [ this.releaseArtifactUrl( installVersion, `protoc-${installVersion.replace(/^v/, "")}-${os}-${arch}.zip`, ), ].map(dwnUrlOut); }
Line range hint
69-85
: Add error handling and validation for file operations.The installation process lacks proper error handling and validation for critical file operations. This could lead to incomplete installations or silent failures.
Consider adding these improvements:
override async install(args: InstallArgs) { try { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = $.path(args.downloadPath).join(fileName); if (!await fileDwnPath.exists()) { throw new Error(`Download file not found: ${fileDwnPath}`); } await unarchive(fileDwnPath.toString(), args.tmpDirPath); // Validate extraction const extractedFiles = await std_fs.readDir(args.tmpDirPath); if (extractedFiles.length === 0) { throw new Error('Archive extraction produced no files'); } const installPath = $.path(args.installPath); if (await installPath.exists()) { try { await installPath.remove({ recursive: true }); } catch (e) { throw new Error(`Failed to remove existing installation: ${e.message}`); } } await std_fs.copy( args.tmpDirPath, args.installPath, ); // Verify installation if (!await $.path(args.installPath).exists()) { throw new Error('Installation verification failed'); } } catch (error) { throw new Error(`Installation failed: ${error.message}`); } }
Line range hint
1-85
: Add JSDoc documentation for supported platforms and version requirements.The implementation would benefit from clear documentation about supported platforms and version requirements.
Consider adding documentation:
/** * Protocol Buffers (protoc) installer port. * * Supported platforms: * - Linux (x86_64, aarch64) * - macOS (x86_64, aarch64) * * @example * ```typescript * const port = new Port(); * await port.install({ * installVersion: "v21.0", * platform: { os: "linux", arch: "x86_64" }, * // ... other args * }); * ``` */ export class Port extends GithubReleasePort {ports/temporal_cli.ts (2)
Line range hint
36-57
: LGTM with suggestions for improvement.The architecture mapping and URL construction look correct. Consider these improvements:
- Move architecture mapping to a shared constant/enum for reusability
- Add input validation for
installVersion
to ensure it follows semver formatExample implementation:
const ARCH_MAPPING = { "x86_64": "amd64", "aarch64": "arm64", } as const; override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; const arch = ARCH_MAPPING[platform.arch]; if (!arch) { throw new Error(`unsupported arch: ${platform.arch}`); } const version = installVersion.replace(/^v/, ""); if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version)) { throw new Error(`invalid version format: ${installVersion}`); } return [ this.releaseArtifactUrl( installVersion, `temporal_cli_${version}_${platform.os}_${arch}.tar.gz`, ), ].map(dwnUrlOut); }
Line range hint
58-82
: Add error handling and atomic installation.The installation logic needs more robust error handling and atomic installation to prevent inconsistent states.
Consider these improvements:
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); try { await unarchive(fileDwnPath, args.tmpDirPath); const tmpDir = $.path(args.tmpDirPath); const binDir = await tmpDir.join("bin").ensureDir(); const exeSuffix = args.platform.os === "windows" ? ".exe" : ""; // Move executables for (const fileName of ["temporal"]) { const srcFile = tmpDir.join(fileName + exeSuffix); if (!await srcFile.exists()) { throw new Error(`Missing expected file: ${fileName}${exeSuffix}`); } await srcFile.renameToDir(binDir); } // Atomic installation using rename const installPath = $.path(args.installPath); const tempInstallPath = $.path(args.installPath + '.new'); if (await tempInstallPath.exists()) { await tempInstallPath.remove({ recursive: true }); } await tmpDir.rename(tempInstallPath); if (await installPath.exists()) { await installPath.remove({ recursive: true }); } await tempInstallPath.rename(installPath); } catch (error) { // Cleanup on failure const tempInstallPath = $.path(args.installPath + '.new'); if (await tempInstallPath.exists()) { await tempInstallPath.remove({ recursive: true }); } throw error; } }modules/ports/ambient.ts (1)
51-53
: Enhance the no-op documentation.While the
override
keyword addition is correct, consider improving the comment to better explain why this method is a no-op.- override async download() { - // no op - } + override async download() { + // No download required for ambient ports as they use existing system binaries + }ports/pnpm.ts (2)
Line range hint
34-75
: Enhance error messages and improve maintainability.Consider the following improvements:
- Make error messages more descriptive by including supported values
- Extract platform mappings into constants for better maintainability
+ const ARCH_MAPPING = { + x86_64: "x64", + aarch64: "arm64", + } as const; + + const OS_MAPPING = { + linux: "linuxstatic", + darwin: "macos", + windows: "win", + } as const; override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; - let arch; - switch (platform.arch) { - case "x86_64": - arch = "x64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported arch: ${platform.arch}`); - } + const arch = ARCH_MAPPING[platform.arch]; + if (!arch) { + throw new Error( + `Unsupported architecture: ${platform.arch}. Supported: ${Object.keys(ARCH_MAPPING).join(", ")}` + ); + } - let os; let ext = ""; - switch (platform.os) { - case "linux": - os = "linuxstatic"; - break; - case "darwin": - os = "macos"; - break; - case "windows": - os = "win"; - ext = ".exe"; - break; - default: - throw new Error(`unsupported: ${platform}`); - } + const os = OS_MAPPING[platform.os]; + if (!os) { + throw new Error( + `Unsupported OS: ${platform.os}. Supported: ${Object.keys(OS_MAPPING).join(", ")}` + ); + } + if (platform.os === "windows") { + ext = ".exe"; + }
Line range hint
77-91
: Add error handling for filesystem operations.The installation process should handle potential filesystem errors and validate the successful copy operation.
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const installPath = $.path(args.installPath); + try { if (await installPath.exists()) { await installPath.remove({ recursive: true }); } const binDir = await installPath.join("bin").ensureDir(); const sourcePath = $.path(args.downloadPath).join(fileName).toString(); const targetPath = binDir.join(fileName).toString(); await std_fs.copy(sourcePath, targetPath); + // Verify successful copy + const fileExists = await std_fs.exists(targetPath); + if (!fileExists) { + throw new Error("Installation failed: Binary not found after copy"); + } + } catch (error) { + throw new Error(`Installation failed: ${error.message}`); + } }docs/known-issues.md (2)
24-28
: Consider tracking and prioritizing the token leakage security risk.The current workaround of manually cleaning tokens from the lockfile is error-prone and could lead to accidental token exposure. This security risk should be tracked and prioritized for a more robust solution.
Some potential improvements to consider:
- Implement automatic token redaction in the lockfile
- Store sensitive values in a separate, git-ignored file
- Add pre-commit hooks to detect and prevent token commits
Would you like me to:
- Open a GitHub issue to track this security concern?
- Propose a detailed technical solution for any of the suggested improvements?
29-33
: Enhance command block visibility.Consider improving the command block formatting for better visibility and copy-paste convenience:
-```bash -rm .ghjk/lock.json -# this command will re-resolve all ports -ghjk p resolve -``` +```shell +# Remove the existing lockfile +$ rm .ghjk/lock.json + +# Re-resolve all ports +$ ghjk p resolve +``` </blockquote></details> <details> <summary>ports/act.ts (3)</summary><blockquote> Line range hint `36-75`: **Consider improving error handling and maintainability.** The platform-specific logic could be enhanced in several ways: 1. Error messages could be more descriptive by including supported platforms 2. Platform mappings could be centralized into constants Consider applying these improvements: ```diff + const ARCH_MAPPING = { + x86_64: "x86_64", + aarch64: "arm64", + } as const; + + const OS_MAPPING = { + linux: { os: "Linux", ext: "tar.gz" }, + darwin: { os: "Darwin", ext: "tar.gz" }, + windows: { os: "Windows", ext: "zip" }, + } as const; override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; - let arch; - switch (platform.arch) { - case "x86_64": - arch = "x86_64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported: ${platform}`); - } + const arch = ARCH_MAPPING[platform.arch]; + if (!arch) { + throw new Error( + `Unsupported architecture: ${platform.arch}. Supported: ${ + Object.keys(ARCH_MAPPING).join(", ") + }` + ); + } - let os; - let ext; - switch (platform.os) { - case "linux": - os = "Linux"; - ext = "tar.gz"; - break; - case "darwin": - os = "Darwin"; - ext = "tar.gz"; - break; - case "windows": - os = "Windows"; - ext = "zip"; - break; - default: - throw new Error(`unsupported: ${platform}`); - } + const osMapping = OS_MAPPING[platform.os]; + if (!osMapping) { + throw new Error( + `Unsupported OS: ${platform.os}. Supported: ${ + Object.keys(OS_MAPPING).join(", ") + }` + ); + } return [ this.releaseArtifactUrl( installVersion, - `${this.repoName}_${os}_${arch}.${ext}`, + `${this.repoName}_${osMapping.os}_${arch}.${osMapping.ext}`, ), ].map(dwnUrlOut); }
Line range hint
76-96
: Add error handling for file operations.The installation process lacks proper error handling and validation steps.
Consider enhancing the error handling:
+ const BINARY_NAME = "act"; override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + try { await unarchive(fileDwnPath, args.tmpDirPath); + } catch (error) { + throw new Error(`Failed to unarchive ${fileName}: ${error.message}`); + } const tmpDir = $.path(args.tmpDirPath); - const binDir = await tmpDir.join("bin").ensureDir(); + const binDir = await tmpDir.join("bin").ensureDir().catch((error) => { + throw new Error(`Failed to create bin directory: ${error.message}`); + }); for ( - const fileName of ["act"] + const fileName of [BINARY_NAME] ) { await tmpDir.join( args.platform.os == "windows" ? fileName + ".exe" : fileName, - ).renameToDir(binDir); + ).renameToDir(binDir).catch((error) => { + throw new Error(`Failed to move binary to bin directory: ${error.message}`); + }); } const installPath = $.path(args.installPath); if (await installPath.exists()) { - await installPath.remove({ recursive: true }); + await installPath.remove({ recursive: true }).catch((error) => { + throw new Error(`Failed to remove existing installation: ${error.message}`); + }); } - await tmpDir.rename(installPath); + await tmpDir.rename(installPath).catch((error) => { + throw new Error(`Failed to rename temporary directory: ${error.message}`); + }); }
Line range hint
1-35
: Add JSDoc documentation for better maintainability.The class and its methods would benefit from comprehensive documentation.
Consider adding documentation:
+ /** + * Port implementation for the nektos/act GitHub Actions runner + * @see https://github.com/nektos/act + */ export class Port extends GithubReleasePort { repoOwner = "nektos"; repoName = "act"; + /** + * Generates download URLs for the act binary based on platform architecture + * @param args Download arguments containing platform and version information + * @returns Array of download URLs with output paths + * @throws Error if platform or architecture is unsupported + */ override downloadUrls(args: DownloadArgs) { + /** + * Installs the act binary to the specified location + * @param args Installation arguments containing paths and platform information + * @throws Error if installation steps fail + */ override async install(args: InstallArgs) {ghjk.ts (3)
11-11
: Consider extracting the version number into a constant.For better maintainability and consistency, consider extracting "3.12.7" into a constant at the top of the file, similar to how
DENO_VERSION
is managed.+ const CPY_BS_VERSION = "3.12.7"; config({ defaultBaseEnv: "test", enableRuntimes: true, - allowedBuildDeps: [ports.cpy_bs({ version: "3.12.7" })], + allowedBuildDeps: [ports.cpy_bs({ version: CPY_BS_VERSION })], });
45-54
: Add comments explaining regex patterns.The regex patterns for documentation files are complex. Consider adding comments to explain what each pattern matches and updates.
"./docs/*.md": [ [ + // Updates version in URLs like ".../metatypedev/ghjk/v0.2.0/..." /(.*\/metatypedev\/ghjk\/v)[^/]*(\/.*)/, GHJK_VERSION, ], [ + // Updates version in environment variable declarations /(GHJK_VERSION\s*=\s*v)[^\s]*(.*)/, GHJK_VERSION, ], ],
1-2
: Consider removing @ts-nocheck.The
@ts-nocheck
directive might hide potential type issues. Consider:
- Addressing the type issues that necessitated this directive
- Using more specific
@ts-ignore
comments for specific lines if neededports/terraform.ts (3)
Line range hint
13-13
: Address the TODO comment regarding port exports validation.The TODO comment suggests a need for comprehensive validation of exports across all ports. This is important for ensuring consistent port behavior and preventing runtime issues.
Would you like me to help implement these sanity checks? I can:
- Generate a test suite that validates common port interface requirements
- Create a utility function to verify export consistency
- Open a GitHub issue to track this task
Line range hint
44-48
: Add null check for version list.The method assumes there will always be a stable version available and uses the non-null assertion operator (!). This could lead to runtime errors if no stable version is found.
Consider adding a null check:
override async latestStable() { const all = await this.listAll(); - return all.findLast((str) => !str.match(/-/))!; + const latest = all.findLast((str) => !str.match(/-/)); + if (!latest) { + throw new Error("No stable version found"); + } + return latest; }
Line range hint
78-92
: Enhance error handling for file system operations.While the installation process follows a safe pattern, the file system operations could benefit from additional error handling to ensure atomicity and cleanup on failure.
Consider wrapping the operations in a try-catch block:
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + try { await unarchive(fileDwnPath, args.tmpDirPath); const installPath = $.path(args.installPath); if (await installPath.exists()) { await installPath.remove({ recursive: true }); } await std_fs.move( args.tmpDirPath, (await installPath.ensureDir()).join("bin").toString(), ); + } catch (error) { + // Clean up temporary files if they exist + const tmpDir = $.path(args.tmpDirPath); + if (await tmpDir.exists()) { + await tmpDir.remove({ recursive: true }); + } + throw error; + } }ports/cargo-binstall.ts (3)
Line range hint
36-70
: LGTM with suggestions for version handling.The architecture and OS handling is robust with proper error handling. Consider making the version string manipulation more explicit:
- installVersion.match(/^v/) ? installVersion : `v${installVersion}`, + installVersion.startsWith('v') ? installVersion : `v${installVersion}`,
Line range hint
52-53
: TODO: Support for Ubuntu/Debian versions needs to be addressed.The comment indicates a need for Ubuntu/Debian version support. This could impact compatibility for users on these distributions.
Would you like me to help create a GitHub issue to track this enhancement? I can provide a detailed proposal for implementing distribution-specific package handling.
Line range hint
71-91
: Add error handling for file operations and consider backup strategy.While the installation logic is sound, there are some areas that could be improved:
- Add error handling for file operations:
override async install(args: InstallArgs) { + try { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); await unarchive(fileDwnPath, args.tmpDirPath); const tmpDir = $.path(args.tmpDirPath); const binDir = await tmpDir.join("bin").ensureDir(); for ( const fileName of ["cargo-binstall", "detect-targets", "detect-wasi"] ) { + if (!await tmpDir.join(fileName).exists()) { + throw new Error(`Required binary ${fileName} not found in archive`); + } await tmpDir.join(fileName).renameToDir(binDir); } const installPath = $.path(args.installPath); if (await installPath.exists()) { + const backupPath = `${args.installPath}_backup_${Date.now()}`; + await installPath.rename(backupPath); } await tmpDir.rename(installPath); + } catch (error) { + throw new Error(`Installation failed: ${error.message}`); + } }ports/mold.ts (1)
Line range hint
65-98
: Consider improving error handling and type safety.While the implementation is functional, there are several areas that could be enhanced:
- Add error handling for the tar extraction command
- Make the directory existence check more specific
- Add error handling for symlink creation
- Use proper type assertion or validation for the config
Consider applying these improvements:
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + try { await $`${ depExecShimPath(std_ports.tar_aa, "tar", args.depArts) } xf ${fileDwnPath} --directory=${args.tmpDirPath}`; + } catch (error) { + throw new Error(`Failed to extract archive: ${error.message}`); + } const installPath = $.path(args.installPath); - if (await installPath.exists()) { + if (await installPath.exists() && (await installPath.stat()).isDirectory) { await installPath.remove({ recursive: true }); } const dirs = []; for await ( const entry of std_fs.expandGlob( std_path.joinGlobs([args.tmpDirPath, "*"]), ) ) { dirs.push(entry); } if (dirs.length != 1 || !dirs[0].isDirectory) { throw new Error("unexpected archive contents"); } await std_fs.copy( dirs[0].path, args.installPath, ); - if ((args.config as unknown as MoldInstallConfig).replaceLd) { + const config = args.config as MoldInstallConfig; + if (config?.replaceLd) { + try { await installPath.join("bin", "ld") .symlinkTo(installPath.join("bin", "mold").toString(), { kind: "relative", }); + } catch (error) { + throw new Error(`Failed to create ld symlink: ${error.message}`); + } } }ports/meta_cli_ghrel.ts (1)
Line range hint
52-89
: Improve error handling and code organization.While the platform handling logic is comprehensive, there are a few improvements that could enhance maintainability and user experience:
- Error messages should be more descriptive
- Platform-specific logic could be extracted into a separate method
- The linux-aarch64 validation should be moved earlier
Consider applying these changes:
override downloadUrls(args: DownloadArgs) { const conf = confValidator.parse(args.config); const { installVersion, platform } = args; + + // Early validation for unsupported platform combinations + if (platform.os === "linux" && platform.arch === "aarch64") { + throw new Error( + `Linux ARM64 is not supported. Available platforms: Linux (x86_64), macOS (x86_64, ARM64)` + ); + } + let arch; switch (platform.arch) { case "x86_64": arch = "x86_64"; break; case "aarch64": arch = "aarch64"; break; default: - throw new Error(`unsupported: ${platform}`); + throw new Error( + `Unsupported architecture: ${platform.arch}. Available: x86_64, aarch64` + ); } + let os; const ext = ".tar.gz"; switch (platform.os) { case "linux": os = "unknown-linux-gnu"; break; case "darwin": os = "apple-darwin"; break; default: - throw new Error(`unsupported: ${platform}`); + throw new Error( + `Unsupported OS: ${platform.os}. Available: linux, darwin` + ); } - if (platform.os == "linux" && platform.arch == "aarch64") { - throw new Error(`unsupported: ${platform}`); - } + return [ this.releaseArtifactUrl( installVersion,modules/ports/std.ts (1)
39-41
: Enhance documentation for defaultAllowedDeps.The current documentation is minimal. Consider expanding it to include:
- The purpose and significance of allowed dependencies
- The structure of the AllowedPortDepX type
- Usage guidelines for plugin developers
Here's a suggested improvement:
/** - * The default set of allowed port deps. + * The default set of allowed port dependencies that plugins are expected to use. + * Each dependency is wrapped in an AllowedPortDepX type that includes: + * - manifest: The port's manifest containing metadata and configuration + * - defaultInst: The default instance configuration for the port + * + * Plugin developers should reference these dependencies when defining their + * plugin's requirements. */ports/infisical.ts (2)
Line range hint
51-85
: Improve error handling and code structure.
- The error message in the OS switch statement's default case is incorrect:
- throw new Error(`unsupported arch: ${platform.arch}`); + throw new Error(`unsupported os: ${os}`);
- Consider enhancing error messages with supported values:
- throw new Error(`unsupported arch: ${platform.arch}`); + throw new Error(`unsupported arch: ${platform.arch}. Supported: amd64, arm64`);
- Consider using maps to simplify the switch statements:
const archMap = { x86_64: "amd64", aarch64: "arm64", } as const; const extMap = { linux: "tar.gz", netbsd: "tar.gz", freebsd: "tar.gz", darwin: "tar.gz", windows: "zip", } as const; const arch = archMap[platform.arch]; if (!arch) throw new Error(`unsupported arch: ${platform.arch}. Supported: ${Object.keys(archMap).join(", ")}`); const ext = extMap[os]; if (!ext) throw new Error(`unsupported os: ${os}. Supported: ${Object.keys(extMap).join(", ")}`);
Line range hint
87-108
: Remove commented code and add error handling.
- Remove commented-out code if it's no longer needed:
- // await $`${ - // depExecShimPath(std_ports.tar_aa, "tar", args.depArts) - // } xf ${fileDwnPath} --directory=${args.tmpDirPath}`;- // await Deno.chmod(std_path.resolve(args.installPath, "bin", "ruff"), 0o700);
- Add executable permissions for the binary:
await std_fs.copy( args.tmpDirPath, installPath.join("bin").toString(), ); + await Deno.chmod(installPath.join("bin", "infisical").toString(), 0o755);
- Consider adding error handling for file operations:
try { await std_fs.copy(args.tmpDirPath, installPath.join("bin").toString()); await Deno.chmod(installPath.join("bin", "infisical").toString(), 0o755); } catch (error) { throw new Error(`Failed to install Infisical: ${error.message}`); }hack.ts (1)
Line range hint
1-6
: Update security warning comments to include tasks.The warning comments at the top of the file should be updated to explicitly mention all exposed functionality, including the new
tasks
export, to ensure users are fully aware of the security implications.Consider updating the comment to be more explicit:
//! This file allows an easy way to start with the typescript ghjkfile //! but is generally insecure for serious usage. //! //! If your ghjkfile imports a malicious module, the module could -//! import the functions defined herin and mess with your ghjkfile. +//! import the functions defined herein (config, env, install, task, tasks) +//! and mess with your ghjkfile.modules/tasks/mod.ts (2)
88-90
: LGTM! Consider enhancing the description further.The updated description provides better context about the tasks functionality. This aligns well with the PR's documentation improvements.
Consider adding a brief example of how to view all tasks, like this:
.description(`Tasks module. -The named tasks in your ghjkfile will be listed here.`); +The named tasks in your ghjkfile will be listed here. + +Run 'ghjk tasks --help' to see all available tasks.`);
Line range hint
111-111
: Fix typo in error message.The word "unexepected" contains a typo and should be "unexpected".
- throw new Error(`unexepected version tag deserializing lockEntry`); + throw new Error(`unexpected version tag deserializing lockEntry`);ports/rustup.ts (3)
Line range hint
109-117
: Consider adding error handling and user notification for installationWhile the implementation is functionally correct, consider adding:
- Error handling for the removal operation
- User notification before removing existing installation
- Backup mechanism or confirmation prompt for existing installations
Here's a suggested improvement:
override async install(args: InstallArgs) { const installPath = $.path(args.installPath); if (await installPath.exists()) { + console.log(`Removing existing installation at ${installPath}`); + try { await installPath.remove({ recursive: true }); + } catch (error) { + throw new Error(`Failed to remove existing installation: ${error.message}`); + } } + try { await std_fs.copy( args.downloadPath, (await installPath.ensureDir()).join("bin").toString(), ); + } catch (error) { + throw new Error(`Failed to install Rustup: ${error.message}`); + } }
Line range hint
13-13
: TODO: Implement port exports sanity checkThis TODO indicates a need for validation of port exports, which is important for ensuring consistent port implementations.
Would you like me to help create a sanity check implementation or create an issue to track this task?
Line range hint
44-44
: FIXME: Remove git dependency for version listingThe current implementation relies on git for listing available versions, which creates an unnecessary dependency. Consider using the GitHub API or a direct HTTPS request to fetch release information instead.
Would you like me to:
- Create an implementation using the GitHub API?
- Open an issue to track this improvement?
modules/ports/ghrel.ts (1)
Line range hint
68-81
: LGTM! Consider enhancing error handling.The addition of the
override
keyword is correct, and the implementation includes robust retry logic. However, consider adding explicit error handling for cases where the repository has no releases.Consider adding a more specific error message:
override async latestStable(args: ListAllArgs) { const metadata = await $.withRetries({ count: 10, delay: $.exponentialBackoff(1000), action: async () => await $.request( `https://api.github.com/repos/${this.repoOwner}/${this.repoName}/releases/latest`, ) .header(ghHeaders(args.config)) + .catch((error) => { + if (error.status === 404) { + throw new Error(`No releases found for ${this.repoOwner}/${this.repoName}`); + } + throw error; + }) .json() as { tag_name: string }, }); return metadata.tag_name; }ports/ruff.ts (3)
Line range hint
44-91
: Improve version comparison logic and error handlingThe version comparison logic could be simplified, and error messages could be more descriptive.
Consider these improvements:
- const parsedVersion = semver.parse(installVersion); - const prefix = semver.lessThan(parsedVersion, semver.parse("0.1.8")) - ? this.repoName - : semver.greaterOrEqual( - parsedVersion, - semver.parse("0.5.0"), - ) - ? `${this.repoName}` - : `${this.repoName}-${installVersion.replace(/^v/, "")}`; + const parsedVersion = semver.parse(installVersion); + const prefix = + semver.lessThan(parsedVersion, semver.parse("0.1.8")) || + semver.greaterOrEqual(parsedVersion, semver.parse("0.5.0")) + ? this.repoName + : `${this.repoName}-${installVersion.replace(/^v/, "")}`; - throw new Error(`unsupported: ${platform}`); + throw new Error(`Unsupported platform architecture: ${platform.arch}`); - throw new Error(`unsupported: ${platform}`); + throw new Error(`Unsupported operating system: ${platform.os}`);
Line range hint
44-134
: Overall implementation is solid with room for improvementThe port implementation correctly handles different versions and platforms. The addition of override keywords improves type safety. Consider:
- Creating constants for version numbers to improve maintainability
- Adding debug logging for installation steps
- Documenting the version-specific behaviors in comments
Example constants:
private static readonly VERSION_THRESHOLDS = { LEGACY_FORMAT: "0.1.8", MODERN_FORMAT: "0.5.0", } as const;
Executable permissions should be properly handled for non-Windows platforms
The commented chmod line should be uncommented and implemented with platform-specific handling, as other ports demonstrate. The current implementation lacks proper executable permissions for Unix-like systems.
- The chmod command is commented out in both
ruff.ts
andinfisical.ts
- Other ports (
temporal_cli.ts
,jq_ghrel.ts
,act.ts
) properly handle platform-specific cases- The permission should be
0o755
(read/execute for all, write for owner) rather than0o700
for CLI toolsSuggested implementation:
if (platform.os !== "windows") { await Deno.chmod(installPath.join("bin", "ruff").toString(), 0o755); }🔗 Analysis chain
Line range hint
92-134
: Address security and error handling concernsSeveral potential issues need attention:
- The commented-out chmod command might indicate incomplete security hardening
- Directory structure verification could be more robust
- Error handling could be more specific
Let's verify if other ports require executable permissions:
Consider these improvements:
- if (!dir.isDirectory) { - throw new Error("unexpected archive structure"); + if (!dir.isDirectory) { + throw new Error(`Invalid archive structure: expected directory at ${dir.path}, found ${dir.type}`); + } + + const binPath = installPath.join("bin"); + await binPath.ensureDir(); + + // Ensure proper permissions for executable + if (platform.os !== "windows") { + await Deno.chmod(binPath.join("ruff").toString(), 0o755); + }🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for chmod usage in other ports rg -l 'chmod.*0o700' ports/Length of output: 62
Script:
#!/bin/bash # Let's check the actual chmod implementations in these files rg 'chmod.*0o[0-9]{3}' -A 2 -B 2 ports/Length of output: 451
Script:
#!/bin/bash # Check if other ports have similar installation patterns ast-grep --pattern 'async install(args: InstallArgs) { $$$ }'Length of output: 65
Script:
#!/bin/bash # Check platform-specific handling in other ports rg 'platform\.os.*windows' ports/Length of output: 287
std/sedLock.ts (1)
93-93
: Consider memory usage with large files.While batching writes is a good practice, storing all file contents in memory could be problematic with large files or many changes. Consider adding a size check or implementing a streaming approach for very large files.
ports/asdf_plugin_git.ts (2)
40-46
: Fix typo in warning comment.There's a typo in the warning message: "no" should be "not".
- * WARNING: this is probably no the function you want if you intend + * WARNING: this is probably not the function you want if you intend
Line range hint
95-124
: Consider additional error handling for file operations.The installation process is well-structured, but consider adding error handling for the final move operation to handle potential filesystem issues gracefully.
if (await installPath.exists()) { await installPath.remove({ recursive: true }); } - await std_fs.move(tmpPath.toString(), installPath.toString()); + try { + await std_fs.move(tmpPath.toString(), installPath.toString()); + } catch (error) { + // Cleanup tmp path if move fails + await tmpPath.remove({ recursive: true }); + throw new Error(`Failed to complete installation: ${error.message}`); + }ports/node.ts (2)
Line range hint
74-108
: Enhance error messages and code structure in platform handling.While the platform handling is comprehensive, consider these improvements:
- More descriptive error messages that guide users
- Extract platform mappings into constants for better maintainability
Consider this refactoring:
+ const ARCH_MAPPING = { + x86_64: "x64", + aarch64: "arm64", + } as const; + + const OS_MAPPING = { + linux: { os: "linux", ext: "tar.gz" }, + darwin: { os: "darwin", ext: "tar.gz" }, + windows: { os: "win", ext: "zip" }, + } as const; downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; - let arch; - switch (platform.arch) { - case "x86_64": - arch = "x64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported: ${platform}`); - } + const arch = ARCH_MAPPING[platform.arch]; + if (!arch) { + throw new Error( + `Unsupported architecture: ${platform.arch}. Supported: ${ + Object.keys(ARCH_MAPPING).join(", ") + }` + ); + } - let os; - let ext; - switch (platform.os) { - case "linux": - os = "linux"; - ext = "tar.gz"; - break; - case "darwin": - os = "darwin"; - ext = "tar.gz"; - break; - case "windows": - os = "win"; - ext = "zip"; - break; - default: - throw new Error(`unsupported: ${platform}`); - } + const osConfig = OS_MAPPING[platform.os]; + if (!osConfig) { + throw new Error( + `Unsupported OS: ${platform.os}. Supported: ${ + Object.keys(OS_MAPPING).join(", ") + }` + ); + }
Line range hint
119-148
: Add robust error handling and validation in install method.The installation process could benefit from additional safeguards:
- Add error handling for tar extraction
- Use atomic operations for directory replacement
- Validate extracted contents before installation
Consider these improvements:
override async install(args: InstallArgs) { const [{ name: fileName }] = this.downloadUrls(args); const fileDwnPath = std_path.resolve(args.downloadPath, fileName); + try { await $`${ depExecShimPath(tar_aa_id, "tar", args.depArts) } xf ${fileDwnPath} --directory=${args.tmpDirPath}`; + } catch (error) { + throw new Error(`Failed to extract archive: ${error.message}`); + } + const tmpInstallPath = `${args.installPath}_tmp`; + // Ensure clean temporary directory + if (await $.path(tmpInstallPath).exists()) { + await $.path(tmpInstallPath).remove({ recursive: true }); + } const dirs = []; for await ( const entry of std_fs.expandGlob( std_path.joinGlobs([args.tmpDirPath, "*"]), ) ) { dirs.push(entry); } if (dirs.length != 1 || !dirs[0].isDirectory) { throw new Error("unexpected archive contents"); } + // Validate extracted contents + const expectedFiles = ["bin/node", "bin/npm"]; + for (const file of expectedFiles) { + const fullPath = std_path.join(dirs[0].path, file); + if (!await $.path(fullPath).exists()) { + throw new Error(`Missing expected file: ${file}`); + } + } - const installPath = $.path(args.installPath); - if (await installPath.exists()) { - await installPath.remove({ recursive: true }); - } - await std_fs.copy( - dirs[0].path, - args.installPath, - ); + // Copy to temporary location first + await std_fs.copy(dirs[0].path, tmpInstallPath); + + // Atomic replacement of installation directory + if (await $.path(args.installPath).exists()) { + await $.path(args.installPath).remove({ recursive: true }); + } + await std_fs.rename(tmpInstallPath, args.installPath); }ports/wasmedge.ts (4)
74-77
: Consider using a more specific glob pattern.The current pattern
"lib*/*"
is quite broad. Consider using a more specific pattern like"lib64/*"
or listing the exact library paths you expect to match to avoid potential issues with unintended matches.
Line range hint
78-122
: Refactor duplicated architecture mapping logic.The architecture mapping logic is duplicated for both Darwin and Linux platforms. Consider extracting this into a separate method to improve maintainability and reduce code duplication.
Here's a suggested refactoring:
+ private getArchitecture(platform: Platform, isLinux: boolean): string { + switch (platform.arch) { + case "x86_64": + return "x86_64"; + case "aarch64": + return isLinux ? "aarch64" : "arm64"; + default: + throw new Error(`unsupported arch: ${platform.arch}`); + } + } override downloadUrls(args: DownloadArgs) { const { installVersion, platform } = args; let fileName; if (platform.os == "darwin") { - let arch; - switch (platform.arch) { - case "x86_64": - arch = "x86_64"; - break; - case "aarch64": - arch = "arm64"; - break; - default: - throw new Error(`unsupported arch: ${platform.arch}`); - } + const arch = this.getArchitecture(platform, false); fileName = `${this.repoName}-${installVersion}-${platform.os}_${arch}.tar.gz`; } else if (platform.os == "linux") { const os = "manylinux2014"; - let arch; - switch (platform.arch) { - case "x86_64": - arch = "x86_64"; - break; - case "aarch64": - arch = "aarch64"; - break; - default: - throw new Error(`unsupported arch: ${platform.arch}`); - } + const arch = this.getArchitecture(platform, true); fileName = `${this.repoName}-${installVersion}-${os}_${arch}.tar.gz`; } else { throw new Error(`unsupported os: ${platform.os}`); }
Line range hint
89-90
: Address the TODO comment about Ubuntu/Debian version support.The TODO comment indicates a need for Ubuntu/Debian version support. This limitation should be documented in the user manual or README to set proper expectations.
Would you like me to help create an issue to track this enhancement or update the documentation to reflect this limitation?
Line range hint
123-155
: Enhance error messaging for archive validation.The error message "unexpected archive contents" could be more descriptive by including the actual number of directories found and their types.
Here's a suggested improvement:
if (dirs.length != 1 || !dirs[0].isDirectory) { - throw new Error("unexpected archive contents"); + throw new Error( + `Expected exactly one directory in archive, but found ${dirs.length} entries.` + + `${dirs.map(d => `\n- ${d.name}: ${d.isDirectory ? 'directory' : 'file'}`).join('')}` + ); }ports/npmi.ts (1)
Line range hint
96-150
: LGTM! Consider addressing the FIXME comment.The addition of the
override
keyword improves type safety. However, there's an unaddressed FIXME comment about replacing shebangs with the runtime dep node path.Would you like me to help implement the shebang replacement functionality or create an issue to track this task?
ports/rust.ts (2)
Line range hint
137-160
: Enhance command construction and error handling.The method has a few areas for improvement:
- Command construction using string interpolation could be more maintainable.
- The glob pattern matching for toolchain directory needs better error handling.
Consider these improvements:
override async download(args: DownloadArgs) { const conf = confValidator.parse(args.config); const tmpPath = $.path(args.tmpDirPath); + const cmdArgs = [ + "-y", + "--no-modify-path", + `--default-toolchain ${args.installVersion}`, + ...(conf.host ? [`--default-host ${conf.host}`] : []), + ...(conf.profile ? [`--profile ${conf.profile}`] : []), + ...(conf.targets ? conf.targets.flatMap(t => ["-t", t]) : []), + ...(conf.components ? conf.components.flatMap(c => ["-c", c]) : []), + ]; - const host = conf.host ? `--default-host ${conf.host}` : ""; - const profile = conf.profile ? `--profile ${conf.profile}` : ""; - const components = conf.components ? `-c ${conf.components.join(" ")}` : ""; - const targets = conf.targets ? `-t ${conf.targets.join(" ")}` : ""; await $.raw`${ depExecShimPath(rustup_rustlang_id, "rustup-init", args.depArts) - } -y --no-modify-path --default-toolchain ${args.installVersion} ${host} ${profile} ${targets} ${components}` + } ${cmdArgs.join(" ")}` .env({ RUSTUP_INIT_SKIP_PATH_CHECK: "yes", RUSTUP_HOME: tmpPath.join("rustup").toString(), CARGO_HOME: tmpPath.join("cargo").toString(), }); const toolchainDir = await tmpPath.join("rustup", "toolchains").expandGlob( "*", ).next(); + if (!toolchainDir.value) { + throw new Error("Failed to find toolchain directory after installation"); + } await std_fs.move( toolchainDir.value!.path.toString(), args.downloadPath, ); }
Line range hint
162-171
: Add error handling for file operations.While the method correctly handles the removal of existing installations, it should include error handling for the copy operation.
Consider this improvement:
override async install(args: InstallArgs) { const installPath = $.path(args.installPath); if (await installPath.exists()) { await installPath.remove({ recursive: true }); } + try { await std_fs.copy( args.downloadPath, args.installPath, ); + } catch (error) { + throw new Error(`Failed to copy Rust toolchain to installation path: ${error.message}`); + } }tests/reloadHooks.ts (1)
110-112
: Consider centralizing the ghjk_reload behavior decision.This section duplicates the same behavioral uncertainty as in the posix script. Once the decision about
ghjk_reload
behavior in non-interactive shells is made, both sections will need to be updated.Consider:
- Creating a shared test helper to enforce consistent behavior across shell implementations
- Adding a comment referencing the architectural decision document (when created)
-# test that ghjk_reload doesn't run by default on non-interactive shells -# test $DUMMY_ENV = "dummy"; and exit 1011 +# See ADR-XXX for ghjk_reload behavior in non-interactive shells +${SHARED_NONINTERACTIVE_TEST}ports/asdf.ts (1)
Line range hint
137-152
: Consider adding binary existence check for consistency.Unlike other methods (
latestStable
,listBinPaths
,download
), theinstall
method doesn't check if the binary exists usingtryDepExecShimPath
. This could lead to runtime errors if the install script is missing.Consider applying this change for consistency:
override async install(args: InstallArgs) { const conf = confValidator.parse(args.config); - await $`${ - depExecShimPath(std_ports.asdf_plugin_git, "install", args.depArts) - }` + const binPath = tryDepExecShimPath( + std_ports.asdf_plugin_git, + "install", + args.depArts, + ); + if (!binPath) { + return super.install(args); + } + await $`${binPath}` .env({ ...pathsWithDepArts(args.depArts, args.platform.os), TMPDIR: args.tmpDirPath,ports/cpy_bs.ts (3)
Line range hint
139-178
: Add documentation for build postfix variations.The platform-specific logic is comprehensive, but it would be helpful to document why certain platforms use different postfix values (e.g., why aarch64 Linux uses 'lto-full' instead of 'pgo+lto-full').
Line range hint
139-178
: Consider enhancing error handling for downloads.While the code includes retry logic for API requests, consider adding specific error handling for the download process itself.
await Promise.all( urls.map(dwnUrlOut) - .map((obj) => downloadFile({ ...args, ...obj, headers })), + .map((obj) => downloadFile({ ...args, ...obj, headers }) + .catch(error => { + throw new Error(`Failed to download CPython build: ${error.message}`, { cause: error }); + }) + ), );
Line range hint
179-196
: Enhance installation robustness and error handling.While the installation logic is sound, consider these improvements for better reliability:
- Verify successful extraction before removing the existing installation
- Add error handling for tar extraction
- Validate the extracted files before moving
override async install(args: InstallArgs) { const [_, fileDwnEntry] = await Array.fromAsync( $.path(args.downloadPath).walk(), ); const fileDwnPath = fileDwnEntry.path.toString(); + const tmpInstallPath = $.path(args.tmpDirPath).join("python", "install"); + + // Extract with error handling + try { await $`${ depExecShimPath(tar_aa_id, "tar", args.installPath) } xf ${fileDwnPath} --directory=${args.tmpDirPath}`; + } catch (error) { + throw new Error(`Failed to extract CPython build: ${error.message}`, { cause: error }); + } + + // Validate extraction + if (!(await tmpInstallPath.exists())) { + throw new Error("Extraction failed: Installation files not found in expected location"); + } const installPath = $.path(args.installPath); - if (await installPath.exists()) { - await installPath.remove({ recursive: true }); - } - await std_fs.move( - $.path(args.tmpDirPath).join("python", "install").toString(), - installPath.toString(), - ); + try { + if (await installPath.exists()) { + await installPath.remove({ recursive: true }); + } + await std_fs.move( + tmpInstallPath.toString(), + installPath.toString(), + ); + } catch (error) { + throw new Error(`Failed to move installation files: ${error.message}`, { cause: error }); + } }tests/ports.ts (1)
Line range hint
198-213
: Rename duplicate test case for clarity.There are two test cases named 'cargobi-sd' with different configurations. The second one uses a 'dev' profile and forces cargo-install. Consider renaming it to 'cargobi-sd-dev' or similar to distinguish between the two cases.
- name: "cargobi-sd", + name: "cargobi-sd-dev",README.md (3)
16-16
: Fix compound adjective hyphenation.Add a hyphen to "real world" when used as a compound adjective.
-for a real world example. +for a real-world example.🧰 Tools
🪛 LanguageTool
[uncategorized] ~16-~16: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...pedev/metatype/blob/main/ghjk.ts) for a real world example.<img src...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
118-120
: Consider enhancing the security warning.The configuration example is good, but the security implications of
enableRuntimes
could be more prominent.Consider adding a warning box or emphasizing the security implications:
config({ defaultBaseEnv: "main", defaultEnv: "main", - // by default, nodejs, python and other runtime - // ports are not allowed to be used - // during the build process of other ports. - // Disable this security measure here. + // ⚠️ SECURITY WARNING: + // By default, runtime ports (nodejs, python, etc.) are not allowed during + // the build process of other ports as a security measure. + // Only disable this if you trust all your dependencies. enableRuntimes: true, });
144-144
: Fix verb form of "setup".The word "setup" should be "set up" when used as a verb.
-This will setup a separate installation at `.dev`. +This will set up a separate installation at `.dev`.🧰 Tools
🪛 LanguageTool
[grammar] ~144-~144: The word “setup” is a noun. The verb is spelled with a space.
Context: ...e that's in the working tree. This will setup a separate installation at.dev
. ```...(NOUN_VERB_CONFUSION)
ports/cargobi.ts (2)
Line range hint
108-182
: Enhance error handling and command construction.While the implementation is generally solid, there are a few areas that could be improved:
- The error message for cargo-binstall failure could be more descriptive by including the command that failed.
- Consider using an array to build the command arguments instead of string interpolation for better safety and maintainability.
Here's a suggested refactoring for the error handling:
} else if (res.code != 0) { - throw new Error(`error ${res.code} on cargo-binstall\n${res.combined}`); + throw new Error( + `cargo-binstall failed with code ${res.code} for package ${conf.crateName}@${args.installVersion}\n` + + `Command output:\n${res.combined}` + ); }And for the command construction:
const buildArgs = (options: string[]) => options.filter(opt => opt.length > 0); const cargoBinstallArgs = buildArgs([ conf.crateName, `--version ${args.installVersion}`, '--disable-strategies compile', `--root ${args.tmpDirPath}`, '--no-confirm', '--no-track', target, locked ]);
Line range hint
184-192
: Add error handling and installation verification.While the installation logic is straightforward, it could benefit from better error handling and verification:
- The copy operation should be wrapped in try/catch
- Consider adding a verification step after installation
Here's a suggested improvement:
override async install(args: InstallArgs) { const installPath = $.path(args.installPath); if (await installPath.exists()) { await installPath.remove({ recursive: true }); } - await std_fs.copy( - args.downloadPath, - args.installPath, - ); + try { + await std_fs.copy(args.downloadPath, args.installPath); + + // Verify installation + if (!(await std_fs.exists(args.installPath))) { + throw new Error('Installation verification failed: target directory does not exist'); + } + } catch (error) { + throw new Error(`Installation failed: ${error.message}`); + } }install/mod.ts (1)
247-252
: Consider enhancing PATH-related user guidance.The warning about PATH configuration is a valuable addition. Consider these improvements:
- Combine the two warn messages into one for better readability
- Add shell-specific instructions for updating PATH
- Add PATH verification to avoid showing the warning if the directory is already in PATH
Here's a suggested improvement:
- logger.warn( - "make sure to add the following to your $PATH to access the ghjk CLI", - ); - logger.warn( - installDir.toString(), - ); + const path = Deno.env.get("PATH") || ""; + if (!path.split(":").includes(installDir.toString())) { + logger.warn( + `Add ${installDir} to your PATH to access the ghjk CLI:\n` + + " - Bash/Zsh: echo 'export PATH=\"${installDir}:$PATH\"' >> ~/.bashrc\n" + + " - Fish: fish_add_path ${installDir}" + ); + }modules/ports/worker.ts (3)
Line range hint
231-245
: Consider improving error message formatting.While the implementation is correct, consider enhancing the error message formatting for better debugging:
- throw new Error(`unexpected response from worker ${JSON.stringify(res)}`); + throw new Error( + `unexpected response from worker: expected "listBinPaths", got "${res.ty}"\n${ + JSON.stringify(res, null, 2) + }` + );
Line range hint
246-287
: LGTM: Consistent implementation pattern.The
override
keyword additions and implementations are correct for all three methods. Consider applying the same error message formatting improvement suggested above to these methods for consistency.
Line range hint
288-300
: Consider adding timeout protection for worker operations.While the implementation is correct, consider adding a timeout mechanism to prevent hanging workers:
async call( req: WorkerReq, ): Promise<WorkerResp> { const worker = new Worker(import.meta.url, { name: `${this.manifest.name}@${this.manifest.version}`, type: "module", }); - // promise that resolves when worker replies - const promise = new Promise<WorkerResp>((resolve, reject) => { + const WORKER_TIMEOUT = 30000; // 30 seconds + const promise = Promise.race([ + new Promise<WorkerResp>((resolve, reject) => { worker.onmessage = (evt: MessageEvent<WorkerResp>) => { resolve(evt.data); }; worker.onmessageerror = (evt) => { reject(evt.data); }; worker.onerror = (err) => { reject(err); }; - }); + }), + new Promise<never>((_, reject) => + setTimeout(() => reject(new Error("Worker timeout")), WORKER_TIMEOUT) + ), + ]); // do "RPC" worker.postMessage(req); - const resp = await promise; - - worker.terminate(); - return resp; + try { + return await promise; + } finally { + worker.terminate(); + } }tests/envs.ts (1)
Line range hint
269-270
: Address TODOs regarding inheritance property testing.There are two TODO comments indicating that more properties need to be tested for inheritance. Consider:
- Creating a list of all inheritable properties
- Adding test cases for each property
- Including edge cases for property overrides and conflicts
Would you like me to help create additional test cases for inheritance properties?
Also applies to: 307-308
mod.ts (3)
54-60
: Documentation could be more descriptive.The JSDoc comment could be enhanced to better describe the return value and provide examples of usage for both overloads.
Consider expanding the documentation like this:
/** * Define and register multiple tasks. + * + * @returns An array of task names that were registered. + * + * @example + * // Using array syntax + * tasks([ + * { name: 'build', fn: () => {} }, + * async () => { /* task implementation */ } + * ]); + * + * // Using record syntax + * tasks({ + * build: () => {}, + * test: { desc: 'Run tests', fn: async () => {} } + * }); */
231-258
: Consider refactoring for better maintainability and error handling.The function handles multiple overloads correctly but could benefit from:
- Breaking down the argument processing into smaller, focused functions
- Adding validation for invalid argument combinations
- Adding explicit error handling for edge cases
Consider refactoring like this:
function parseTaskArgs( nameOrArgsOrFn: string | DenoTaskDefArgs | TaskFn, argsOrFn?: Omit<DenoTaskDefArgs, "name"> | TaskFn, argsMaybe?: Omit<DenoTaskDefArgs, "fn" | "name">, ): DenoTaskDefArgs { if (typeof nameOrArgsOrFn === "object") { if (!("name" in nameOrArgsOrFn)) { throw new Error("Task definition must include a name"); } return nameOrArgsOrFn; } if (typeof nameOrArgsOrFn === "function") { if (typeof argsOrFn === "function") { throw new Error("Cannot provide two functions"); } return { ...(argsOrFn ?? {}), fn: nameOrArgsOrFn, }; } if (typeof argsOrFn === "object") { return { ...argsOrFn, name: nameOrArgsOrFn }; } if (argsOrFn) { return { ...(argsMaybe ?? {}), name: nameOrArgsOrFn, fn: argsOrFn, }; } return { name: nameOrArgsOrFn }; } function task( nameOrArgsOrFn: string | DenoTaskDefArgs | TaskFn, argsOrFn?: Omit<DenoTaskDefArgs, "name"> | TaskFn, argsMaybe?: Omit<DenoTaskDefArgs, "fn" | "name">, ) { const args = parseTaskArgs(nameOrArgsOrFn, argsOrFn, argsMaybe); return builder.addTask({ ...args, ty: "denoFile@v1" }); }
271-279
: Add input validation and consider parallel execution.The implementation could be enhanced with:
- Validation for empty inputs
- Parallel task registration for better performance with large sets of tasks
Consider these improvements:
tasks( defs: | (DenoTaskDefArgs | TaskFn)[] | Record<string, TaskFn | Omit<DenoTaskDefArgs, "name">>, ) { if (Array.isArray(defs)) { if (defs.length === 0) { throw new Error("Task definitions array cannot be empty"); } // Use Promise.all for parallel registration return Promise.all(defs.map((def) => task(def))); } else { const entries = Object.entries(defs); if (entries.length === 0) { throw new Error("Task definitions record cannot be empty"); } // Use Promise.all for parallel registration return Promise.all(entries.map(([key, val]) => task(key, val))); } }modules/envs/mod.ts (2)
184-184
: LGTM! Consider enhancing the error message with more context.The error message change correctly uses the resolved
envKey
. However, to improve user experience, consider enhancing the error message with available environment suggestions.Here's a suggested enhancement:
- throw new Error(`no env found under "${envKey}"`); + const availableEnvs = Object.keys(ecx.config.envsNamed).join('", "'); + throw new Error(`no env found under "${envKey}". Available environments: "${availableEnvs}"`);
Line range hint
171-189
: Consider adding structured output format options.The command currently outputs environment details using
$.inspect
. Consider adding options for different output formats (e.g., JSON, YAML) to improve integration with other tools.Example enhancement:
.option( "-t, --task-env <taskName>", "Synchronize to the environment used by the named task", { standalone: true }, + ) + .option( + "-f, --format <format:string>", + "Output format (inspect|json|yaml)", + { default: "inspect" } ) - .action(async function ({ taskEnv }, envKeyMaybe) { + .action(async function ({ taskEnv, format }, envKeyMaybe) { const { envKey } = envKeyArgs({ taskKeyMaybe: taskEnv, envKeyMaybe, }); const env = ecx.config.envs[envKey]; if (!env) { throw new Error(`no env found under "${envKey}"`); } - // deno-lint-ignore no-console - console.log($.inspect(await showableEnv(gcx, env, envKey))); + const envDetails = await showableEnv(gcx, env, envKey); + // deno-lint-ignore no-console + console.log( + format === "json" ? JSON.stringify(envDetails, null, 2) : + format === "yaml" ? yaml.stringify(envDetails) : + $.inspect(envDetails) + );modules/ports/mod.ts (3)
Line range hint
144-270
: Consider enhancing error handling and version comparison logic.While the error handling improvements are good, there are several opportunities for enhancement:
- Error messages could include more context about the current state.
- Version string normalization is duplicated and could be extracted into a helper function.
- Version comparison logic could be more robust.
Consider applying these improvements:
+ function normalizeVersion(version: string): string { + return version.startsWith('v') ? version.slice(1) : version; + } // In the outdated command... - if (latestVersion[0] === "v") { - latestVersion = latestVersion.slice(1); - } - if (installedVersion[0] === "v") { - installedVersion = installedVersion.slice(1); - } + latestVersion = normalizeVersion(latestVersion); + installedVersion = normalizeVersion(installedVersion); if (!config) { throw new Error( - `Config not found for install id: ${installId}` + `Config not found for install id: ${installId}. Current environment: ${envName}` ); }
Line range hint
271-277
: Fix typo in error message.There's a typo in the error message: "unexepected" should be "unexpected".
if (entry.version != "0") { - throw new Error(`unexepected version tag deserializing lockEntry`); + throw new Error(`unexpected version tag deserializing lockEntry`); }
Line range hint
339-340
: Consider adding security measures for file operations.The code reads and parses JSON files without size limits or path validation:
- Consider adding a size limit when reading
recipe.json
to prevent potential DoS attacks.- Validate that the recipe path doesn't contain directory traversal attempts.
+ const MAX_RECIPE_SIZE = 1024 * 1024; // 1MB limit + const recipePath = $.path(gcx.ghjkDir) + .join("envs", envName) + .join("recipe.json") + .toString(); + + // Validate path + if (!recipePath.startsWith($.path(gcx.ghjkDir).toString())) { + throw new Error("Invalid recipe path: possible directory traversal attempt"); + } + + const recipeStats = await Deno.stat(recipePath); + if (recipeStats.size > MAX_RECIPE_SIZE) { + throw new Error(`Recipe file too large: ${recipeStats.size} bytes`); + } const recipeJson = JSON.parse(await Deno.readTextFile(recipePath));modules/envs/posix.ts (2)
244-251
: Consider using a more unique function name to prevent conflicts.While the implementation is correct, the function name
ghjk_deactivate
could potentially conflict with user-defined functions. Consider using a more unique prefix.-function ghjk_deactivate () { +function __ghjk_internal_deactivate () { if [ -n "$\{GHJK_CLEANUP_POSIX+x}" ]; then eval "$GHJK_CLEANUP_POSIX" unset GHJK_CLEANUP_POSIX fi } -ghjk_deactivate +__ghjk_internal_deactivate
335-344
: Consider using a more unique function name in Fish shell.Similar to the POSIX implementation, consider using a more unique prefix for the Fish shell function to prevent conflicts.
-function ghjk_deactivate +function __ghjk_internal_deactivate if set --query GHJK_CLEANUP_FISH eval $GHJK_CLEANUP_FISH set --erase GHJK_CLEANUP_FISH end end -ghjk_deactivate +__ghjk_internal_deactivateutils/mod.ts (2)
Line range hint
293-303
: LGTM! Consider adding JSDoc documentation.The type change from
string
tostring | Path
is a good improvement for consistency with other utility functions. Consider adding JSDoc documentation to clarify the function's behavior and return type.+/** + * Recursively searches for an entry with the given name starting from the specified path + * and moving up the directory tree. + * @param path - The starting path to begin the search + * @param name - The name of the entry to find + * @returns The full path to the found entry, or undefined if not found + */ export async function findEntryRecursive(path: string | Path, name: string) {
Line range hint
293-303
: Consider making the return type explicit.The function implicitly returns
undefined
when no entry is found. Making the return type explicit would improve type safety and documentation.-export async function findEntryRecursive(path: string | Path, name: string) { +export async function findEntryRecursive(path: string | Path, name: string): Promise<string | undefined> {host/mod.ts (1)
112-117
: Validate task definitions before registration.The code assumes that task definitions are valid without explicit validation.
Consider adding validation for task definitions:
+ const taskValidator = zod.object({ + desc: zod.string(), + fn: zod.function().nullable(), + }); for (const [name, def] of Object.entries(initTasks)) { + try { + taskValidator.parse(def); + } catch (error) { + logger().error(`Invalid task definition for ${name}:`, error); + continue; + } initCmd.command( name.replace("init-", ""),host/init/mod.ts (6)
10-10
: Typo in comment: 'featutres' should be 'features'There's a typographical error in the comment on line 10. The word "featutres" should be corrected to "features".
Apply this diff to fix the typo:
- // NOTE: only limited subset of task featutres are avail. + // NOTE: only limited subset of task features are avail.
54-54
: Improve clarity of prompt messageThe prompt message on line 54 is unclear: "Path to .vscode/settings.json ghjk working dir". It would be better to rephrase it for clarity.
Consider updating the prompt message:
- "Path to .vscode/settings.json ghjk working dir", + "Specify the path to .vscode/settings.json for the ghjk working directory:",
95-97
: Use appropriate logging levelThe message indicates that the file does not exist and a new one will be created. This is not an error condition; consider using
$.logger.info
instead of$.logger.error
.Apply this diff:
- $.logger.error( + $.logger.info( `No file detected at ${vscodeSettings}, creating a new one.`, );
123-123
: Typo in error message: 'discovored' should be 'discovered'There's a spelling mistake in the error message on line 123. Correct "discovored" to "discovered".
Apply this diff:
}, "unexpected JSON discovored at .vscode/settings.json"); + }, "unexpected JSON discovered at .vscode/settings.json");
154-155
: Use professional language in error messagesThe error messages on lines 154-155 and 164-165 contain informal language ("Confused :/"), which may not be appropriate for users. Consider rephrasing to be more professional and informative.
Apply this diff:
At lines 154-155:
throw new Error( - `${ghjkfile} detected in "deno.disablePaths". Confused :/`, + `${ghjkfile} detected in "deno.disablePaths". Please check the configuration.`, );At lines 164-165:
throw new Error( - `${ghjkfile} detected in deno.disablePaths. Confused :/`, + `${ghjkfile} detected in deno.disablePaths. Please check the configuration.`, );Also applies to: 164-165
127-176
: Refactor repeated conditional logic for maintainabilityThe function
handleVscodeSettings
contains multiple similar conditional blocks for handlingdeno.enablePaths
anddeno.disablePaths
. This repetition can make the code harder to maintain and extend.Consider refactoring the logic to reduce duplication. One approach is to normalize the configuration paths into a single object and then handle the addition or checking of
ghjkfile
in a unified way.For example:
// Normalize deno settings const denoConfig = parsedConfig.deno ?? parsedConfig; // Check enablePaths const enablePaths = denoConfig.enablePaths ?? []; if (!enablePaths.includes(ghjkfile)) { $.logger.info(`Adding ${ghjkfile} to deno.enablePaths`); enablePaths.push(ghjkfile); denoConfig.enablePaths = enablePaths; writeOut = true; } else { $.logger.info(`Detected ${ghjkfile} in deno.enablePaths, skipping`); } // Check disablePaths const disablePaths = denoConfig.disablePaths ?? []; if (disablePaths.includes(ghjkfile)) { throw new Error( `${ghjkfile} detected in deno.disablePaths. Please check the configuration.`, ); } else { $.logger.info(`No ${ghjkfile} in deno.disablePaths, proceeding`); }This refactoring simplifies the logic and makes it easier to maintain.
ports/pipi.ts (4)
Line range hint
70-103
: Potential issue with virtual environment creation and pip usageYou are creating the virtual environment with
--without-pip
, which excludespip
from the virtual environment. Later, you attempt to install packages usingpip
while setting environment variables likeVIRTUAL_ENV
andPIP_PYTHON
. This approach relies on the globalpip
to install packages into the virtual environment, which may not work consistently and could lead to packages being installed in the wrong location.Consider removing the
--without-pip
option when creating the virtual environment so thatpip
is included. Then, use thepip
executable within the virtual environment for installing packages to ensure they are correctly installed.Apply this diff to fix the issue:
logger().debug("creating new venv for package"); const venvPath = tmpPath.join("venv"); - await $`${ - depExecShimPath(std_ports.cpy_bs_ghrel, "python3", args.depArts) - } -m venv --without-pip ${venvPath.toString()}` + await $`${ + depExecShimPath(std_ports.cpy_bs_ghrel, "python3", args.depArts) + } -m venv ${venvPath.toString()}` .env(depPathEnvs); + // Upgrade pip in the virtual environment to the latest version + await $`${ + venvPath.join('bin', 'python3').toString() + } -m pip install --upgrade pip` + .env({ VIRTUAL_ENV, PATH }); const PATH = `${venvPath.join("bin").toString()}:${depPathEnvs.PATH}`; const VIRTUAL_ENV = venvPath.toString();Update the package installation command to use the virtual environment's
pip
:const dependencies = conf.peerDeps?.map((dep) => ( dep.version ? [dep.name, dep.version].join("==") : dep.name )) ?? []; - await $`${ - depExecShimPath(std_ports.cpy_bs_ghrel, "python3", args.depArts) - } -m pip -qq install ${conf.packageName}==${args.installVersion} ${dependencies}` + await $`${ + venvPath.join('bin', 'pip').toString() + } -qq install ${conf.packageName}==${args.installVersion} ${dependencies}` .env( { ...depPathEnvs,This ensures that you're using the
pip
within the virtual environment, leading to more predictable and reliable package installations.
Line range hint
158-160
: Potential null reference when accessing iterator resultWhen obtaining the Python version directory within the virtual environment, you are accessing
.value!
without checking if the iterator has yielded a result. If theexpandGlob
call does not find any matching directories,next()
will return an object withdone: true
andvalue: undefined
, leading to a runtime error.Consider adding a check to ensure that
value
is not undefined before accessing it, and handle the error appropriately if no matching directories are found.Apply this diff to fix the issue:
const venvBinDir = venvPath.join("bin").toString(); - const venvPYPATH = ( - await venvPath.join("lib").expandGlob("python*").next() - ).value!.path.join("site-packages").toString(); + const globIterator = await venvPath.join("lib").expandGlob("python*").next(); + if (globIterator.done || !globIterator.value) { + throw new Error("No Python version directories found in venv/lib"); + } + const venvPYPATH = globIterator.value.path.join("site-packages").toString(); const PATH = `${venvBinDir}:${depPathEnvs.PATH}`; const VIRTUAL_ENV = venvPath.toString();This ensures that your code does not crash if the expected directory is not found.
Line range hint
190-208
: Optimize file processing to improve efficiencyThe current method of reading and writing files is inefficient, as it processes all files regardless of type, including binary files. This can be optimized by:
- Skipping binary files to avoid unnecessary processing and potential errors.
- Limiting the replacement to shebang lines instead of processing entire file contents.
Would you like assistance in refactoring this section to improve performance? This could involve checking file content types before processing and using more efficient methods to replace only the necessary parts of the files.
205-205
: Follow up on the TODO regardingcreateSymlinkTo
bugYou have a TODO comment to open a ticket about a bug in
createSymlinkTo(relative)
in thedsherret/jax
project. Addressing this issue promptly can help avoid potential problems in your code that relies on this functionality.Would you like assistance in drafting this issue or exploring a workaround in the meantime?
files/mod.ts (1)
Line range hint
1094-1109
: Review the Implications of Exportingtask$
FunctionBy exporting the
task$
function, it becomes part of the public API. Confirm that this is intentional and evaluate any potential side effects. Ensure that exposing this function does not introduce security risks or unintended dependencies. Consider adding documentation to clarify its intended external usage.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
.ghjk/deno.lock
is excluded by!**/*.lock
📒 Files selected for processing (59)
.ghjk/lock.json
(5 hunks).vscode/settings.json
(2 hunks)README.md
(2 hunks)docs/available-commands.md
(0 hunks)docs/installation-vars.md
(1 hunks)docs/known-issues.md
(1 hunks)docs/manual.md
(1 hunks)examples/env_vars/ghjk.ts
(1 hunks)examples/kitchen/ghjk.ts
(1 hunks)files/mod.ts
(2 hunks)ghjk.ts
(4 hunks)hack.ts
(1 hunks)host/init/mod.ts
(1 hunks)host/init/template.ts
(1 hunks)host/mod.ts
(7 hunks)install/mod.ts
(2 hunks)mod.ts
(4 hunks)modules/envs/mod.ts
(1 hunks)modules/envs/posix.ts
(5 hunks)modules/ports/ambient.ts
(2 hunks)modules/ports/ghrel.ts
(2 hunks)modules/ports/mod.ts
(1 hunks)modules/ports/std.ts
(2 hunks)modules/ports/std_runtime.ts
(1 hunks)modules/ports/worker.ts
(7 hunks)modules/tasks/mod.ts
(1 hunks)ports/act.ts
(2 hunks)ports/asdf.ts
(4 hunks)ports/asdf_plugin_git.ts
(4 hunks)ports/cargo-binstall.ts
(2 hunks)ports/cargobi.ts
(2 hunks)ports/cmake.ts
(1 hunks)ports/cpy_bs.ts
(3 hunks)ports/deno_ghrel.ts
(2 hunks)ports/dummy.ts
(3 hunks)ports/earthly.ts
(2 hunks)ports/infisical.ts
(2 hunks)ports/jq_ghrel.ts
(2 hunks)ports/meta_cli_ghrel.ts
(2 hunks)ports/mod.ts
(1 hunks)ports/mold.ts
(2 hunks)ports/node.ts
(2 hunks)ports/npmi.ts
(2 hunks)ports/opentofu_ghrel.ts
(2 hunks)ports/pipi.ts
(3 hunks)ports/pnpm.ts
(2 hunks)ports/poetry.ts
(1 hunks)ports/protoc.ts
(2 hunks)ports/ruff.ts
(2 hunks)ports/rust.ts
(2 hunks)ports/rustup.ts
(2 hunks)ports/temporal_cli.ts
(2 hunks)ports/terraform.ts
(2 hunks)ports/wasmedge.ts
(2 hunks)std/sedLock.ts
(3 hunks)tests/envs.ts
(3 hunks)tests/ports.ts
(3 hunks)tests/reloadHooks.ts
(2 hunks)utils/mod.ts
(1 hunks)
💤 Files with no reviewable changes (1)
- docs/available-commands.md
✅ Files skipped from review due to trivial changes (1)
- ports/mod.ts
🧰 Additional context used
🪛 LanguageTool
README.md
[uncategorized] ~16-~16: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...pedev/metatype/blob/main/ghjk.ts) for a real world example.
<img src...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[grammar] ~144-~144: The word “setup” is a noun. The verb is spelled with a space.
Context: ...e that's in the working tree. This will setup a separate installation at .dev
. ```...
(NOUN_VERB_CONFUSION)
docs/installation-vars.md
[uncategorized] ~10-~10: Did you mean “its” (the possessive pronoun)?
Context: ...generally preferable for ghjk to manage it's own Deno versions still. | A Deno CLI i...
(ITS_PREMIUM)
docs/known-issues.md
[grammar] ~6-~6: The word ‘fore’ is a noun or an adjective. A verb or adverb is missing or misspelled here, or maybe a comma is missing.
Context: ...s imported by the ghjk.ts file. You can fore re-serialization of the ghjkfile by del...
(PRP_MD_NN)
[grammar] ~11-~11: Did you mean “it’s” (contraction of “it is/has”)?
Context: ...s get their files from github releases, its easy to get past this limit especially ...
(ITS_TO_IT_S)
[typographical] ~11-~11: Consider inserting a comma for improved readability.
Context: ...eleases, its easy to get past this limit especially in CI contexts. This will manifest in f...
(MISSING_COMMAS)
docs/manual.md
[grammar] ~29-~29: The singular determiner ‘this’ may not agree with the plural noun ‘documents’. Did you mean “these”?
Context: ...d ghjkfile is available and the rest of this documents will use typescript for confi...
(THIS_NNS)
[grammar] ~29-~29: Use the singular noun “document” with the word ‘this’.
Context: ...kfile is available and the rest of this documents will use typescript for configuration. ...
(DT_JJ_NNS_MD)
[uncategorized] ~73-~73: Possible missing comma found.
Context: ...One that contains a recognized ghjkfile format like any file called ghjk.ts
- One th...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~87-~87: Possible missing comma found.
Context: ...again, to execute task functions you've written for example. While the details of the o...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~88-~88: Consider an alternative for the often overused word ‘important’.
Context: ...While the details of the output are not important, this serialize then do workflow defi...
(NOT_IMPORTANT)
[uncategorized] ~88-~88: Possible missing comma found.
Context: ...lize then do_ workflow defines how ghjk functions as we should see. The ghjk CLI seriali...
(AI_HYDRA_LEO_MISSING_COMMA)
[misspelling] ~105-~105: This sounds awkward in English. The standard is “the question of how”.
Context: ...atency of the CLI commands. This raises the question how well the cache invalidation works in gh...
(THE_QUESTION_WH)
[uncategorized] ~132-~132: Possible missing comma found.
Context: ... retain version numbers resolved during installation which is important for the basic need o...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~141-~141: Consider replacing this phrase with the adverb “traditionally” to avoid wordiness.
Context: ... is to: - Resolve the ghjkfile conflict in a traditional manner - Instead of manually resolving the loc...
(IN_A_X_MANNER)
[uncategorized] ~147-~147: Possible missing comma found.
Context: ...e contained new versions, they'll be re-resolved possibly to a different version. But ge...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~151-~151: Possible missing comma found.
Context: ... The lockfile format itself is still in flux and there are plans to improve the merg...
(AI_HYDRA_LEO_MISSING_COMMA)
[duplication] ~156-~156: Possible typo: you repeated a word
Context: ...pt functions, and then invoke them from the the CLI. The CLI will then load your ghjkfi...
(ENGLISH_WORD_REPEAT_RULE)
[misspelling] ~180-~180: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’.
Context: ...hjk x greet ghjk ``` The $
object is a enhanced version of the one from the [d...
(EN_A_VS_AN)
[style] ~180-~180: The preposition ‘Amongst’ is correct, but some people think that it is old-fashioned or literary. A more frequently used alternative is the preposition “among”.
Context: ...dax](https://jsr.io/david/jsr) library. Amongst many things, it allows easy execution o...
(AMONGST)
[misspelling] ~181-~181: This word is normally spelled with a hyphen.
Context: ...s easy execution of shell commands in a cross platform way. Look at the official documentation...
(EN_COMPOUNDS_CROSS_PLATFORM)
[grammar] ~182-~182: Did you mean the possessive pronoun “its”?
Context: ...t the official documentation for all of it's illustrious powers. Tasks can also dep...
(IT_S_ITS)
[uncategorized] ~184-~184: Possible missing comma found.
Context: ... powers. Tasks can also depend on each other meaning that the depended on task is al...
(AI_HYDRA_LEO_MISSING_COMMA)
[typographical] ~186-~186: Two consecutive dots
Context: ...examples/tasks/ghjk.ts) for more details.. ## Envs Ghjk's environments, simply p...
(DOUBLE_PUNCTUATION)
[uncategorized] ~191-~191: Possible missing preposition found.
Context: ...e current working directory and the set environment variables. Ghjk envs then allow you: -...
(AI_HYDRA_LEO_MISSING_OF)
[typographical] ~193-~193: Consider adding two commas here.
Context: ... allow you: - Set environment variables of course - Add existing paths or newly installed...
(OF_COURSE_COMMA)
[uncategorized] ~217-~217: The adjective “additive-based” is spelled with a hyphen.
Context: ... the main
environment. Inheritance is additive based for most env properties and allows easy...
(BASED_HYPHEN)
[misspelling] ~232-~232: This word is normally spelled with a hyphen.
Context: ... That is, entering an environment is a two step process. Cooking is what we call prepa...
(EN_COMPOUNDS_TWO_STEP)
[grammar] ~237-~237: After ‘it’, use the third-person verb form “is”.
Context: ...shell scripts to activate/deactivate it are prepared. The results of env cooking ar...
(IT_VBZ)
[uncategorized] ~259-~259: “you” seems less likely than “your” (belonging to you).
Context: ...deactivate any active environments from you shell, when it cd
s away into a direct...
(AI_HYDRA_LEO_CP_YOU_YOUR)
[duplication] ~267-~267: Possible typo: you repeated a word
Context: ...hat the CLI activate command depends on the the ghjk shell hooks being available. If no...
(ENGLISH_WORD_REPEAT_RULE)
[uncategorized] ~306-~306: Possible missing comma found.
Context: ...ritten in Deno flavoured typescript are supported and there's a small collection of such ...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~310-~310: Possible missing comma found.
Context: ...stallConfig` objects that describe user configuration along with where the port can be found ...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~385-~385: The phrase “a variety of” may be wordy. To make your writing clearer, consider replacing it.
Context: ...d installing one from the internet. For a variety of reasons, the standard set of allowed po...
(A_VARIETY_OF)
[grammar] ~396-~396: The verb form ‘is’ does not seem to match the subject ‘implementations’.
Context: ...riting ports The ports implementations is going through a lot of breaking changes...
(SUBJECT_VERB_AGREEMENT_PLURAL)
[style] ~396-~396: The phrase ‘a lot of’ might be wordy and overused. Consider using an alternative.
Context: ... ports implementations is going through a lot of breaking changes. If you need to author...
(A_LOT_OF)
[grammar] ~402-~402: You used an adverb (‘primarily’) instead of an adjective, or a noun (‘difference’) instead of another adjective.
Context: ...CI jobs and for use in build tools. The primarily difference between the two scenarios is how activa...
(A_RB_NN)
[uncategorized] ~455-~455: Possible missing comma found.
Context: ...LL command available in some Dockerfile implementations or by using command processors more adv...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~455-~455: “that” seems less likely than “than” (as in: greater than).
Context: ... using command processors more advanced that POSIX sh. ```dockerfile # contraption ...
(AI_HYDRA_LEO_CP_THAT_THAN)
[style] ~465-~465: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...rketplace/actions/ghjk-everything) that is able to: - Installs ghjk CLI and hooks - Caches...
(BE_ABLE_TO)
[uncategorized] ~471-~471: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...r to the bash
shell to have the hooks auto activate your environment. Otherwise, it's neces...
(AUTO_HYPHEN)
🪛 Markdownlint
README.md
147-147: null
Dollar signs used before commands without showing output
(MD014, commands-show-output)
153-153: null
Dollar signs used before commands without showing output
(MD014, commands-show-output)
docs/manual.md
101-101: Expected: h3; Actual: h4
Heading levels should only increment by one level at a time
(MD001, heading-increment)
270-270: Expected: h3; Actual: h4
Heading levels should only increment by one level at a time
(MD001, heading-increment)
143-143: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
🔇 Additional comments (63)
examples/env_vars/ghjk.ts (1)
20-20
: Consider adding error handling and input validation.
While the dynamic evaluation using template literals is a good approach, there are a few considerations:
- Shell command execution could be vulnerable if
A
orB
contain malicious input - The command might fail silently if the shell execution encounters an error
Consider:
- Adding input validation for variables A and B
- Implementing error handling for the shell command execution
- Using a safer string interpolation method if shell execution isn't strictly necessary
modules/ports/std_runtime.ts (1)
8-17
: Verify runtime ports usage.
The export configuration is well-structured and documented. However, let's verify that all these ports are actually used when enableRuntimes
is enabled.
✅ Verification successful
Runtime ports are correctly configured and used as dependencies
The verification confirms that the runtime ports in std_runtime.ts
are properly used:
node.default()
is used as a dependency for npmi port installationscpy_bs.default()
is used as a dependency for pipi port installationsrust.default()
is used as a dependency for cargobi port installationsasdf_plugin_git.buildDep()
is used as a dependency for asdf plugin installations
Each port implementation correctly includes its corresponding runtime dependency in its configuration, making these runtime ports essential when enableRuntimes
is true.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the usage of runtime ports when enableRuntimes is true
# Search for enableRuntimes usage and its connection to these ports
echo "Searching for enableRuntimes configuration..."
rg -l "enableRuntimes"
# Search for imports of std_runtime
echo "Checking std_runtime imports..."
rg -l "std_runtime"
# Search for usage patterns of each port
echo "Checking individual port usage..."
rg -l "node\.default\(\)"
rg -l "cpy_bs\.default\(\)"
rg -l "rust\.default\(\)"
rg -l "asdf_plugin_git\.buildDep\(\)"
Length of output: 817
Script:
#!/bin/bash
# Let's check how std_runtime is used in files/mod.ts and its connection to enableRuntimes
echo "Checking std_runtime usage in files/mod.ts..."
rg -A 5 -B 5 "std_runtime" files/mod.ts
# Let's also check the enableRuntimes configuration in ghjk.ts
echo "Checking enableRuntimes configuration in ghjk.ts..."
rg -A 5 -B 5 "enableRuntimes" ghjk.ts
# Let's check if these runtime ports are used in any other way
echo "Checking other usage patterns of runtime ports..."
rg "from.*node"
rg "from.*cpy_bs"
rg "from.*rust"
rg "from.*asdf_plugin_git"
Length of output: 2591
Script:
#!/bin/bash
# Let's check how these runtime ports are actually used in their respective package managers
echo "Checking npmi port usage of node runtime..."
rg -A 5 "node\.default" ports/npmi.ts
echo "Checking pipi port usage of cpy_bs runtime..."
rg -A 5 "cpy_bs\.default" ports/pipi.ts
echo "Checking cargobi port usage of rust runtime..."
rg -A 5 "rust\.default" ports/cargobi.ts
echo "Checking asdf port usage of asdf_plugin_git runtime..."
rg -A 5 "asdf_plugin_git\.buildDep" ports/asdf.ts
# Let's also check how enableRuntimes affects the usage of these ports
echo "Checking enableRuntimes impact..."
rg -A 10 "enableRuntimes.*true" "tests/*.ts"
Length of output: 771
Script:
#!/bin/bash
# Let's check the actual implementation of these package manager ports
echo "Checking npmi implementation..."
rg -A 10 "export default" ports/npmi.ts
echo "Checking pipi implementation..."
rg -A 10 "export default" ports/pipi.ts
echo "Checking cargobi implementation..."
rg -A 10 "export default" ports/cargobi.ts
echo "Checking asdf implementation..."
rg -A 10 "export default" ports/asdf.ts
# Let's also check the tests directory path and then check enableRuntimes
echo "Finding tests directory..."
fd -t d "tests"
# Check config files for runtime dependencies
echo "Checking runtime dependencies in configs..."
rg -l "buildDeps.*node\.default|buildDeps.*cpy_bs\.default|buildDeps.*rust\.default|buildDeps.*asdf_plugin_git\.buildDep"
Length of output: 2108
.vscode/settings.json (2)
22-28
: LGTM! Dictionary updates are comprehensive.
The added technical terms align well with the project's context and requirements. The capitalization is correctly preserved for proper spell checking.
3-4
: LGTM, but verify if both paths are necessary.
While the addition of "ghjk.ts" aligns with the new task management system, consider if it's necessary to specify both "." and "ghjk.ts" since the root path "." would include "ghjk.ts".
ports/cmake.ts (1)
Line range hint 27-42
: Verify cache invalidation for platform-specific installations.
Given that this PR includes cache invalidation fixes, please verify that:
- The macOS-specific pip installation properly invalidates its cache when versions change
- The asdf installation path correctly handles cache updates for non-macOS platforms
Let's check for any cache-related code in the codebase:
✅ Verification successful
Let me gather more specific information about the installation caching mechanism:
Let me check the caching implementation in the ports module specifically:
Based on the comprehensive analysis of the codebase, I can now generate the final response:
Cache invalidation is properly handled for both installation paths.
The implementation correctly handles cache invalidation:
- For macOS (pipi): The cache is managed through the
installId
hash which includes the version, ensuring proper invalidation when versions change - For non-macOS (asdf): Cache is similarly managed through the same mechanism in the
sync.ts
module
The caching system is robust because:
- Each installation is uniquely identified by a hash of its configuration
- The
sync.ts
module checks cache status before installation (cached && cached.progress == "installed"
) - Both download and install stages are properly tracked in the cache
- Cache entries include all necessary artifacts and are version-specific
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for cache-related code in the installation paths
rg -i "cache|invalidate" --type ts
Length of output: 1967
Script:
#!/bin/bash
# Check the implementation of installation caching in ports
ast-grep --pattern 'async function install($_) {
$$$
}'
# Also check for any pipi and asdf specific cache handling
rg -B2 -A2 "pipi|asdf" --type ts
Length of output: 15282
Script:
#!/bin/bash
# Check the ports sync implementation which handles caching
cat modules/ports/sync.ts
# Also check if there are any specific cache implementations for pipi
cat ports/pipi.ts
Length of output: 36233
ports/dummy.ts (1)
Line range hint 42-46
: LGTM: Correctly marked override method
The override
keyword is properly used, and the implementation is appropriate for a test port.
ports/deno_ghrel.ts (1)
Line range hint 38-61
: LGTM! Platform support implementation looks solid.
The override
keyword addition correctly indicates method inheritance, and the implementation properly handles platform-specific naming conventions.
Let's verify if all supported platforms are covered:
✅ Verification successful
Based on the search results, I can now generate the final response:
Platform support implementation is complete and consistent with other ports
The platform support in deno_ghrel.ts
correctly handles all the major platforms (Linux, Windows, Darwin) that are consistently supported across other ports in the codebase. The OS naming conventions used (unknown-linux-gnu
, windows-msvc
, apple-darwin
) align with Deno's official release artifacts.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify platform support completeness
# Test: Check if there are any platform-specific conditions or configurations elsewhere in the codebase
# that might indicate additional platforms that should be supported here
# Search for platform-related configurations
rg -g '!*.lock' -g '!*.json' -A 3 'platforms.*=.*\[(.*)\]|case.*"(linux|windows|darwin)"'
Length of output: 5415
ports/opentofu_ghrel.ts (2)
40-40
: LGTM! Correctly marked as override.
The override
keyword addition properly indicates that this method implements the abstract method from GithubReleasePort
.
68-68
: LGTM! Correctly marked as override.
The override
keyword addition properly indicates that this method implements the abstract method from GithubReleasePort
.
modules/ports/ambient.ts (2)
Line range hint 15-46
: LGTM! Well-structured error handling.
The addition of the override
keyword correctly indicates method inheritance. The error handling is comprehensive with proper error chaining and descriptive messages.
47-49
: LGTM! Clear and focused implementation.
The addition of the override
keyword correctly indicates method inheritance. The method has a single responsibility and properly handles the async operation.
ghjk.ts (1)
23-23
: Verify array access safety from pipi port.
The [0]
index access suggests pipi
returns an array. Let's verify this implementation to ensure it always returns at least one element.
✅ Verification successful
Let me search for the implementation of the pipi
function to understand its return type and behavior.
Let me search for the type definition of PipiInstallConf
and any interfaces/types related to the pipi function's return type.
Based on the implementation in ports/pipi.ts
, I can now generate the final response:
Array access from pipi port is safe
The pipi
port's conf
function always returns an array with exactly two elements: the parsed config and a cpy_bs()
dependency. The [0]
index access is safe as it consistently returns the first element containing the package configuration.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for pipi port implementation
ast-grep --pattern 'export function pipi($_) {
$$$
}'
# Search for other usages of pipi port
rg 'ports\.pipi\(' -A 2
Length of output: 1380
Script:
#!/bin/bash
# Search for pipi implementation and its return type
ast-grep --pattern 'export function pipi($_): $_ {
$$$
}'
# Search for pipi type definition if it exists
rg 'pipi.*=' -A 5
Length of output: 318
Script:
#!/bin/bash
# Search for PipiInstallConf type definition
rg 'type PipiInstallConf' -A 5
# Search for pipi function implementation in ports directory
fd pipi.ts -t f --exec cat {}
# Search for array return types or Install types
rg 'type.*Install.*=' -A 5
Length of output: 18248
ports/terraform.ts (1)
71-75
: LGTM!
The parallel download implementation using Promise.all is efficient, and the override keyword is correctly applied.
ports/mold.ts (2)
Line range hint 47-64
: LGTM! Proper use of the override keyword.
The override
keyword addition correctly indicates that this method implements the parent class's abstract method. The URL construction logic is sound and handles version strings appropriately.
Line range hint 65-98
: Enhance security measures for archive handling.
The current implementation could benefit from additional security measures when handling downloaded archives:
- Validate the archive's checksum before extraction
- Implement size limits for extracted content
- Sanitize file paths during extraction to prevent path traversal
Let's check if other ports implement these security measures:
Consider implementing these security enhancements to protect against potentially malicious archives.
ports/meta_cli_ghrel.ts (1)
Line range hint 91-108
: Add error handling and validation for file operations.
The installation process lacks proper error handling and validation steps that could prevent data loss or incomplete installations.
Consider applying these improvements:
override async install(args: InstallArgs) {
const [{ name: fileName }] = this.downloadUrls(args);
const fileDwnPath = std_path.resolve(args.downloadPath, fileName);
+
+ // Verify download exists
+ if (!await std_fs.exists(fileDwnPath)) {
+ throw new Error(`Downloaded file not found: ${fileDwnPath}`);
+ }
+
+ // Create backup of existing installation
const installPath = $.path(args.installPath);
if (await installPath.exists()) {
- await installPath.remove({ recursive: true });
+ const backupPath = `${installPath}.backup`;
+ await std_fs.copy(installPath.toString(), backupPath);
+ try {
+ await installPath.remove({ recursive: true });
+ } catch (error) {
+ throw new Error(
+ `Failed to remove existing installation: ${error.message}`
+ );
+ }
}
- await std_fs.copy(
- args.tmpDirPath,
- installPath.join("bin").toString(),
- );
+
+ try {
+ // Extract archive
+ await $`${
+ depExecShimPath(std_ports.tar_aa, "tar", args.depArts)
+ } xf ${fileDwnPath} --directory=${args.tmpDirPath}`;
+
+ // Verify extraction
+ const extractedFiles = await std_fs.readDir(args.tmpDirPath);
+ if (extractedFiles.length === 0) {
+ throw new Error("Archive extraction produced no files");
+ }
+
+ // Copy files
+ const binPath = installPath.join("bin").toString();
+ await std_fs.ensureDir(binPath);
+ await std_fs.copy(args.tmpDirPath, binPath);
+
+ // Verify installation
+ const installedFiles = await std_fs.readDir(binPath);
+ if (installedFiles.length === 0) {
+ throw new Error("Installation directory is empty after copy");
+ }
+ } catch (error) {
+ // Restore backup on failure
+ if (await std_fs.exists(`${installPath}.backup`)) {
+ await std_fs.copy(`${installPath}.backup`, installPath.toString());
+ }
+ throw new Error(`Installation failed: ${error.message}`);
+ } finally {
+ // Cleanup backup
+ if (await std_fs.exists(`${installPath}.backup`)) {
+ await std_fs.remove(`${installPath}.backup`);
+ }
+ }
}
Let's verify the installation process:
modules/ports/std.ts (1)
1-2
: Verify impact of strengthened dependency requirement.
The documentation change from "allowed" to "expected" implies a stronger requirement for plugins to depend on standard ports. This could potentially affect existing plugins that were designed with optional standard port dependencies.
Let's check for any plugins that might be affected:
✅ Verification successful
Documentation change from "allowed" to "expected" is consistent with architecture
Based on the architecture documentation and codebase analysis, the semantic change from "allowed" to "expected" in the standard ports documentation aligns with the existing architecture. The documentation states that ports are "expected to expose" certain stages, indicating that this was already an established requirement rather than a breaking change. The standard ports appear to provide core functionality that plugins inherently depend on to implement the required stages.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Search for plugin implementations to assess impact
# Look for plugin files that might optionally use standard ports
fd -e ts -e js --full-path '*/plugins/*' --exec rg -l 'import.*from.*ports/std'
Length of output: 372
Script:
#!/bin/bash
# Search for plugin implementations that import from ports/std
fd -e ts -e js -g '**/plugins/**' --exec rg -l 'import.*from.*ports/std' {} \;
# Also search for any optional usage patterns of standard ports
fd -e ts -e js -g '**/plugins/**' --exec rg -A 5 -B 5 'ports/std' {} \;
# Look for any plugin configuration or setup files
fd -e ts -e js -g '**/plugins/**' --exec rg -l 'Plugin|plugin.*config' {} \;
Length of output: 240
Script:
#!/bin/bash
# Let's try a different approach to find plugin-related files and their dependencies
# First, find the ports/std.ts file to confirm its location
fd -t f "std.ts"
# Search for any imports referencing 'std' in the entire codebase
rg -l "from ['\"].*std['\"]"
# Look for plugin-related files and their content
rg -l "Plugin|plugin"
Length of output: 366
Script:
#!/bin/bash
# Let's examine the content of key files to understand the port system better
# Check the types and interfaces for plugins
rg -A 5 "interface.*Plugin|type.*Plugin" modules/ports/types.ts
# Look at how std ports are used in other port files
rg -A 3 "from ['\"].*std['\"]" modules/ports/std_runtime.ts modules/ports/ambient.ts
# Check architecture documentation for plugin requirements
rg -A 10 -B 10 "plugin|Plugin" docs/architecture.md
Length of output: 1218
ports/infisical.ts (1)
46-49
: LGTM! Correct override implementation.
The override
keyword addition and version string manipulation are consistent with the class's behavior.
hack.ts (1)
18-18
: LGTM! New export follows secure patterns.
The new tasks
export correctly implements the security patterns used throughout the file, utilizing both Object.freeze
and firstCallerCheck
.
Let's verify that this is the only place where tasks are exported:
✅ Verification successful
Multiple exports of tasks
found, but they serve different purposes
The two exports of tasks
are unrelated and don't pose a security concern:
- In
modules/std.ts
,tasks
is a string constant ("tasks") used as a key in the module mapping system - In
hack.ts
,tasks
is the secured configuration object wrapped withfirstCallerCheck
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify tasks export uniqueness and usage
# Expect: Only one export of tasks should exist to maintain security
rg -p "export.*tasks.*="
Length of output: 151
Script:
#!/bin/bash
# Let's check the context of both exports to understand their relationship and usage
# Check the content of modules/std.ts
echo "=== Content of modules/std.ts ==="
cat modules/std.ts
# Check references to tasks from std.ts
echo -e "\n=== References to tasks from std.ts ==="
rg "std.*tasks" -A 2
# Check if firstCallerCheck is used in std.ts
echo -e "\n=== firstCallerCheck usage in std.ts ==="
rg "firstCallerCheck" modules/std.ts
Length of output: 866
ports/rustup.ts (2)
63-65
: LGTM: Correct use of override keyword
The override
keyword addition properly indicates that this method implements the abstract method from PortBase
.
102-107
: LGTM: Proper download implementation with executable permissions
The override
keyword is correctly added, and the implementation appropriately handles concurrent downloads while setting executable permissions (0o700) for the downloaded files.
modules/ports/ghrel.ts (1)
Line range hint 53-67
: LGTM! Verify base class method signature.
The addition of the override
keyword improves code clarity by explicitly indicating inheritance. The implementation includes proper error handling and concurrent downloads.
Let's verify the base class method signature:
✅ Verification successful
The override
keyword is correctly used and matches the base class signature
The verification confirms that:
PortBase
is an abstract class inmodules/ports/base.ts
- It declares an abstract method
download(args: DownloadArgs): Promise<void> | void
- The implementation in
GithubReleasePort
correctly overrides this method with a compatible signature
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the base class (PortBase) contains the download method
# Expected: Find the download method signature in base.ts
# Search for the download method in the base class
ast-grep --pattern 'class PortBase {
$$$
download(args: DownloadArgs): Promise<void> {
$$$
}
$$$
}'
Length of output: 113
Script:
#!/bin/bash
# Let's try a broader search to find the base class and its method definitions
# First, let's find the base class file
fd "base.ts" --type f
# Then, let's examine its content focusing on abstract methods
rg "abstract.*download.*args.*Promise" --type ts
# Also search for any class named PortBase
ast-grep --pattern 'class PortBase {
$$$
}'
# Additionally, let's check for abstract class definition
ast-grep --pattern 'abstract class PortBase {
$$$
}'
Length of output: 3790
std/sedLock.ts (1)
43-44
: LGTM: Clean initialization of workSet.
The type annotation and initialization are clear and well-placed for the batched write implementation.
examples/kitchen/ghjk.ts (1)
122-123
: Consider adding error handling for directory-dependent tasks
The onEnter task executes ls
in the parent directory (..
), which could fail if:
- The parent directory doesn't exist
- The script is run from the root directory
- The user doesn't have read permissions
Let's verify the directory structure and potential edge cases:
Consider adding error handling and validation:
.onEnter(task({
workingDir: "..",
- fn: ($) => $`ls`,
+ fn: async ($) => {
+ try {
+ await $`ls`;
+ } catch (error) {
+ console.warn("Warning: Could not list parent directory contents");
+ }
+ },
}))
ports/asdf_plugin_git.ts (3)
3-3
: LGTM: Import additions are properly organized.
The new imports AllowedPortDep
and getPortRef
are correctly placed and will be used by the new buildDep
function.
Also applies to: 7-7
54-61
: LGTM: Well-structured build dependency configuration.
The buildDep
function correctly implements the AllowedPortDep
interface, providing both the manifest and default instance configuration.
Line range hint 80-93
: Track download path handling improvement.
The existence check is a good temporary solution, but as noted in the FIXME comment, this should be handled by core download tracking in the future.
Would you like me to create an issue to track the implementation of core download tracking? This would help ensure this temporary solution doesn't become permanent.
Let's verify the download path handling:
✅ Verification successful
Download path existence check is consistent with other implementations
The existence check for downloadPath
is currently implemented in two ports: asdf_plugin_git.ts
and pipi.ts
. Both implementations follow the same pattern of skipping the download if the path exists. While this is marked as a temporary solution with a FIXME comment, it's consistent across the codebase.
ports/pipi.ts
: Uses the same download path existence check patternports/asdf_plugin_git.ts
: Implements the check with an additional FIXME comment
The core download tracking enhancement should be implemented at the framework level to benefit all ports uniformly, rather than addressing it in individual ports.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for other similar download path checks that might need the same improvement
rg -A 2 "downloadPath.*exists\(\)" --type typescript
Length of output: 89
Script:
#!/bin/bash
# Check for other similar download path checks using ripgrep without file type filter
rg -A 2 "downloadPath.*exists\(\)"
# Also check for any other download-related existence checks
rg -A 2 "\.exists\(\)" ports/
Length of output: 3772
ports/node.ts (1)
47-61
: LGTM! Well-structured method overrides.
The overridden methods are properly implemented:
execEnv
correctly sets up the NODE_PATH environment variablelatestStable
appropriately delegates to the common implementationlistLibPaths
intentionally returns an empty array to avoid including node_module sources
ports/wasmedge.ts (1)
66-73
: Verify the commented environment variables.
There are two commented environment variables (WASMEDGE_LIB_DIR
and WASMEDGE_INCLUDE_DIR
) that might be important for WasmEdge configuration. Are these intentionally disabled or planned for future implementation?
Let me help verify if these environment variables are required:
ports/npmi.ts (1)
Line range hint 84-92
: LGTM! Verify parent class method exists.
The addition of the override
keyword improves type safety by explicitly declaring the method overrides a parent class method.
Let's verify the parent class method exists:
✅ Verification successful
override
keyword is correctly used - parent class has abstract method
The download
method in ports/npmi.ts
correctly uses the override
keyword as it implements the abstract method download(args: DownloadArgs)
declared in the parent class PortBase
(found in modules/ports/base.ts
).
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that the download method exists in the parent class (PortBase)
# Expected: Find the download method declaration in the parent class
ast-grep --pattern 'class PortBase {
$$$
download(args: DownloadArgs) {
$$$
}
$$$
}'
Length of output: 98
Script:
#!/bin/bash
# Let's try a broader search to find the parent class and its method
# First, let's find files containing PortBase
rg "class PortBase" -A 10
# Also search for abstract method declaration
rg "abstract.*download.*DownloadArgs"
# Let's also check if it's in an interface
rg "interface.*Port.*download.*DownloadArgs"
Length of output: 759
tests/reloadHooks.ts (1)
41-44
: Address FIXME: Decision needed on ghjk_reload behavior in non-interactive shells.
The commented test and FIXME indicate an unresolved decision about whether ghjk_reload
should run by default in non-interactive shells. This is a critical architectural decision that needs to be finalized.
Would you like me to:
- Open an issue to track this architectural decision?
- Help document the behavior once decided?
ports/asdf.ts (3)
Line range hint 96-115
: LGTM! Robust implementation with proper error handling.
The method correctly handles:
- Binary path verification
- Environment variable setup
- Output parsing with empty string filtering
Line range hint 116-136
: LGTM! Well-structured implementation with proper error handling.
The method appropriately:
- Handles missing download scripts
- Sets all required environment variables
- Returns early when binary is not found
Line range hint 75-95
: Address the FIXME comment regarding required environment variables.
The comment indicates that ASDF's requirement for ASDF_INSTALL_VERSION
in latest-stable
is questionable. This should be investigated and documented properly.
Would you like me to help investigate this issue and propose a proper fix?
Additionally, consider handling the case where args.config.version
is undefined more explicitly:
- ASDF_INSTALL_VERSION: args.config.version ?? "",
+ ASDF_INSTALL_VERSION: args.config.version || "latest",
ports/cpy_bs.ts (1)
Line range hint 64-71
: LGTM! Verify Python executable path construction.
The execEnv
override looks correct. However, let's verify that the Python executable path is constructed correctly across different platforms.
✅ Verification successful
Python executable path construction is consistent across the codebase
The verification shows that the Python executable path construction in execEnv
is consistent with other usages in the codebase:
- The path always uses
bin/python3
structure - The
REAL_PYTHON_EXEC_PATH
environment variable is correctly referenced in dependent ports (e.g.,pipi.ts
) - The path construction aligns with how Python executables are invoked in tests and other ports
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify Python executable path construction across the codebase
# Test: Search for other Python executable path constructions for consistency
rg -g '*.ts' -g '*.js' 'python3|REAL_PYTHON_EXEC_PATH' -A 2
Length of output: 1556
tests/ports.ts (5)
Line range hint 9-14
: LGTM: Well-structured type definition.
The CustomE2eTestCase
type properly extends E2eTestCase
with clear property definitions and appropriate types.
Line range hint 224-232
: LGTM: Comprehensive shell testing.
The test harness appropriately tests commands across multiple shell environments (bash, fish, zsh), ensuring broad compatibility.
Line range hint 233-244
: Consider implementing the suggested InstallDb tests.
The commented FIXME indicates a need for better InstallDb testing. The current timeout-based approach might not be the most reliable way to test the installation database.
Let's check for existing InstallDb tests:
#!/bin/bash
# Search for existing InstallDb tests
rg -l "InstallDb.*test"
Would you like help implementing a more robust testing strategy for InstallDb?
193-195
: Verify the necessity of duplicate secureConf configurations.
Both 'cargobi-sd' test cases have identical secureConf
configurations. Consider extracting this into a shared configuration if these are truly meant to be the same.
Let's check if this pattern exists elsewhere:
#!/bin/bash
# Search for other similar secureConf patterns
rg -A 3 'secureConf: \{.*enableRuntimes: true' tests/
Also applies to: 208-210
15-16
: Address missing test coverage for asdf.
The FIXME comment indicates that a test for 'asdf' is missing. This could impact the completeness of the test suite.
Let's check if there are any references to asdf tests in the codebase:
Would you like me to help create the missing test case for asdf?
README.md (2)
38-44
: LGTM!
Clear and well-structured list of prerequisites.
106-109
: LGTM!
Clear demonstration of the builder syntax with proper method chaining.
ports/cargobi.ts (1)
104-106
: LGTM!
The latestStable
method correctly overrides the parent class method and delegates to the utility function.
install/mod.ts (1)
204-212
: LGTM! Improved installation robustness.
The changes enhance the installation process by:
- Ensuring the installation directory exists before proceeding
- Moving the executable installation log to debug level, which is more appropriate for this technical detail
modules/ports/worker.ts (2)
Line range hint 204-216
: LGTM: Appropriate override implementation.
The override
keyword addition correctly indicates that this method implements a superclass method, and the implementation properly handles worker communication and error cases.
Line range hint 217-230
: LGTM: Well-structured override implementation.
The override
keyword addition and implementation are correct, maintaining type safety and consistent error handling.
tests/envs.ts (2)
54-58
: Well-structured deactivation tests!
The new deactivation tests thoroughly verify that:
- Environment-specific variables are cleared
- GHJK_ENV system variable is cleared
- The cleanup is consistent across shell variants
This ensures proper isolation between different environment activations.
Also applies to: 87-91
51-51
: Verify the rationale for exit code changes.
The exit codes have been changed from 3-digit (101) to 4-digit numbers (1010, 1011, etc.) in both Posix and Fish shell test scripts. While this makes the error codes more specific, it would be helpful to understand:
- The reasoning behind this change
- Whether these codes map to specific error categories
- If there's documentation for these error codes
Also applies to: 54-58, 68-68, 87-91
✅ Verification successful
Exit code changes are part of test refactoring
After analyzing the codebase, the change from 3-digit to 4-digit exit codes appears to be a deliberate test refactoring pattern where:
- 3-digit codes (101-108) are used for general test assertions
- 4-digit codes (1010-1014) are specifically used for environment-related checks
- The changes are consistent across both POSIX and Fish shell tests
The exit codes follow a logical grouping:
- 101-108: General test assertions
- 1010-1014: Environment variable checks
- 1022: Deactivation checks
This change improves test organization by making environment-specific failures more distinguishable from general test failures.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any error code documentation or constants
rg -i "error.*code|exit.*code" --type md
Length of output: 42
Script:
#!/bin/bash
# Let's search for exit codes in all files to understand their usage pattern
rg "\bexit\s+\d{3,4}\b" -n
# Also search for any comments or documentation near these exit codes
rg -B2 -A2 "\bexit\s+\d{3,4}\b"
Length of output: 17495
mod.ts (1)
122-125
: LGTM!
The type extension is well-integrated and properly documented.
modules/ports/mod.ts (1)
144-144
: LGTM: Consistent command description formatting.
The addition of a period at the end of the command description maintains consistency in documentation formatting.
modules/envs/posix.ts (4)
241-243
: LGTM! Clear and important documentation.
The added comment clearly explains that the script must be sourced and not executed directly, which is crucial for proper environment setup.
Line range hint 258-285
: LGTM! Robust environment variable handling.
The improved logic for tracking and restoring environment variables is well-implemented and thoroughly documented. The handling of unset variables and shell escaping is particularly robust.
307-307
: LGTM! Clear documentation of performance optimization.
The comment effectively explains the purpose of using a shim to improve latency.
Line range hint 351-378
: LGTM! Well-implemented Fish shell support.
The Fish shell implementation is clean and well-documented:
- Effectively handles environment variable tracking and restoration
- Takes advantage of Fish's simpler quoting rules
- Maintains parity with the POSIX implementation while being more concise
.ghjk/lock.json (5)
9-34
: Version updates require verification of dependency compatibility.
Several version updates have been made:
act_ghrel
updated to v0.2.69pre-commit
updated to 4.0.1- Build dependencies updated:
cpy_bs_ghrel
: 3.12.7tar_aa
: 1.35zstd_aa
: v1.5.6
These updates should be tested to ensure compatibility.
#!/bin/bash
# Description: Check for version-specific imports or dependencies
# Look for version constraints or requirements in the codebase
# Search for version requirements
rg -g '*.{ts,js,py}' -A 3 'require.*version|version.*require'
# Search for potential breaking changes in imports
rg -g '*.{ts,js,py}' -A 3 'import.*from.*@[0-9]'
72-98
: New module 'vale' added with dependencies.
A new module vale
(version 3.8.0.0) has been added with its build dependencies. Ensure that:
- The version is stable and production-ready
- All required build dependencies are properly configured
- The module is compatible with x86_64-linux platform
#!/bin/bash
# Description: Verify vale module configuration and dependencies
# Check for vale-related configurations
rg -g '*.{ts,js,py,json}' -A 5 'vale.*config|config.*vale'
# Look for potential vale usage patterns
rg -g '*.{ts,js,py}' -A 3 'import.*vale|require.*vale'
124-131
: Verify build dependency allowlist configuration.
The allowedBuildDeps
configuration has been updated in both main and test environments. Ensure that:
- The referenced dependency ID exists
- The dependency has all required permissions
#!/bin/bash
# Description: Verify build dependency configuration
# Check if the dependency ID exists in the configuration
rg "bciqicqqpm2733snzw4pmjnkbw7qbbji7t7cpwj2nbrok6abrzauooqa" -A 5 -B 5
# Look for any security-related configurations
rg -g '*.{json,ts}' "allowedBuildDeps.*security|security.*allowedBuildDeps"
3-3
: Verify platform compatibility for x86_64-linux.
The platform has been changed from aarch64-darwin
to x86_64-linux
. This is a significant architectural change that could affect binary compatibility.
✅ Verification successful
Platform change to x86_64-linux is fully supported
After analyzing the lock file, all dependencies explicitly support the x86_64-linux platform:
- act_ghrel: supports "x86_64-linux" among other platforms
- pipi_pypi (pre-commit, vale): supports "x86_64-linux" among other platforms
- deno_ghrel: supports "x86_64-linux" among other platforms
- All ambient access tools (tar, git, curl, etc.) support "x86_64-linux"
The platform change from aarch64-darwin to x86_64-linux is safe as all dependencies have explicit platform compatibility declarations that include x86_64-linux.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that all dependencies support x86_64-linux platform
# Look for platform specifications in the manifest sections
rg -A 10 '"platforms":\s*\[' | grep -B 1 -A 10 'x86_64-linux'
Length of output: 243
Script:
#!/bin/bash
# Let's try a different approach to verify platform compatibility
# First, let's check the content of the lock file
cat .ghjk/lock.json
# Also search for any platform-specific configurations or build scripts
fd -e json -e yaml -e yml | xargs rg -l "platform|arch|x86_64|aarch64"
Length of output: 18010
578-589
: Verify dependency mapping consistency.
The dependency mappings in the blackboard section have been updated. Ensure that:
- All referenced IDs exist in the configuration
- The mappings are consistent with the platform change
✅ Verification successful
All dependency mappings are consistent and properly referenced
After examining the lock.json file content, I can confirm that:
- All IDs in the blackboard section are properly defined in the configuration
- The mappings are consistent with the platform dependencies
- Each ID is referenced appropriately in the configuration structure
- The dependency chain is complete and valid
The verification shows that the dependency mappings in the blackboard section are correctly maintained and there are no dangling or invalid references.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify dependency mapping consistency
# Extract all dependency IDs
rg -o 'bciq[a-z0-9]{48}' | sort -u > /tmp/all_ids
# Check for any dangling references
while IFS= read -r id; do
count=$(rg -c "$id" | wc -l)
if [ "$count" -eq 1 ]; then
echo "Potential dangling reference: $id"
fi
done < /tmp/all_ids
Length of output: 56
Script:
#!/bin/bash
# Let's try a different approach to verify dependency mappings
# First, let's check if there are any references to these IDs in other files
for id in bciqicqqpm2733snzw4pmjnkbw7qbbji7t7cpwj2nbrok6abrzauooqa \
bciqb6ua63xodzwxngnbjq35hfikiwzb3dclbqkc7e6xgjdt5jin4pia \
bciqfl5s36w335ducrb6f6gwb3vuwup7vzqwwg67pq42xtkngsnxqobi \
bciqcfe7qyxmokpn6pgtaj35r5qg74jkehuu6cvyrtcsnegvwlm64oqy \
bciqgkpwxjmo5phw5se4ugyiz4xua3xrd54quzmk7wdwpq3vghglogjy \
bciqmcvyepuficjj3mwshsbfecwdmzch5gwxqo557icnq4zujtdllh4a \
bciqk4ivbyqvpxwcaj5reufmveqldiizo6xmqiqq7njtaczgappydoka \
bciqpgt5wsiw4y7qzovqbt2yrdgq5mvhhjpcg6cxzt4w4taudyen44ca \
bciqakxf4wsx3mtku4x5exrl44k4r4kyq6gaw4va5hsb3v26cipmmekq \
bciqboouqnp54fnumgxvl7uay2k6ho4vhlbibvgoyyt5yt3rkwqaohzi \
bciqhjmjvlo4aqvwxjkrmoiledobmhkfe7iovqe3wndxiw2aootwn4lq \
bciqoxx4uhfhw77sux6kzqhy6bvxhxkk4cqigrxdrmggillzkfjgjnli; do
echo "Checking references for $id:"
rg "$id" --type json
done
# Also check the structure of the lock file
echo -e "\nLock file structure:"
fd -e json -x head -n 20 {}
Length of output: 11824
Script:
#!/bin/bash
# Let's check the actual lock.json file content and structure
echo "Checking lock.json content:"
fd -g 'lock.json' -x cat {}
# Also let's check if there are any other JSON files that might reference these IDs
echo -e "\nChecking all JSON files for dependency references:"
fd -e json -x grep -l "bciq[a-z0-9]" {} || true
Length of output: 262
Script:
#!/bin/bash
# Let's try a different approach to locate and examine the lock file
echo "Finding lock.json files:"
find . -name "lock.json" -type f
echo -e "\nTrying to read .ghjk/lock.json specifically:"
cat .ghjk/lock.json 2>/dev/null || echo "File not accessible"
echo -e "\nChecking parent directories of lock.json:"
find . -name "lock.json" -type f -exec dirname {} \;
Length of output: 18315
host/mod.ts (1)
381-390
: LGTM! Efficient hash file writing implementation.
The implementation correctly handles:
- Conditional writing based on locked state
- Prevention of unnecessary writes through deep equality comparison
- Proper serialization status tracking
ports/pipi.ts (1)
65-67
: Good use of the 'override' keyword for method clarity
Adding the override
keyword to the latestStable
method explicitly indicates that it overrides a method from the superclass. This enhances code readability and helps prevent accidental method mismatches.
files/mod.ts (2)
28-28
: Ensure Correct Import Path and Consistent Naming
The import statement adds runtime_ports
from "../modules/ports/std_runtime.ts"
. Please verify that the file path is correct and that the module exists at the specified location. Also, ensure that the naming convention aligns with existing imports (e.g., std_ports
) for consistency.
1087-1090
: Confirm Compatibility of runtime_ports
in stdDeps
Function
In the stdDeps
function, you're spreading runtime_ports
within the array passed to reduceAllowedDeps
. Ensure that runtime_ports
is an iterable containing elements compatible with AllowedPortDep[]
. This will prevent potential runtime errors due to incompatible types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 12
🧹 Nitpick comments (83)
modules/mod.ts (1)
11-15
: Consider standardizing return type for asynchronous consistency
This method can return eitherPromise<void>
orvoid
. If usage across implementors is consistently asynchronous, consider always returning aPromise<void>
to avoid confusion.-abstract loadConfig( - manifest: ModuleManifest, - bb: Blackboard, - lockEnt: LockEnt | undefined, -): Promise<void> | void; +abstract loadConfig( + manifest: ModuleManifest, + bb: Blackboard, + lockEnt: LockEnt | undefined, +): Promise<void>;src/ghjk/systems.rs (1)
40-119
: Erased system instance pattern
TheErasedSystemInstance
design properly abstracts away type details, letting callers manage dynamic, heterogeneous system instances. The usage of closures to box trait methods is robust, but remain mindful of performance overhead.src/deno_systems/bindings.ts (4)
1-5
: Clarify the offline mechanism comment or remove dead code
These lines contain purely commented text referencing “offline” functionality which may cause confusion if left in the code with no operational references.
16-18
: Reevaluate empty setInterval for keep-alive
Using a one-second interval with an empty body effectively forces the event loop to remain active. Although this works, confirm whether a more explicit, deterministic solution is preferred (e.g., awaiting a controlled promise or using a dedicated keep-alive mechanism).
56-86
: Consider error recovery or partial registration
TheprepareSystems
function processes systems in a loop and registers them at line 85. If a singleimport
fails orsafeParse
returns errors for part of the data, consider implementing partial recoveries or fallback logic (e.g., skipping a faulty system rather than halting the entire process).
100-153
: Instance binding callbacks
TheinstanceBinding
function creates a series of unique callback properties for config loading, lock entry, and CLI commands. This design is intuitive, but be cautious of potential memory growth if many instances are spun up since each callback is stored inGhjk.callbacks
. Consider removing or cleaning up callbacks for instances no longer in use.src/ghjk/ext.rs (2)
55-63
:inject
method handles state injection
This logic is straightforward, but be mindful of potential collisions with previously stored contexts inOpState
. If another extension modifies or replacesExtContext
, ensure there’s no conflict.
144-156
: Exception dispatch design
op_dispatch_exception2
sends exceptions through ampsc::UnboundedSender<eyre::Report>
if available. Verify whether buffering large bursts of exceptions must be handled—an unbounded channel can risk memory usage growth if exceptions are produced rapidly.src/ghjk/utils.rs (1)
242-261
: Recursive file search
find_entry_recursive
ascends until no parent is available. This is correct but can lead to reading a large number of parents for deeply nested paths. This is likely fine for typical usage, though you may want to short-circuit or set a max depth if performance or security is a concern.src/ghjk/host/hashfile.rs (2)
26-58
:from_result
usesfile_digests
When computing file digests (line 49), consider handling large or missing files gracefully. A single error fromfile_digests
is fatal. If partial generation of theHashObj
is acceptable, wrap in a pattern that allows ignoring compromised files.
149-180
: Skipping large file hashing
Using aLARGE_FILE_THRESHOLD
is a practical optimization. If certain large files are critical to the system, ensure they’re not silently missed. You might log a warning or store partial data to let users know these files were skipped.src/denort/unsync.rs (2)
50-65
:spawn
usage with single-thread
Masking the future asSend
is an effective approach if the code is guaranteed to remain on a single-thread runtime. Ensure that no external calls migrate tasks to a multi-threaded runtime, as this can lead to undefined behavior.
265-280
:abort_all
vsdetach_all
usage
Aborting all tasks vs detaching them can lead to significantly different performance and memory usage patterns. Provide ample documentation or disclaimers for library consumers to clarify the difference and potential ramifications.src/ghjk/systems/deno.rs (5)
10-17
: Consider refining concurrency management inDenoSystemsContext
TheArc<std::sync::Mutex<Option<tokio::task::JoinHandle<Res<()>>>>>
pattern can be tricky for concurrency, especially if multiple callers attempt termination concurrently. Alternative approaches (e.g., channels or single-flight abstractions) can often reduce locking complexity and potential race conditions.
34-60
: Break down the largesystems_from_deno
function
The function is fairly long and contains multiple steps for constructing configurations, preparing modules, and setting up the worker. Consider splitting it into smaller helper functions (e.g., for constructing the config, registering hostcalls, etc.). This can improve readability, maintainability, and testability.
103-125
: Check permissions and environment during module preparation
Whileallow_all: true
is a convenient default for development, consider restricting permissions in production or when running untrusted code in Deno. Fine-grained permissions help mitigate security risks.
128-138
: Clarify "premature exit" scenario
The error message “premature exit … before manifests were sent” is appropriate, but a custom error type might be beneficial for clarity. This helps downstream error handling or logs to distinguish it from other run errors.
144-181
: Ensure error handling for event-loop exceptions
The loop that logs errors caught by theexception_line.recv()
is beneficial. Having an optional retry or additional context for repeated failures might help maintain system resiliency if the cause is transient.src/ghjk/config.rs (3)
13-25
: Use of#[serde(flatten)]
Flattening fields inLocalConfigFile
is a neat approach for merging global config data. Just be cautious about naming collisions if fields overlap in future expansions.
64-85
: Auto-creation of.ghjk
directory
The logic automatically creating the directory and.gitignore
is user-friendly. Consider logging more details (e.g., the final path) at info level to assist in debugging.
225-260
:source_env_config
final layering
Sourcing environment variables last aligns with the typical override strategy. Just ensure environment variables that disable certain features (deno_lockfile = "off"
) are documented so that developers know about this special string.src/ghjk/ext/callbacks.rs (4)
26-29
:CallbackCtx
concurrency
Wrappingmsg_rx
andterm_signal
in a single struct is clear. However, if you anticipate multiple watchers or additional signals, consider grouping them with a typed concurrency pattern or higher-level abstraction for better extendibility.
31-65
:CallbackLine
design
The concept of “taking” the callback line once is well-explained. If you expect advanced scenarios (reload, partial teardown), consider re-initializing or reattaching the line.
92-103
:CallbacksMsg
enum is minimal and sufficient
Right now there is onlyExec
. Should new message types (e.g., to remove or update a callback) be needed in the future, ensuring backward compatibility is crucial.
283-317
:op_callbacks_set
usage
Registering the callback in aHashMap
keyed byString
is straightforward. Just be mindful of potential memory leaks if callbacks are registered dynamically in large numbers without clearing or reinitializing.src/denort/lib.rs (3)
3-9
: Module exports and submodules
Exportingdeno
and submodules (macros
,promises
, etc.) is clear. Ensure that only relevant APIs are re-exported publicly to avoid unintentional usage from consumers.
60-81
:run_sync
spawns a dedicated thread
This design pattern is beneficial if the main thread is not intended to be blocked. Handling errors by unwrapping the join result is pragmatic; consider more explicit error capturing if partial failures must be logged or processed.
83-124
:run
function
The fallback toDefault::default()
for flags is terse but can mask missing settings if they are not provided. Ensuring robust validation or logging of the final flags helps in diagnosing issues.src/ghjk/systems/deno/cli.rs (2)
6-27
:CliCommandDesc
structure
Defining fields likehide
,aliases
, andabout
allows for flexible CLI definitions. Just ensure thataliases
vs.visible_aliases
usage is explicitly documented for user clarity.
29-115
:CliCommandDesc::convert
method
This method elegantly transforms JSON-based descriptors intoclap::Command
definitions. The usage ofdisable_help_subcommand
, subcommands, and an optionalaction_cb_key
is flexible. Watch for potential panics (like line 71panic!(...)
) by providing a friendlier error message or fallback when IDs clash.src/ghjk/host.rs (2)
83-99
: Avoid potential confusion with interactive discarding logic.When the lockfile is corrupt and the user declines discarding it, the function errors out. In CI or non-interactive contexts, this might unintentionally break builds. Consider a fallback, a retry, or an explicit non-interactive path.
289-303
: Lockfile updates are discarded iflocked
is set.This default is sensible, but end-users might expect a warning or an error rather than just a trace log. Possibly consider an explicit message confirming the lockfile is unchanged due to
locked
.src/ghjk/cli.rs (2)
14-21
: Remove or justify commented-out thread logging.These lines are commented out debugging logs. Consider removing them if they are no longer needed or documenting their purpose to prevent confusion.
- /* tokio::spawn({ - async { - loop { - println!("{:?}: thread is not blocked", std::thread::current().id()); - tokio::time::sleep(std::time::Duration::from_secs(2)).await; - } - } - }); */
130-148
: Ensure full coverage of Clap error handling.At lines 130-148, only certain error types trigger lockfile writes or immediate exit. Confirm that
ErrorKind::UnknownArgument
and other possible Clap errors are also handled, if they may arise.src/denort/worker.rs (3)
28-41
: Avoid silent termination inselect!
.When
term_signal_rx2.changed()
ends orNone
frommsg_rx
, the loop breaks. Consider logging a more explicit message or capturing the reason for termination (e.g., “deno worker messages ended” vs. “termination signal set”), so debugging is more straightforward.
57-57
: Commented-out memory management.
// std::mem::forget(cx);
is commented out. If you intend to keep the worker context in memory or avoid dropping it, consider clarifying with a code comment. Otherwise, remove commented code to reduce confusion.
74-89
: Consider capacity in MPSC channels.The capacity is set to
1
or32
in different channels. Evaluate if backlog spikes could occur, potentially blocking sender tasks. If there's a risk of saturating the channel, either handle backpressure or raise the capacity.src/deno_systems/mod.ts (1)
4-10
: Consider lazy/dynamic loading for systems.Creating constructor closures for each system at initialization can be fine. However, if modules are large or numerous, a lazy-loading approach could improve startup performance by deferring system construction until needed.
src/denort/macros.rs (1)
3-5
: Correct spelling and grammar in inline comments.Minor typos noticed:
- "funciton" → "function"
- "it's Error type" → "its Error type"
-// This can be made a funciton but we have to +// This can be made a function but we have to -// to it's Error type. +// to its Error type.install/utils.ts (1)
7-7
: Clarify usage note for the embedded runtime shim.The comment sufficiently explains the assumption that this is running in the embedded deno runtime. Consider referencing any external docs or the user manual for additional clarity on usage or environment differences.
src/ghjk/js/00_runtime.js (3)
1-3
: Ensure robust error handling when accessing Deno core operations.
The usage of thecore
andops
objects looks straightforward. However, consider surrounding this usage with try/catch blocks or additional checks to handle potential failures or permission errors from Deno.
9-22
: ImprovegetOp
function documentation and checks.
The logic ingetOp
is clear. To enhance clarity, consider adding doc comments detailing the expected behavior if operations are missing. Additionally, you might log a more user-friendly message before throwing the error.
24-24
: Provide a descriptive name or inlined comment forop_callbacks_set
.
The identifierop_callbacks_set
is self-explanatory at first glance, but consider adding a short doc comment describing its purpose. This can help new contributors quickly understand the operation’s role in callback management.files/deno/bindings.ts (1)
14-16
: Validate URI inputs with additional constraints.
Whilezod.string()
ensures the input is a string, the URI might need further validation, for instance ensuring it’s a valid URL or file path. Adding.url()
or a custom check can prevent unexpected runtime errors.install.ts (1)
30-31
: Customize directory handling logic.
The newghjkDataDir
environment-based logic is straightforward, but ensure that users are fully aware of how to override or switch directories. Possibly consider adding a fallback or providing a warning if the directory does not exist.src/ghjk/main.rs (1)
65-72
: PublicGhjkCtx
struct might benefit from derived traits
GhjkCtx
is a fundamental struct. Consider deriving traits likeClone
,Serialize
, or others as needed for testability or logging. This might improve maintainability in the future.ports/fx_ghrel.ts (2)
30-63
: Robust architecture detection with fallback or error handlingIn
downloadUrls()
, you handle platform architecture thoroughly, but ensure a fallback approach or improved error messaging if new architectures emerge. Having a single error for unsupported platforms is good, but more granular messages can help debugging.
65-72
: Efficient cleanup strategy in theinstall
methodClearing the install path before copying avoids stale files. Verify whether partial installs could produce partially removed directories in some environments. Logging a message before removing could further clarify behavior.
src/ghjk/host/deno.rs (1)
14-92
: Consider deduplicating file paths inread_file_paths
.When appending the loaded modules to
read_file_paths
, duplicate entries may appear in certain cases. To eliminate duplicates and prevent repeated file lookups, consider using aHashSet
or a similar approach.Below is an example diff:
let mut read_file_paths = resp.read_file_paths; - read_file_paths.append(&mut loaded_modules); + use std::collections::HashSet; + let mut unique_set = HashSet::from_iter(read_file_paths.into_iter()); + unique_set.extend(loaded_modules); + let read_file_paths = unique_set.into_iter().collect::<Vec<_>>();src/denort/promises.rs (1)
20-71
: Validate the closure’s failure modes and unhandled rejections.While wrapping a promise ensures that errors do not produce unhandled rejection warnings, consider whether you want to bubble up such errors or rethrow within the handler to maintain standard rejection flows.
modules/ports/sync.ts (1)
521-528
: Correct the minor typo in the error message.There is a small typographical error in line 522: "verison" → "version".
Here is a proposed fix:
- `error resolving verison ${config.version}: not found, available versions: [${ + `error resolving version ${config.version}: not found, available versions: [${.cargo/config.toml (1)
1-10
: Aliases and Rust flags look good.The newly introduced
[alias]
section improves developer convenience when runningxtask
. Thetokio_unstable
configuration is appropriate for accessing advanced features intokio-rs/console
, but consider verifying compiler compatibility across different environments if your team uses stable-only environments.docs/known-issues.md (3)
6-6
: Add comma for better readabilityAdd a comma before "especially" to improve readability.
-Since many of the ports get their files from GitHub releases, it's easy to get past this limit especially in CI contexts. +Since many of the ports get their files from GitHub releases, it's easy to get past this limit, especially in CI contexts.🧰 Tools
🪛 LanguageTool
[typographical] ~6-~6: Consider inserting a comma for improved readability.
Context: ...leases, it's easy to get past this limit especially in CI contexts. This will manifest in f...(MISSING_COMMAS)
19-23
: Consider additional security measures for token handlingWhile the current documentation correctly warns about token leakage, consider adding:
- Instructions for token cleanup in git pre-commit hooks
- Documentation about using environment-specific token handling
- Reference to
.gitignore
patterns for lock files containing sensitive dataWould you like me to provide example implementations for these security measures?
24-28
: Add warning about data lossThe command sequence will reset all port configurations. Consider adding a warning about potential data loss.
```bash +# Warning: This will reset all port configurations rm .ghjk/lock.json # this command will re-resolve all ports ghjk p resolve
</blockquote></details> <details> <summary>.github/workflows/nightly.yml (1)</summary><blockquote> `42-51`: **Consider consolidating duplicate package installation logic** The package installation steps for Ubuntu and macOS have similar dependencies (fish, zsh, cmake). Consider extracting this into a composite action to reduce duplication and improve maintainability. </blockquote></details> <details> <summary>src/ghjk/Cargo.toml (2)</summary><blockquote> `15-16`: **Consider specifying exact versions for serde dependencies** Using just the major version (`"1"`) for `serde` and `serde_json` could lead to unexpected breaking changes. Consider pinning to specific versions for better reproducibility. --- `65-66`: **Address TODO comment about config formats** The TODO comment indicates potential support for more config formats. Consider: 1. Creating an issue to track this enhancement 2. Documenting which additional formats are planned Would you like me to create a GitHub issue to track the implementation of additional config formats? </blockquote></details> <details> <summary>.github/workflows/tests.yml (1)</summary><blockquote> `89-102`: **Remove commented out code** If the test-action job is no longer needed, it should be removed rather than left commented out. </blockquote></details> <details> <summary>modules/tasks/mod.ts (1)</summary><blockquote> Line range hint `96-109`: **Enhance error message clarity** The error message for version tag mismatch could be more descriptive. ```diff - throw new Error(`unexpected version tag deserializing lockEntry`); + throw new Error(`Unexpected version tag '${entry.version}' while deserializing lockEntry. Expected '0'.`);
.github/workflows/release.yml (2)
1-19
: Fix typo in input parameter name and descriptionThere's a typo in the
ovewriteArtifacts
input parameter.- ovewriteArtifacts: - description: Ovewrite artifacts on the release. Some will only be skipped. + overwriteArtifacts: + description: Overwrite artifacts on the release. Some will only be skipped.
61-63
: Track FIXME comment as an issueThe FIXME comment about musl support should be tracked in the issue tracker.
Would you like me to create a GitHub issue to track the musl support requirement?
install/hook.fish (2)
4-4
: Consider improving timestamp handling for other platforms.The fallback case uses Linux's stat format which might not work on other platforms. Consider:
- Adding specific handling for other common platforms.
- Using Deno's timestamp functionality consistently across all platforms for uniformity.
Also applies to: 6-10
121-127
: Consider extracting auto-hook validation logic.The multiple conditions for GHJK_AUTO_HOOK validation could be simplified into a helper function for better readability and reusability.
+function is_auto_hook_enabled + test -n "$GHJK_AUTO_HOOK"; \ + and test $GHJK_AUTO_HOOK != "0"; \ + and test $GHJK_AUTO_HOOK != "false"; \ + and test $GHJK_AUTO_HOOK != "" +end -if set --query GHJK_AUTO_HOOK; and begin; - test $GHJK_AUTO_HOOK != "0"; - and test $GHJK_AUTO_HOOK != "false"; - and test $GHJK_AUTO_HOOK != "" -end; or status is-interactive; +if is_auto_hook_enabled; or status is-interactive; ghjk_hook endinstall/hook.sh (2)
10-12
: Consider unifying timestamp handling across shell scripts.The timestamp handling logic is duplicated between fish and sh scripts. Consider extracting this into a shared script that both shells can source.
121-136
: Consider simplifying shell mode detection logic.The current implementation is verbose and could be simplified. Consider extracting the auto-hook check into a function, similar to the suggestion for the fish script.
+is_auto_hook_enabled() { + [ -n "${GHJK_AUTO_HOOK+x}" ] && [ "$GHJK_AUTO_HOOK" != "0" ] && [ "$GHJK_AUTO_HOOK" != "false" ] +} case "$-" in *i*) - if [ -z "$GHJK_AUTO_HOOK" ] || [ "$GHJK_AUTO_HOOK" != "0" ] && [ "$GHJK_AUTO_HOOK" != "false" ]; then + if is_auto_hook_enabled; then ghjk_hook fi ;; *) - if [ -n "${GHJK_AUTO_HOOK+x}" ] && [ "$GHJK_AUTO_HOOK" != "0" ] && [ "$GHJK_AUTO_HOOK" != "false" ]; then + if is_auto_hook_enabled; then ghjk_hook fi : ;; esacinstall/mod.ts (1)
108-121
: Enhance error handling in home directory detection.While the platform detection is good, the error message could be more informative by including the current platform and environment variables.
const homeDir = getHomeDir(); if (!homeDir) { - throw new Error("cannot find home dir"); + throw new Error( + `Cannot find home directory for platform ${Deno.build.os}. ` + + `Checked environment variables: ${Deno.build.os === "windows" ? "USERPROFILE" : "HOME"}` + ); }ports/asdf.ts (2)
127-127
: Add error handling for directory creation.The directory creation should include error handling in case of permission issues or disk space problems.
- await $.path(args.downloadPath).ensureDir(); + try { + await $.path(args.downloadPath).ensureDir(); + } catch (error) { + throw new Error(`Failed to create download directory: ${error.message}`); + }
140-140
: Add error handling for installation directory creation.Similar to the download method, add error handling for directory creation.
- await $.path(args.installPath).ensureDir(); + try { + await $.path(args.installPath).ensureDir(); + } catch (error) { + throw new Error(`Failed to create installation directory: ${error.message}`); + }install.sh (2)
37-77
: Add validation for supported architectures.While the platform detection is comprehensive, it silently skips unsupported architectures. Consider adding explicit error messages for unsupported combinations.
"linux") case "$MACHINE" in "arm64"* | "aarch64"* ) PLATFORM='aarch64-unknown-linux-gnu' ;; *"64") PLATFORM='x86_64-unknown-linux-gnu' ;; + *) echo "Error: Unsupported Linux architecture: $MACHINE" 1>&2; exit 1 ;; esac ;; "darwin") case "$MACHINE" in "arm64"* | "aarch64"* ) PLATFORM='aarch64-apple-darwin' ;; *"64") PLATFORM='x86_64-apple-darwin' ;; + *) echo "Error: Unsupported macOS architecture: $MACHINE" 1>&2; exit 1 ;; esac ;;
133-174
: Enhance user feedback for shell configuration.Consider providing more informative messages about the shell configuration process and what users should expect after the changes.
- printf "Path added to %s\nRun 'source %s' to apply changes." "$SHELL_CONFIG" "$SHELL_CONFIG" + printf "Path added to %s\nTo complete the installation:\n1. Run 'source %s' to apply changes\n2. Verify installation with 'ghjk --version'\n" "$SHELL_CONFIG" "$SHELL_CONFIG"README.md (2)
16-16
: Add hyphen to compound adjective.Change "real world example" to "real-world example" as it's a compound adjective modifying "example".
-This makes it especially convenient for mono-repos and long-lived projects. See [Metatype](https://github.com/metatypedev/metatype) and its [ghjkfile](https://github.com/metatypedev/metatype/blob/main/ghjk.ts) for a real world example. +This makes it especially convenient for mono-repos and long-lived projects. See [Metatype](https://github.com/metatypedev/metatype) and its [ghjkfile](https://github.com/metatypedev/metatype/blob/main/ghjk.ts) for a real-world example.🧰 Tools
🪛 LanguageTool
[uncategorized] ~16-~16: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...pedev/metatype/blob/main/ghjk.ts) for a real world example.<img src...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
143-144
: Fix verb usage: "setup" should be "set up"."Setup" is a noun, while "set up" is the correct verb form.
-This will setup a separate installation at `.dev`. +This will set up a separate installation at `.dev`.🧰 Tools
🪛 LanguageTool
[grammar] ~144-~144: The word “setup” is a noun. The verb is spelled with a space.
Context: ...e that's in the working tree. This will setup a separate installation at.dev
. ```...(NOUN_VERB_CONFUSION)
ghjk.ts (2)
29-54
: Consider extracting logging configuration to a separate constant.The logging configuration could be more maintainable by extracting the module-level configurations into a separate constant or configuration object.
+const LOG_LEVELS = { + TRACE: [], + DEBUG: [], + INFO: [ + "deno::npm", + "deno::file_fetcher", + "swc_ecma_transforms_base", + "swc_common", + "h2", + "rustls", + "mio", + "hyper_util", + ], +}; env("main").vars({ RUST_LOG: [ "info", - Object.entries({ - "TRACE": [], - "DEBUG": [], - "INFO": [ - "deno::npm", - "deno::file_fetcher", - "swc_ecma_transforms_base", - "swc_common", - "h2", - "rustls", - "mio", - "hyper_util", - ], - }).flatMap(([level, modules]) => + Object.entries(LOG_LEVELS).flatMap(([level, modules]) => modules.map((module) => `${module}=${level.toLowerCase()}`) ), ].join(), });
Line range hint
144-205
: Add version string validation.The lock-sed task should validate version strings before applying them.
+const VERSION_PATTERN = /^\d+\.\d+\.\d+(-rc\.\d+)?$/; task( "lock-sed", async ($) => { const GHJK_VERSION = "0.3.0-rc.1"; + if (!VERSION_PATTERN.test(GHJK_VERSION)) { + throw new Error(`Invalid version format: ${GHJK_VERSION}`); + } await sedLock( $.path(import.meta.dirname!), { lines: {host/init/mod.ts (1)
89-184
: Enhance error messages with more context.The error messages could be more specific about what exactly failed during the VS Code settings validation.
- throw new Error(`error parsing JSON at ${vscodeSettings}`, { + throw new Error(`Failed to parse VS Code settings at ${vscodeSettings}. Error: ${err.message}`, { cause: err, }); - originalConfig, + originalConfig, + errorMessage: "Invalid VS Code settings structure. Expected deno.enablePaths or deno.disablePaths to be string arrays.", - }, "unexpected JSON discovored at .vscode/settings.json"); + }, "Invalid VS Code settings structure detected at .vscode/settings.json");mod.ts (2)
54-60
: Enhance type documentation for AddTasks.The AddTasks type could benefit from more detailed documentation about its overloads and usage examples.
/** * Define and register multiple tasks. + * + * @example + * ```typescript + * // Array syntax + * tasks([ + * { name: 'task1', fn: () => {} }, + * async () => {} // unnamed task + * ]); + * + * // Record syntax + * tasks({ + * task1: () => {}, + * task2: { desc: 'Task 2', fn: async () => {} } + * }); + * ``` */ export type AddTasks = {
231-258
: Add input validation for task arguments.The task function should validate its inputs before processing them.
function task( nameOrArgsOrFn: string | DenoTaskDefArgs | TaskFn, argsOrFn?: Omit<DenoTaskDefArgs, "name"> | TaskFn, argsMaybe?: Omit<DenoTaskDefArgs, "fn" | "name">, ) { + // Validate string input + if (typeof nameOrArgsOrFn === "string" && !nameOrArgsOrFn.trim()) { + throw new Error("Task name cannot be empty"); + } + + // Validate object input + if (typeof nameOrArgsOrFn === "object" && !nameOrArgsOrFn.name?.trim()) { + throw new Error("Task definition must include a non-empty name"); + } + let args: DenoTaskDefArgs; // ... rest of the implementationmodules/envs/mod.ts (1)
Line range hint
63-250
: Fix typo in "show" command description.The implementation provides a clean and organized way to handle commands. However, there's a typo in the "about" field of the "show" command - it incorrectly states "Cooks the environment" instead of "Shows environment details".
Apply this diff to fix the typo:
- about: `Cooks the environment to a posix shell.`, + about: `Shows details about an environment.`,Otherwise, the command handling implementation is well-structured and follows good practices for CLI design.
install/bash-preexec.sh (3)
59-60
: Protect against race conditions in global state.The global state variables
__bp_inside_precmd
and__bp_inside_preexec
are used for preventing recursive calls, but they could be affected by race conditions in concurrent scenarios.Consider using a more robust mechanism for state management, such as:
-__bp_inside_precmd=0 -__bp_inside_preexec=0 +declare -A __bp_inside_precmd_pids=() +declare -A __bp_inside_preexec_pids=()Then modify the functions to use the PID as a key:
# In __bp_precmd_invoke_cmd: if [[ -n "${__bp_inside_precmd_pids[$BASHPID]}" ]]; then return fi __bp_inside_precmd_pids[$BASHPID]=1 # ... function body ... unset "__bp_inside_precmd_pids[$BASHPID]"
189-193
: Document potential DEBUG trap conflicts.The script uses the DEBUG trap which could conflict with other debugging tools or scripts that rely on the same trap.
Add a warning comment:
# This function is installed as the DEBUG trap. It is invoked before each # interactive prompt display. Its purpose is to inspect the current # environment to attempt to detect if the current command is being invoked # interactively, and invoke 'preexec' if so. +# WARNING: This implementation uses the DEBUG trap which may conflict with +# other debugging tools. Ensure no other scripts are using this trap. __bp_preexec_invoke_exec() {
277-332
: Add installation success logging.The installation function should provide feedback about successful installation.
Add success logging:
__bp_install() { # Exit if we already have this installed. if [[ "${PROMPT_COMMAND:-}" == *"__bp_precmd_invoke_cmd"* ]]; then + echo "bash-preexec hooks are already installed." >&2 return 1; fi trap '__bp_preexec_invoke_exec "$_"' DEBUG + echo "Successfully installed bash-preexec hooks." >&2🧰 Tools
🪛 Shellcheck (0.10.0)
[warning] 286-286: Declare and assign separately to avoid masking return values.
(SC2155)
[error] 312-312: Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet).
(SC1087)
docs/manual.md (1)
125-126
: Address TODO comments in documentation.There are unresolved TODO comments in the documentation about node-based APIs and fetch shim.
Would you like me to create GitHub issues to track these documentation tasks?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
-
.ghjk/deno.lock
is excluded by!**/*.lock
-
Cargo.lock
is excluded by!**/*.lock
-
deno.lock
is excluded by!**/*.lock
📒 Files selected for processing (82)
-
.cargo/config.toml
(1 hunks) -
.ghjk/lock.json
(10 hunks) -
.github/workflows/nightly.yml
(1 hunks) -
.github/workflows/release.yml
(1 hunks) -
.github/workflows/tests.yml
(4 hunks) -
.gitignore
(1 hunks) -
.pre-commit-config.yaml
(3 hunks) -
.vscode/settings.json
(2 hunks) -
Cargo.toml
(1 hunks) -
README.md
(3 hunks) -
deno.jsonc
(3 hunks) -
deps/common.ts
(1 hunks) -
deps/install.ts
(1 hunks) -
docs/known-issues.md
(1 hunks) -
docs/manual.md
(1 hunks) -
files/deno/bindings.ts
(1 hunks) -
files/deno/mod.ts
(1 hunks) -
files/deno/worker.ts
(1 hunks) -
ghjk.ts
(2 hunks) -
host/init/mod.ts
(1 hunks) -
host/mod.ts
(0 hunks) -
install.sh
(1 hunks) -
install.ts
(2 hunks) -
install/bash-preexec.sh
(1 hunks) -
install/ghjk.sh
(0 hunks) -
install/hook.fish
(2 hunks) -
install/hook.sh
(2 hunks) -
install/mod.ts
(5 hunks) -
install/utils.ts
(1 hunks) -
main.ts
(0 hunks) -
mod.ts
(5 hunks) -
modules/envs/mod.ts
(8 hunks) -
modules/envs/posix.ts
(7 hunks) -
modules/mod.ts
(1 hunks) -
modules/ports/mod.ts
(7 hunks) -
modules/ports/std.ts
(2 hunks) -
modules/ports/sync.ts
(2 hunks) -
modules/ports/worker.ts
(8 hunks) -
modules/tasks/mod.ts
(3 hunks) -
modules/types.ts
(1 hunks) -
ports/asdf.ts
(5 hunks) -
ports/cmake.ts
(0 hunks) -
ports/cpy_bs.ts
(4 hunks) -
ports/fx_ghrel.ts
(1 hunks) -
ports/infisical.ts
(2 hunks) -
ports/livekit_cli_ghrel.ts
(1 hunks) -
ports/mod.ts
(1 hunks) -
ports/npmi.ts
(1 hunks) -
ports/poetry.ts
(1 hunks) -
ports/zstd.ts
(1 hunks) -
rust-toolchain.toml
(1 hunks) -
scripts/check.ts
(0 hunks) -
scripts/dev.ts
(0 hunks) -
src/deno_systems/bindings.ts
(1 hunks) -
src/deno_systems/mod.ts
(1 hunks) -
src/deno_systems/types.ts
(1 hunks) -
src/denort/Cargo.toml
(1 hunks) -
src/denort/lib.rs
(1 hunks) -
src/denort/macros.rs
(1 hunks) -
src/denort/promises.rs
(1 hunks) -
src/denort/unsync.rs
(1 hunks) -
src/denort/worker.rs
(1 hunks) -
src/ghjk/Cargo.toml
(1 hunks) -
src/ghjk/build.rs
(1 hunks) -
src/ghjk/cli.rs
(1 hunks) -
src/ghjk/config.rs
(1 hunks) -
src/ghjk/ext.rs
(1 hunks) -
src/ghjk/ext/callbacks.rs
(1 hunks) -
src/ghjk/host.rs
(1 hunks) -
src/ghjk/host/deno.rs
(1 hunks) -
src/ghjk/host/hashfile.rs
(1 hunks) -
src/ghjk/js/00_runtime.js
(1 hunks) -
src/ghjk/js/mock.sfx.ts
(1 hunks) -
src/ghjk/js/runtime.d.ts
(1 hunks) -
src/ghjk/js/runtime.js
(1 hunks) -
src/ghjk/log.rs
(1 hunks) -
src/ghjk/main.rs
(1 hunks) -
src/ghjk/systems.rs
(1 hunks) -
src/ghjk/systems/deno.rs
(1 hunks) -
src/ghjk/systems/deno/cli.rs
(1 hunks) -
src/ghjk/utils.rs
(1 hunks) -
src/play/Cargo.toml
(1 hunks)
⛔ Files not processed due to max files limit (22)
- src/play/main.rs
- src/xtask/Cargo.toml
- src/xtask/main.rs
- src/xtask/utils.rs
- std/sedLock.ts
- tests/envHooks.ts
- tests/envs.ts
- tests/hashfile.ts
- tests/ports.ts
- tests/portsOutdated.ts
- tests/reloadHooks.ts
- tests/tasks.ts
- tests/test-alpine.Dockerfile
- tests/test.Dockerfile
- tests/test.Dockerfile.dockerignore
- tests/todo.ts
- tests/utils.ts
- tools/check.ts
- tools/dev.ts
- utils/logger.ts
- utils/mod.ts
- utils/unarchive.ts
💤 Files with no reviewable changes (6)
- scripts/check.ts
- ports/cmake.ts
- scripts/dev.ts
- install/ghjk.sh
- main.ts
- host/mod.ts
✅ Files skipped from review due to trivial changes (4)
- .gitignore
- deps/install.ts
- src/play/Cargo.toml
- src/denort/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (8)
- .vscode/settings.json
- ports/npmi.ts
- ports/mod.ts
- ports/cpy_bs.ts
- modules/ports/std.ts
- ports/poetry.ts
- modules/ports/worker.ts
- ports/infisical.ts
🧰 Additional context used
📓 Learnings (1)
README.md (1)
Learnt from: Yohe-Am
PR: metatypedev/ghjk#106
File: README.md:64-73
Timestamp: 2024-11-13T21:37:28.981Z
Learning: In the ghjk project, it's acceptable to use 'https://raw.github.com' in import URLs in `README.md`, as Deno's import system supports redirects and the shorter form is preferred.
🪛 actionlint (1.7.4)
.github/workflows/release.yml
64-64: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
.github/workflows/tests.yml
59-59: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
.github/workflows/nightly.yml
24-24: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
🪛 Shellcheck (0.10.0)
install/bash-preexec.sh
[error] 1-1: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
(SC2148)
[warning] 137-137: BP_PIPESTATUS appears unused. Verify use (or export if used externally).
(SC2034)
[warning] 241-241: Remove space after = if trying to assign a value (for empty string, use var='' ... ).
(SC1007)
[warning] 286-286: Declare and assign separately to avoid masking return values.
(SC2155)
[error] 312-312: Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet).
(SC1087)
🪛 LanguageTool
README.md
[uncategorized] ~16-~16: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...pedev/metatype/blob/main/ghjk.ts) for a real world example.
<img src...
(EN_COMPOUND_ADJECTIVE_INTERNAL)
[grammar] ~144-~144: The word “setup” is a noun. The verb is spelled with a space.
Context: ...e that's in the working tree. This will setup a separate installation at .dev
. ```...
(NOUN_VERB_CONFUSION)
docs/manual.md
[grammar] ~29-~29: The singular determiner ‘this’ may not agree with the plural noun ‘documents’. Did you mean “these”?
Context: ...d ghjkfile is available and the rest of this documents will use typescript for confi...
(THIS_NNS)
[grammar] ~29-~29: Use the singular noun “document” with the word ‘this’.
Context: ...kfile is available and the rest of this documents will use typescript for configuration. ...
(DT_JJ_NNS_MD)
[uncategorized] ~69-69: It seems likely that a singular genitive (’s) apostrophe is missing./.bashr...
Context: ...the hooks that were installed into your shells rc file (startup scripts like `
(AI_HYDRA_LEO_APOSTROPHE_S_XS)
[uncategorized] ~73-~73: Possible missing comma found.
Context: ...One that contains a recognized ghjkfile format like any file called ghjk.ts
- One th...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~87-~87: Possible missing comma found.
Context: ...again, to execute task functions you've written for example. While the details of the o...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~88-~88: Consider an alternative for the often overused word ‘important’.
Context: ...While the details of the output are not important, this serialize then do workflow defi...
(NOT_IMPORTANT)
[uncategorized] ~88-~88: Possible missing comma found.
Context: ...lize then do_ workflow defines how ghjk functions as we should see. The ghjk CLI seriali...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~103-~103: Possible missing comma found.
Context: ...files in workers is not the quickest of operations as it turns out. Ghjk caches output of ...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~104-~104: Possible missing article found.
Context: ...operations as it turns out. Ghjk caches output of this serialization to improve the la...
(AI_HYDRA_LEO_MISSING_THE)
[misspelling] ~105-~105: This sounds awkward in English. The standard is “the question of how”.
Context: ...atency of the CLI commands. This raises the question how well the cache invalidation works in gh...
(THE_QUESTION_WH)
[uncategorized] ~105-~105: Possible missing comma found.
Context: ...ow well the cache invalidation works in ghjk and that's a good question. Cache inva...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~113-~113: Possible missing comma found.
Context: ...lization This doesn't cover everything though and the ghjk.ts
implementation genera...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~132-~132: Possible missing comma found.
Context: ... retain version numbers resolved during installation which is important for the basic need o...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~135-~135: Possible missing comma found.
Context: ...an lead to version conflicts during git merges for example. One can always remove the...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~141-~141: Consider replacing this phrase with the adverb “traditionally” to avoid wordiness.
Context: ... is to: - Resolve the ghjkfile conflict in a traditional manner - Instead of manually resolving the loc...
(IN_A_X_MANNER)
[uncategorized] ~147-~147: Possible missing comma found.
Context: ...e contained new versions, they'll be re-resolved possibly to a different version. But ge...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~151-~151: Possible missing comma found.
Context: ... The lockfile format itself is still in flux and there are plans to improve the merg...
(AI_HYDRA_LEO_MISSING_COMMA)
[duplication] ~156-~156: Possible typo: you repeated a word
Context: ...pt functions, and then invoke them from the the CLI. The CLI will then load your ghjkfi...
(ENGLISH_WORD_REPEAT_RULE)
[misspelling] ~180-~180: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’.
Context: ...hjk x greet ghjk ``` The $
object is a enhanced version of the one from the [d...
(EN_A_VS_AN)
[style] ~180-~180: The preposition ‘Amongst’ is correct, but some people think that it is old-fashioned or literary. A more frequently used alternative is the preposition “among”.
Context: ...dax](https://jsr.io/david/jsr) library. Amongst many things, it allows easy execution o...
(AMONGST)
[misspelling] ~181-~181: This word is normally spelled with a hyphen.
Context: ...s easy execution of shell commands in a cross platform way. Look at the official documentation...
(EN_COMPOUNDS_CROSS_PLATFORM)
[grammar] ~182-~182: Did you mean the possessive pronoun “its”?
Context: ...t the official documentation for all of it's illustrious powers. Tasks can also dep...
(IT_S_ITS)
[typographical] ~186-~186: Two consecutive dots
Context: ...examples/tasks/ghjk.ts) for more details.. ## Envs Ghjk's environments, simply p...
(DOUBLE_PUNCTUATION)
[uncategorized] ~191-~191: Possible missing preposition found.
Context: ...e current working directory and the set environment variables. Ghjk envs then allow you: -...
(AI_HYDRA_LEO_MISSING_OF)
[typographical] ~193-~193: Consider adding two commas here.
Context: ... allow you: - Set environment variables of course - Add existing paths or newly installed...
(OF_COURSE_COMMA)
[uncategorized] ~217-~217: The adjective “additive-based” is spelled with a hyphen.
Context: ... the main
environment. Inheritance is additive based for most env properties and allows easy...
(BASED_HYPHEN)
[misspelling] ~232-~232: This word is normally spelled with a hyphen.
Context: ... That is, entering an environment is a two step process. Cooking is what we call prepa...
(EN_COMPOUNDS_TWO_STEP)
[grammar] ~237-~237: After ‘it’, use the third-person verb form “is”.
Context: ...shell scripts to activate/deactivate it are prepared. The results of env cooking ar...
(IT_VBZ)
[uncategorized] ~259-~259: “you” seems less likely than “your” (belonging to you).
Context: ...deactivate any active environments from you shell, when it cd
s away into a direct...
(AI_HYDRA_LEO_CP_YOU_YOUR)
[duplication] ~267-~267: Possible typo: you repeated a word
Context: ...hat the CLI activate command depends on the the ghjk shell hooks being available. If no...
(ENGLISH_WORD_REPEAT_RULE)
[uncategorized] ~274-~274: Possible missing comma found.
Context: ...$GHJK_ENV`, they'll use the set default env as described in the next section. ```b...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~306-~306: Possible missing comma found.
Context: ...ritten in Deno flavoured typescript are supported and there's a small collection of such ...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~310-~310: Possible missing comma found.
Context: ...stallConfig` objects that describe user configuration along with where the port can be found ...
(AI_HYDRA_LEO_MISSING_COMMA)
[style] ~385-~385: The phrase “a variety of” may be wordy. To make your writing clearer, consider replacing it.
Context: ...d installing one from the internet. For a variety of reasons, the standard set of allowed po...
(A_VARIETY_OF)
[uncategorized] ~396-~396: The verb “is” doesn’t seem to fit in this context, “are” is probably more formally correct.
Context: ...riting ports The ports implementations is going through a lot of breaking changes...
(AI_HYDRA_LEO_CPT_IS_ARE)
[style] ~396-~396: The phrase ‘a lot of’ might be wordy and overused. Consider using an alternative.
Context: ... ports implementations is going through a lot of breaking changes. If you need to author...
(A_LOT_OF)
[grammar] ~402-~402: You used an adverb (‘primarily’) instead of an adjective, or a noun (‘difference’) instead of another adjective.
Context: ...CI jobs and for use in build tools. The primarily difference between the two scenarios is how activa...
(A_RB_NN)
[uncategorized] ~425-~425: Possible missing comma found.
Context: ...s the ghjk envs activate
command from functioning which requires that these hooks be run ...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~457-~457: Possible missing comma found.
Context: ...LL command available in some Dockerfile implementations or by using command processors more adv...
(AI_HYDRA_LEO_MISSING_COMMA)
[uncategorized] ~457-~457: “that” seems less likely than “than” (as in: greater than).
Context: ... using command processors more advanced that POSIX sh. ```dockerfile # contraption ...
(AI_HYDRA_LEO_CP_THAT_THAN)
[style] ~467-~467: As a shorter alternative for ‘able to’, consider using “can”.
Context: ...rketplace/actions/ghjk-everything) that is able to: - Installs ghjk CLI and hooks - Caches...
(BE_ABLE_TO)
[uncategorized] ~473-~473: It appears that a hyphen is missing (if ‘auto’ is not used in the context of ‘cars’).
Context: ...r to the bash
shell to have the hooks auto activate your environment. Otherwise, it's neces...
(AUTO_HYPHEN)
docs/known-issues.md
[typographical] ~6-~6: Consider inserting a comma for improved readability.
Context: ...leases, it's easy to get past this limit especially in CI contexts. This will manifest in f...
(MISSING_COMMAS)
🪛 Markdownlint (0.37.0)
README.md
147-147: null
Dollar signs used before commands without showing output
(MD014, commands-show-output)
docs/manual.md
101-101: Expected: h3; Actual: h4
Heading levels should only increment by one level at a time
(MD001, heading-increment)
270-270: Expected: h3; Actual: h4
Heading levels should only increment by one level at a time
(MD001, heading-increment)
143-143: Expected: 2; Actual: 4
Unordered list indentation
(MD007, ul-indent)
🪛 Gitleaks (8.21.2)
.ghjk/lock.json
366-366: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
372-372: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (133)
modules/mod.ts (3)
2-2
: Import usage is consistent with new commands integration
No issues found with the added import statement forCliCommand
.
6-7
: Constructor encapsulation looks clean
Storing theGhjkCtx
as a protected property is a logical approach, ensuring that derived classes can access shared context. No immediate concerns.
20-21
: Methods neatly align with module specification
genLockEntry
andcommands
remain self-explanatory; just ensure consistent error handling if either might fail or produce unexpected results.ports/livekit_cli_ghrel.ts (2)
1-31
: Solid configuration pattern, but verify Darwin variants
You currently skip Mac support for brew disclaimers at line 19. If Apple Silicon or Intel-based macOS support becomes pertinent, confirm thatosXarch
covers the intended Mac architecture variants or provide alternative instructions.
70-89
: Ensure destructive removal is intentional
The existing code removes a pre-existing installation path (line 85). Confirm that removing any existing installation is desired and that you have an appropriate rollback or backup strategy if the removal is unwanted.src/ghjk/log.rs (3)
3-5
: Initialization guard is well implemented
Use ofstd::sync::Once
ensures safe one-time initialization without concurrency pitfalls.
6-53
: String-based panic check might miss future variations
At line 44, the code checks for"A Tokio 1.x context was found..."
substring. Consider a more robust approach (regex or structured error) if this message might change in future library versions.
55-99
: Logging defaults are well-considered
Fallback to"info"
ifRUST_LOG
is undefined is a good practice. Overall, the multi-layered tracing configuration is clearly structured and aligns with typical usage patterns.src/deno_systems/types.ts (9)
5-8
: Schema aligns with future extension
DefiningdenoSystemsRoot
as a structured object is flexible and consistent.
9-51
: CLI argument schema is comprehensive
The enumeration ofvalue_hint
covers multiple scenarios, and the optional properties (e.g.,help
,long_help
) give implementers clarity.
53-61
: Extended schema for flags is well-structured
SeparatingcliFlag
fromcliArg
clarifies usage. Good approach to define short and long forms separately.
63-79
: Command base schema is clean
Using separate fields forabout
,before_help
, and related properties helps maintain clarity in command definitions. No changes recommended.
80-88
: Flags and args typed union
Including arrays, numbers, booleans, and strings ensures the needed flexibility for typical CLI patterns.
89-98
: Optional action function
Allowing commands to provide an async or sync action nicely supports both straightforward subcommands and advanced asynchronous processing.
100-112
: Lazy evaluation approach for subcommands
Excellent use of zod’s lazy schema for recursive structures, ensuring that commands can nest subcommands seamlessly.
113-131
: Deno system constructor integration
DefiningDenoSystemCtor
as a factory function fosters modular expansions while maintaining typed LockEnt usage.
139-145
: Export grouping
All core schemas and types are neatly exported in a single object, enabling consistent importing patterns.src/ghjk/systems.rs (5)
1-3
: Clear documentation
Introductory comments succinctly describe the purpose of systems as functional units.
10-20
: Enum-based approach for system manifests
Separating system variants (currently onlyDeno
) is a clean approach that facilitates future extension.
22-38
: Asynchronous trait usage is well-defined
The design allows each system to provide a uniqueLockState
while offering consistent async methods to handle config and lock logic.
121-128
: Config blackboard approach
SystemConfig
withid
andconfig
fields is straightforward; storing system-specific config as JSON is flexible and easy to integrate with hierarchical data.
129-147
: CLI command composition
SystemCliCommand
effectively bundles command metadata with subcommands and potential action. The custom debug implementation helps for logging.src/deno_systems/bindings.ts (5)
6-14
: Confirm behavior for unhandled promise rejections
While manually dispatching "unhandledrejection" events is helpful to avoid a shutdown, ensure that relevant error details (e.g., error message, name, cause) are propagated properly. Currently, only the stack is taken ifreason
is anError
. Consider preserving or logging additional properties, if any.
41-54
: Validate strictness in Zod schema parsing
The Zod schema is straightforward but may benefit from more robust validations (e.g., non-empty strings if required). Also, wrappingprepareSystems(args)
in a try/catch or error check might prevent unexpected runtime errors.
88-91
: ManifestDesc structure is cleanly defined
This type is concise and properly typed. No issues found.
93-98
: InstanceDesc type usage
This structure neatly consolidates callback keys for a module instance. The naming is self-explanatory and consistent with the rest of the file.
155-176
: Command binding parse
The logic incommandBinding
is well-structured. Note thatcliActionArgs
parsing might throw if there are unexpected fields or data types. If partial input is valid, ensure robust error-handling logic.src/ghjk/ext.rs (2)
13-23
: Initialization pattern inextensions
The function returns anArc<CustomExtensionsCb>
that clonesconfig
without version checking or concurrency locking. Confirm that multiple calls won’t cause unintended side effects.
26-32
:ExtConfig
usage
TheExtConfig
struct includes optionalexception_tx
but lacks concurrency guards aroundhostcalls
. Ensure that modifications tohostcalls
(e.g., registering new hostcall functions) happen in a controlled manner to avoid data races.src/ghjk/utils.rs (2)
1-9
: Utility methods appear consistent
Thedefault
function andDHashMap
alias are straightforward. No immediate concerns.
139-150
: Hashing usingmultihash
Storing digest in base32 multibase is nice, but ensure collision risk is acceptable for your environment. If collision handling is needed, consider adding collisions check or fallback logic.src/ghjk/host/hashfile.rs (1)
73-109
:is_stale
logic
The environment variable comparisons and file exist checks handle typical scenarios effectively. However, a file system race condition could still occur between checks (e.g., file creation after the check or removal mid-check). If needed, consider a more robust approach.src/denort/unsync.rs (2)
19-28
: Check concurrency for partialabort()
usage
Theabort
method allows forcibly canceling tasks, but confirm if partial usage can lead to domain-specific resource leaks or inconsistent states.
140-156
: Managing wakers inJoinSet
The logic for storing a waker ifjoin_next
returnsNone
is clear. However, if external concurrency modifies the join set while a waker is stored, ensure that spurious or missed wakes do not occur.src/ghjk/systems/deno.rs (3)
19-32
: Graceful termination logic is well-structured
Theterminate
method correctly handles scenario checks (already terminated
) and awaits the join handle's result. This approach ensures a clear, predictable shutdown sequence for the worker.
61-99
: Hostcall registration appears consistent
The registration of"register_systems"
and the use of an async move block is solid. Be mindful that any panics or early returns in this block will bubble up, so ensure robust error logging is in place.
257-321
: Implementation ofSystemInstance
methods is clean
The methodsload_config
,load_lock_entry
,gen_lock_entry
, andcommands
consistently offload logic to callbacks, minimizing Rust side complexity. Ensure that the TS side includes adequate error handling to avoid silent callback failures.src/ghjk/config.rs (6)
3-11
: Well-definedConfig
struct
TheConfig
struct centralizes all key environment paths, making the configuration easier to manage. Ensure future expansions (e.g., more optional fields) maintain backward compatibility for existing environment setups.
27-63
: Readable approach to environment variable overrides
Thesource
method’s logic for environment variables (GHJK_DIR
,GHJKFILE
) ensures user overrides are respected while still searching recursively otherwise. This is well-structured, though consider clarifying fallback routines in docs for user clarity.
105-159
: Synchronous file reads in global config
All config reads and merges occur viatokio::task::spawn_blocking
, which is correct when bridging sync IO with async flows. Good job ensuring no blocking on the main async thread.
188-223
:source_local_config
handles local overrides
Local overrides are merged on top of global config. This layered approach ensures logical handling of environment vs. user vs. local overrides. The code is well-structured and uses strongly typed deserialization.
263-286
: Helper functions are straightforward
resolve_config_path
andpath_from_env
handle absolute path creation and environment variable checks respectively. The error messages are well-defined.
161-186
:source_global_config
merges well
The function merges data from the optional global config file. The usage ofresolve_config_path
for each path is consistent. Remember to handle concurrency carefully if multiple processes might write to these config files simultaneously.Do you run any checks for concurrent config updates? If so, consider verifying by scanning the codebase for file locks or concurrency patterns referencing config writes:
src/ghjk/ext/callbacks.rs (4)
14-24
: Nicely scopedCallbackError
Defining distinct variants ensures that errors likeNotFound
andJsError
become more meaningful, aiding debugging. Good practice using#[source]
for nestedeyre::Report
.
67-90
:CallbacksHandle::exec
channel-based approach
Using a one-shot channel to collect the callback’s return is effective. The code provides robust error logs when the channel is closed. Keep in mind that large payloads might benefit from a streaming approach if performance becomes a concern.
105-154
: Spawning callback worker
The dedicated worker thread approach for callbacks isolates potential panics or high-latency tasks from the main event loop. This pattern is well-suited for an asynchronous environment.
156-266
:exec_callback
robust V8 bridging
Error handling for both immediate (!is_promise()
) and async promise-based results is well implemented. The possibility of “runtime shutting down” or “promise rejection” is suitably covered.src/denort/lib.rs (6)
10-24
:interlude
module provides a convenient alias
Re-exporting common items (Result as Res
,v8
, etc.) simplifies referencing these across files. Keep an eye on naming collisions if the codebase grows.
36-50
:init
function
Early invocation ofinit_v8_flags
is essential to prevent V8 from misconfiguring itself. The fallback to setRUST_MIN_STACK
in debug mode is a good measure for avoiding stack overflows, especially with complex compiled code.
52-60
:spawn_subcommand
Boxing the future locally with.boxed_local()
effectively reduces stack usage. This is a neat pattern for tasks that may have large stack frames.
126-158
:test_sync
Similar approach torun_sync
, which is consistent. Using a separate function helps keep test logic distinct. Good clarity, though be sure to unify any error-handling logic across both run and test flows.
160-314
:test
function
The interplay between doc tests, coverage, filtering, and concurrency is handled thoroughly. Great job ensuring the code checks for no specifiers found, returning an error early.
316-327
:new_thread_builder
Conditionally customizing the stack size in debug builds is a good balance between safety and performance. This approach matches the earlier stack adjustments ininit
.src/ghjk/systems/deno/cli.rs (5)
118-189
:deno_cb_action
multi-arg extraction
Collectingflags
andargs
separately is clear, leveragingArgActionSerde
to interpret the type of each. The unstoppableunreachable!()
calls forHelp
,HelpShort
, etc. are acceptable since clap typically intercepts them earlier.
191-289
:CliArgDesc
Breaking out each property (required
,global
,hide
, etc.) is beneficial for maintainability. The methodconvert
systematically applies them, keeping code straightforward.
291-332
:CliFlagDesc
Inherits fromCliArgDesc
but adds optional short/long aliases—this is a good DRY approach for code reuse.
334-370
:ValueHintSerde
Mapping enumerated “hints” to Clap’sValueHint
ensures commands can provide accurate guidance to the user (e.g., file paths, hostnames). Very helpful for usability.
372-400
:ArgActionSerde
Mirroring Clap’sArgAction
variants allows maximum flexibility. Consider providing user-facing documentation or help text in case advanced users or script authors rely on these for scriptable CLIs.src/ghjk/host.rs (3)
26-37
: Consider clarifying concurrency implications forfile_hash_memo
.This field caches file content digests but may become stale if used extensively after serialization. Clearly document or enforce a lifecycle to avoid stale hashes in long-running tasks or repeated references.
104-110
: Validate presence of hashfile/lockfile whenlocked
is set.These bailouts are appropriate for strict builds. Make sure to document that setting
locked
mandates these files, and confirm all calls to this function handle the error gracefully.
137-147
: Re-check stale logic conditions.When
obj.is_stale
orre_serialize
is triggered, the hash object is replaced withNone
, leading to potential re-serialization. Ensure there is no scenario where partial or inconsistent states arise if multiple stale conditions overlap (e.g.,re_serialize
plus ephemeral disk errors).src/ghjk/cli.rs (2)
29-31
: Graceful exit on quick CLI success.The flow returns immediately with
ExitCode::SUCCESS
iftry_quick_cli
resolves toNone
. This is good for short-circuit logic, but ensure any required cleanup or common post-processing is not bypassed.
68-77
: Handle errors when loading systems from Deno.Here, the function
systems_from_deno
can fail. The error is unwrapped with?
. Verify that upper layers can handle partial initialization or system load failures gracefully.src/denort/worker.rs (1)
354-361
: Drive event loop carefully.The function loads the main module, then calls
drive_till_exit()
. Ensure the worker remains valid during concurrency tasks (e.g., open file watchers, HMR runners). If unimplemented or commented out, partial references may cause unexpected states.src/ghjk/build.rs (1)
1-3
: Handle possible build script configuration errors.
shadow_rs::new()
returns an error that’s propagated up. This is correct, but consider logging or clarifying in user docs how to address build failures ifshadow_rs::new()
fails.src/ghjk/js/runtime.js (2)
1-6
: Documentation and reference comments look good.No issues found in the file references or doc comments. The comments clearly explain the purpose of the file and the associated TypeScript declarations.
7-10
: Verify existence of the global property.
globalThis.____GhjkHost
might be unavailable in certain non-browser or older runtime environments. Consider providing a fallback or a guard check to handle situations where____GhjkHost
is not present, preventing potential runtime errors.ports/zstd.ts (1)
13-13
: Confirm trailing comma removal in version extraction.The updated regex excludes any trailing commas in the version string. If you want to support optional trailing commas (e.g., “v1.5.6,”), consider using a modified pattern such as
v(\d+\.\d+\.\d+),?
. Otherwise, this change looks fine.src/ghjk/js/mock.sfx.ts (2)
1-3
: Introductory comments are clear.The doc comments concisely explain the file’s purpose: providing a mock object for
Ghjk
to enable testing code reliant on theGhjk
extension without the real implementation.
4-20
: Ensure correct behavior alignment between mock and real implementation.While this mock is great for sanity checks, ensure it accurately mirrors the real
Ghjk
methods’ arguments, return values, and side effects to avoid false positives in tests.modules/types.ts (1)
19-19
: Ensure all references to the renamed property are updated.The rename from
ghjkShareDir
toghjkDataDir
is straightforward here. However, confirm that all usages and references throughout the codebase have also been updated to avoid runtime errors or broken references.Run the following script to check for any lingering references to the old property name:
✅ Verification successful
Property rename is safe - no lingering references to old name found
The search results show that there are no remaining references to
ghjkShareDir
in the codebase, whileghjkDataDir
is consistently used across multiple files. All occurrences ofghjkDataDir
are properly used in the correct context (configuration, environment setup, and path handling), indicating that the rename was thoroughly implemented.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # This script searches the entire repo for references to `ghjkShareDir`. rg "ghjkShareDir"Length of output: 17
Script:
#!/bin/bash # Let's check for both the old and new property names to understand the context better echo "Searching for ghjkDataDir:" rg "ghjkDataDir" -A 2 echo -e "\nChecking TypeScript/JavaScript files specifically:" fd "\.(ts|js|tsx|jsx)$" --exec grep -l "ghjk.*Dir"Length of output: 5063
src/ghjk/js/runtime.d.ts (3)
1-4
: Validate JSON type definitions.Defining
JsonLiteral
,JsonObject
,JsonArray
, andJson
ensures safer handling of JSON-like data across your codebase. These types look good as a foundation for typed serialization/deserialization.
6-16
: Double-check the error handling in callbacks and hostcall.Your
GhjkNs
interface includes adispatchException
method. Ensure callbacks andhostcall
usage are wrapped with consistent error handling to prevent unhandled exceptions.
17-17
: Exporting The Ghjk Namespace.Exporting
Ghjk
asGhjkNs
helps maintain a single source of truth for runtime definitions. Verify that downstream consumers now useGhjk
consistently, rather than defining parallel or conflicting interfaces.install/utils.ts (2)
15-15
: Security note: environment variable injection.Note that you are injecting an environment variable (
GHJK_DIR
) dynamically into the shell. This is fine if guaranteed to be trusted, but be cautious about potential injection issues when dealing with user-provided or untrusted paths.
21-21
: Same usage caveat for Fish shell shim.As with the posix shim, confirm that references to
GHJK_DIR
remain valid in the fish environment and do not present any undisclosed security concerns when user input is involved.deno.jsonc (4)
3-4
: Cargo build integration for testing and self-invocation.Switching to Cargo commands (
cargo build
/cargo run
) before running Deno tasks unifies the build process. Verify that all required environment variables and dependencies are properly set up in your CI pipelines and dev environments.
6-7
: Redirect to new scripts for checking and development.The commands in
./tools/
may differ from previous scripts. Ensure that any referenced environment variables or additional flags are reflected in these new script files.
17-18
: Exclude vendor and target directories from formatting.Explicitly excluding
vendor/**
and./target/
fromfmt
is common practice to avoid formatting large or generated directories. Confirm that these directories are indeed ephemeral or regenerated so skipping them is acceptable.
28-29
: Exclude vendor and target directories from linting.Same rationale as for formatting. Verify there are no essential code files within these directories; otherwise, they might inadvertently remain unchecked.
src/ghjk/js/00_runtime.js (2)
29-42
: Consider broader error handling for the____GhjkHost
object.
Each method references an operation that might fail or raise an exception. Consider adding validation or try/catch blocks to each operation invocation to make the host more resilient in various runtime environments.
44-44
: Global exposure of____GhjkHost
.
Attaching____GhjkHost
toglobalThis
can be helpful but also risky if it introduces naming collisions or security concerns. Verify this is intentional and that the naming is sufficiently unique.files/deno/bindings.ts (1)
33-35
: Check for missingargs
before parsing.
Ensure thatGhjk.blackboard.get("args")
is guaranteed to be set. If not, consider providing a default or throwing a more explicit error to inform the user that arguments are required.install.ts (1)
8-12
: Confirm the installation caching approach.
By importing modules (std.ts
,port.ts
,mod.ts
) to cache them in the Deno store, you ensure they’re downloaded ahead of time. Just confirm that this approach aligns with how users expect these modules to be installed and updated.files/deno/worker.ts (1)
10-10
: Use type-only imports consistently for clarity.
You are correctly usingimport type { DriverRequests, DriverResponse }
to import types. Verify that all other modules only import what they need (e.g., type vs. runtime imports) to keep the codebase consistent.deps/common.ts (1)
13-13
: Consider verifying the migration to version 3.4.0This line updates the
zod-validation-error
version from3.3.0
to3.4.0
. Although it's a minor version bump, confirm there are no breaking changes or deprecations by checking the upstream changelog and adjusting accordingly.files/deno/mod.ts (1)
56-56
: Confirm necessity and security of the 'import' permissionAllowing imports in the worker (
import: true
) can be necessary for dynamic module loading but also opens potential security or performance implications. Verify your threat model and confirm this permission is strictly needed.src/ghjk/main.rs (3)
1-10
: Good use of aninterlude
module for consolidated importsCentralizing commonly needed symbols and crates within the
interlude
block can improve maintainability and readability. Ensure that usage of these globally re-exported symbols remains consistent and documented.
11-28
: Check for version conflicts among deeply nested dependenciesThe re-exports from
color_eyre
,denort
,futures
, and others can interact in nuanced ways. If you see type or trait conflicts, confirm that all crates and library versions are compatible.
39-63
: main function logic looks clean and clearYour usage of
cli::deno_quick_cli()
before initiating the runtime is straightforward. The fallback tounreachable!()
suggests some deeper assumptions about control flow—ensure the CLI always returns as expected to avoid edge cases.ports/fx_ghrel.ts (3)
1-10
: Validate your import paths and naming consistencyThe import block is extensive. Check that each imported symbol (
GithubReleasePort
,readGhVars
, etc.) is correctly named and that references in the code align with your naming strategy.
12-19
: Manifest definition is well-structuredThe
manifest
object is a concise way to define metadata for your port. Ensure your versioning standard (currently0.1.0-alpha
) aligns with the rest of the project’s semver guidelines.
20-28
: Combine environment variable reading with user config carefullyMerging
readGhVars()
with user-providedconfig
can introduce unexpected overrides if keys collide. Document or guard against these collisions to ensure predictable behavior.src/ghjk/host/deno.rs (1)
5-12
: Good struct design for capturing Deno output.The
InternalSerializationResult
structure neatly holds the configuration, environment keys, and file paths returned from the Deno module. This provides clear separation of concerns.src/denort/promises.rs (1)
17-20
: Documentation is clear and well-commented.Your doc comments accurately convey the effect on unhandled rejections, informing users of potential trade-offs.
modules/ports/sync.ts (1)
56-56
: Confirm permission and existence checks for the new data directory path.When switching from
gcx.ghjkShareDir
togcx.ghjkDataDir
, ensure the environment and user permissions allow creation and usage of the new “ports” directory.rust-toolchain.toml (2)
4-6
: Configuration looks good!The toolchain configuration is well-structured with appropriate components (rustfmt, clippy) and WebAssembly targets.
2-4
: Verify version synchronization mechanismThe comment indicates manual synchronization between this file and
ghjk.ts
. Consider automating this to prevent version mismatches.Cargo.toml (3)
1-4
: Workspace configuration looks good!The workspace is well-structured with appropriate member inclusion and exclusion rules.
31-33
: Verify clap version compatibilityThe warning about matching clap version with deno needs verification.
12-15
: Verify deno dependency version compatibilityThe warning about tracking deno_core version used by deno is important. Consider:
- Automating version compatibility checks
- Adding a link to deno's dependency tree for reference
.github/workflows/nightly.yml (2)
54-66
: Review the necessity of commented-out test-action jobThe commented-out
test-action
job should either be:
- Removed if it's no longer needed
- Re-enabled if it's still required
- Documented with a comment explaining why it's temporarily disabled
23-25
: Verify the availability of custom-arm runnerThe runner label "custom-arm" is not a standard GitHub-hosted runner. Ensure that:
- This is a properly configured self-hosted runner
- The runner is actually available and operational
🧰 Tools
🪛 actionlint (1.7.4)
24-24: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
src/ghjk/Cargo.toml (1)
56-56
: Review the necessity of exact version pin for futures crateThe
futures
crate is pinned to exactly version 0.3.30. Consider:
- Document the reason for this exact version pin
- Verify if this version has any known security vulnerabilities
.pre-commit-config.yaml (1)
69-80
: LGTM! Comprehensive Rust linting configurationThe addition of Rust pre-commit hooks with strict clippy configuration (
--deny warnings
) will help maintain high code quality. The configuration includes:
- Format checking with
fmt
- Comprehensive linting with
clippy
- All features and targets coverage
.github/workflows/tests.yml (2)
Line range hint
1-15
: Well-structured workflow configuration!Good addition of concurrency settings to cancel in-progress runs when new changes are pushed. This prevents resource wastage and ensures only the latest changes are tested.
18-18
: Verify compatibility with Deno 2.xThe upgrade from Deno 1.x to 2.x is a major version bump that might introduce breaking changes.
Run this script to check for compatibility issues:
✅ Verification successful
Deno 2.x upgrade appears safe to proceed
Based on the analysis of the codebase:
- Most Deno API usage is focused on stable APIs that haven't changed significantly in 2.x:
- File system operations (read, write, symlink)
- Environment variables
- Platform detection (Deno.build)
- Basic process operations (exit)
- The project uses the KV API which is still marked as unstable (referenced with
/// <reference lib="deno.unstable" />
)- The deno.jsonc configuration shows standard task definitions and lint rules that are compatible with 2.x
The used APIs are part of Deno's stable API surface and haven't undergone breaking changes in the 2.x release. The unstable KV API usage is properly marked as unstable, and the upgrade won't affect its behavior.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for Deno 2.x compatibility issues # Look for deprecated APIs or breaking changes in the codebase # Search for known Deno 1.x APIs that changed in 2.x rg -l "Deno\.(run|readFile|writeFile|mkdir|remove|rename|chmod|chown|symlink|readLink|readDir|stat|lstat|realPath|truncate|create|open|read|write|seek|close|copy|iter|iterSync|watch|watchFs|build|bundle|compile|format|lint|test|bench|doc|coverage|info|repl|upgrade|eval|install|uninstall|completions)" # Look for import maps which might need updates fd "import_map.json|deno.json|deno.jsonc"Length of output: 655
Script:
#!/bin/bash # Let's check the actual usage of Deno APIs in these files to understand the impact # First, let's look at the deno.jsonc configuration cat deno.jsonc # Then, let's examine the actual Deno API usage in the files echo "=== Checking Deno API usage ===" for file in hack.ts tests/utils.ts ports/pipi.ts ports/ruff.ts install/mod.ts ghjk.ts ports/infisical.ts modules/ports/sync.ts modules/envs/posix.ts modules/ports/mod.ts utils/worker.ts utils/unarchive.ts modules/ports/db.ts tests/ports.ts tests/ambient.ts tests/hashfile.ts; do if [ -f "$file" ]; then echo "=== $file ===" rg "Deno\." "$file" -A 2 fi doneLength of output: 13148
modules/tasks/mod.ts (2)
Line range hint
26-48
: LGTM! Good refactoring to improve encapsulationThe removal of the
gcx
parameter in favor of usingthis.gcx
improves the code structure by leveraging class encapsulation.
50-93
: Well-structured command implementation!Good improvements:
- Clear command descriptions and help messages
- Proper type usage with CliCommand
- Well-organized sub-commands with sorted keys
.github/workflows/release.yml (3)
21-37
: LGTM! Well-configured release jobGood implementation with:
- Proper tag handling
- Automatic release notes generation
- Smart prerelease detection based on tag content
64-65
: Configure custom runner label in actionlint.yamlThe
custom-arm
runner label needs to be configured in actionlint.yaml, same as in tests.yml.🧰 Tools
🪛 actionlint (1.7.4)
64-64: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
38-90
: Well-structured release workflow!Good implementation with:
- Proper target architecture matrix
- Build caching with sccache
- Comprehensive artifact handling
🧰 Tools
🪛 actionlint (1.7.4)
64-64: label "custom-arm" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2022", "windows-2019", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "macos-12-xl", "macos-12-xlarge", "macos-12-large", "macos-12", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file
(runner-label)
install/hook.fish (2)
14-20
: Well-structured interactive shell check!Good improvement to prevent unnecessary reloads in non-interactive shells, making the behavior more efficient.
114-116
: Good defensive programming!The explicit file existence check before timestamp comparison prevents potential errors.
install/hook.sh (1)
114-114
: Consistent defensive programming across shell implementations!The explicit file existence check matches the fish implementation, maintaining consistency.
install/mod.ts (3)
8-10
: Clean import organization and VFS setup!Good separation of concerns with type imports and use of xdg for cross-platform compatibility.
147-154
: Reconsider using CWD as base for ghjkDataDir.Using the current working directory as a base for resolving
ghjkDataDir
might lead to unexpected behavior if the installation is triggered from different locations.Consider using a more stable base directory or documenting the expected working directory context.
100-106
: Verify impact of removed InstallArgs fields.The interface has been simplified, but removal of fields like
skipExecInstall
andghjkExecInstallDir
is a breaking change.ports/asdf.ts (2)
Line range hint
75-95
: Address the FIXME comment regarding ASDF_INSTALL_VERSION requirement.The comment indicates that ASDF requires ASDF_INSTALL_VERSION for latest-stable, which seems counterintuitive. This might indicate a design issue in the underlying ASDF plugin system.
Would you like me to investigate alternative approaches to handle version resolution without relying on ASDF_INSTALL_VERSION?
Line range hint
96-115
: LGTM! Well-structured implementation.The method properly handles platform-specific paths and includes appropriate error handling.
README.md (1)
64-73
: LGTM! Import URLs follow project conventions.The use of raw.github.com in import URLs is acceptable as Deno's import system supports redirects, and this format is preferred in the README.
ghjk.ts (1)
12-27
: LGTM! Configuration setup is well-structured.The configuration is properly defined with clear version specifications and build dependencies.
host/init/mod.ts (2)
20-22
: Incorrect string interpolation in error messageThe error message uses template literals correctly, but this was flagged in a previous review.
44-44
: Improper argument parsingThe comparison
$.argv[0] == "--yes"
was previously flagged as potentially missing flags not in the first position.modules/ports/mod.ts (2)
3-3
: LGTM!The import statement correctly imports the required dependencies for table creation and data validation.
38-38
: LGTM!The import statement correctly imports the
CliCommand
type for command handling.modules/envs/posix.ts (4)
205-205
: LGTM!The variable renaming from
shareDirVar
todataDirVar
better reflects its purpose and is consistently used.Also applies to: 214-214
238-240
: LGTM!The added comments provide clear instructions about how to properly use the script, preventing potential misuse.
241-247
: LGTM!The
ghjk_deactivate
function provides a clean and safe way to handle environment cleanup, following shell scripting best practices.
330-339
: LGTM!The fish shell implementation provides consistent functionality with the POSIX version while correctly using fish-specific syntax and following fish shell best practices.
modules/envs/mod.ts (2)
23-23
: LGTM!The import statement correctly imports the
CliCommand
type for command handling.
Line range hint
38-60
: LGTM!The
loadConfig
method implementation correctly manages environment context and follows good practices for configuration loading..ghjk/lock.json (1)
443-443
: Review hardcoded path in environment variable.The
RUSTY_V8_MIRROR
environment variable contains a hardcoded path that may not be portable.
env.sh
doesn't auto-invoke theghjk_hook
unlessGHJK_AUTO_HOOK
is set.Addresses MET-721, MET-678, #18, #19, #94, #74.
Summary by CodeRabbit
Summary by