Skip to content

feat: Arox Framework#56

Merged
vrdons merged 1 commit intomainfrom
feat/main
Mar 8, 2026
Merged

feat: Arox Framework#56
vrdons merged 1 commit intomainfrom
feat/main

Conversation

@vrdons
Copy link
Member

@vrdons vrdons commented Mar 8, 2026

No description provided.

@vrdons vrdons merged commit c76814c into main Mar 8, 2026
1 check passed
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request lays the groundwork for the Arox Framework, providing a structured and extensible base for building Discord bots. It introduces core components for command and event management, integrates internationalization, and sets up a modern build and release system to facilitate development and deployment.

Highlights

  • Core Framework Structure: Introduced the foundational Arox Framework, including a new Client class extending Discord.js, and dedicated builders for commands and events to streamline development.
  • Command and Event Handling: Implemented robust command and event handling mechanisms, supporting both slash commands and traditional prefix-based commands, along with a flexible context system for command execution.
  • Internationalization (i18n) Integration: Integrated i18next for internationalization, allowing for multi-language support within the framework's commands and responses, complete with a custom logger adapter.
  • Advanced Build and Release System: Established a comprehensive build pipeline using esbuild and oxc for dual CJS/ESM module output, alongside automated GitHub and npm release scripts for efficient package publishing and version management.
  • Developer Tooling and Quality of Life: Added configurations for code formatting (oxfmt, Prettier), linting (oxlint), and pre-commit hooks (Husky) to ensure code quality and consistency across the project.
Changelog
  • .github/dependabot.yml
    • Added Dependabot configuration to automate dependency updates for npm packages.
  • .gitignore
    • Updated ignored files to include build outputs, environment scripts, and other temporary directories.
  • .husky/pre-commit
    • Added a pre-commit hook to run code checks before commits.
  • .npmignore
    • Added a list of files and directories to exclude from npm package publication.
  • .oxfmtrc.json
    • Added configuration file for the oxfmt code formatter.
  • .prettierrc
    • Added Prettier configuration for consistent code styling.
  • CHANGELOG.md
    • Added a comprehensive changelog file to track project history and releases.
  • cliff.toml
    • Added configuration for git-cliff to generate changelogs based on conventional commits.
  • examples/basic_client/events/ready.js
    • Added an example event handler for the client ready event.
  • examples/basic_client/index.js
    • Added a basic client example demonstrating command and i18n usage.
  • examples/basic_client/locales/en-US/error.json
    • Added an English locale file for error messages.
  • examples/basic_client/locales/en-US/test.json
    • Added an English locale file for test messages.
  • package.json
    • Updated package metadata, added new development dependencies for build and linting tools, and configured build/release scripts.
    • Configured dual package exports for CommonJS and ES Modules.
    • Added discord.js as a peer dependency.
  • scripts/actions/github.js
    • Added a script to manage GitHub releases, including tag creation and asset uploads.
  • scripts/actions/npm.js
    • Added a script to manage npm package publishing, including version checks and dist tag handling.
  • scripts/build.js
    • Added a build script utilizing esbuild and unplugin-oxc for CJS/ESM output and placeholder patching.
  • scripts/prepareHusky.js
    • Added a script to conditionally prepare Husky git hooks.
  • scripts/utils/build.js
    • Added a utility function to build and pack the project into a tarball.
  • scripts/utils/github.js
    • Added utility functions for interacting with the GitHub API for repository and release information.
  • scripts/utils/npm.js
    • Added utility functions for checking npm package versions and determining distribution tags.
  • scripts/utils/util.js
    • Added general utility functions for executing shell commands and generating changelogs.
  • src/constants/messages.ts
    • Added constant strings for common command-related messages.
  • src/context.ts
    • Added a module for managing the global client instance context.
  • src/events/interaction.ts
    • Added a core event handler for Discord interactions to process slash commands.
  • src/events/message.ts
    • Added a core event handler for Discord messages to process prefix commands.
  • src/events/ready.ts
    • Added a core event handler for the client ready event to register commands.
  • src/index.ts
    • Exported core framework components, logger, and context utilities.
  • src/structures/builder/Builder.ts
    • Added an ApplicationCommandBuilder to extend Discord.js slash command functionality with prefix support and aliases.
  • src/structures/builder/Command.ts
    • Added a CommandBuilder for defining and registering commands with message and interaction handlers.
  • src/structures/builder/Context.ts
    • Added a Context class to encapsulate command execution data and provide i18n capabilities.
  • src/structures/builder/Event.ts
    • Added an EventBuilder for defining and registering Discord event handlers.
  • src/structures/builder/index.ts
    • Exported all builder components.
  • src/structures/core/Client.ts
    • Added the main Client class, extending Discord.js Client with custom logging, command/alias management, and i18n integration.
  • src/structures/core/index.ts
    • Exported the core Client class.
  • src/structures/index.ts
    • Exported all framework structures.
  • src/utils/Files.ts
    • Added utility functions for file system operations, including finding project root and listing files.
  • src/utils/index.ts
    • Exported all utility functions.
  • src/utils/logger/ILogger.ts
    • Defined the LogLevel enum and ILogger interface for logging functionality.
  • src/utils/logger/Logger.ts
    • Implemented a custom Logger class with configurable levels, styles, and timestamping, including an i18n adapter.
  • src/utils/normalizeArray.ts
    • Added a utility function to normalize array inputs.
  • src/utils/util.ts
    • Added utility functions for message deletion and prefix parsing.
  • tsconfig.json
    • Added TypeScript configuration, including path aliases, module resolution, and build options.
  • types/client.d.ts
    • Defined TypeScript types for framework client options and configurations.
  • types/extra.d.ts
    • Defined a utility TypeScript type for MaybePromise.
  • types/logger.d.ts
    • Defined TypeScript types for logger options and interfaces.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the Arox Framework, a new foundation for building Discord bots, featuring a well-organized structure with a builder pattern for commands and events, i18n support, and a comprehensive build and release process. However, several utility scripts used for building and releasing the package are vulnerable to command injection. These scripts construct shell commands using string interpolation with variables from package.json, posing a risk of arbitrary command execution in build or CI environments. Additionally, the review highlights design concerns regarding global mutable state for the client instance, and suggests improvements for error handling, TypeScript compiler settings, and naming conventions.

Comment on lines +47 to +57
const command = `gh release create ${version} ${assetPath} \
--target ${sha} \
--title "${version}" \
--notes-file - \
${prereleaseFlag}`;

execSync(command, {
input: notes,
stdio: ["pipe", "inherit", "inherit"],
encoding: "utf-8",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The createRelease function is vulnerable to command injection. It constructs a shell command string by interpolating the version and assetPath variables. An attacker could inject shell metacharacters into the version field of package.json to execute arbitrary commands. Although the developer attempted to prevent injection for the release notes by using stdin, the version and assetPath parameters remain unprotected. It is recommended to use execFileSync and pass arguments as an array to avoid shell interpretation.

import { execFileSync } from "node:child_process";

export function createRelease(version, tgzPath, body = "") {
	const sha = getSha();

	console.log(`Creating GitHub Release & Tag: ${version}`);

	const prereleaseFlag = isPrerelease(version) ? "--prerelease" : null;
	const notes = body || `Release ${version}`;
	const assetPath = tgzPath ? path.resolve(tgzPath) : "";

	const args = [
		"release",
		"create",
		version,
		assetPath,
		"--target",
		sha,
		"--title",
		version,
		"--notes-file",
		"-"
	];
	if (prereleaseFlag) args.push(prereleaseFlag);

	execFileSync("gh", args, {
		input: notes,
		stdio: ["pipe", "inherit", "inherit"],
		encoding: "utf-8"
	});

	console.log(`Release ${version} successfully published.`);
}

Comment on lines +13 to +15
exec(`npm view ${packageName}@${version} --registry=${registry}`, {
stdio: "ignore",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The checkVersionExists function is vulnerable to command injection. It uses string interpolation to build an npm view command, where packageName and version variables are sourced from package.json. This creates a potential vector for command injection in the build environment. To mitigate this, it is recommended to use a safer execution method that doesn't involve the shell, such as execFileSync with an arguments array.

import { execFileSync } from "node:child_process";

export function checkVersionExists(packageName, version, registry) {
	try {
		execFileSync("npm", ["view", `${packageName}@${version}`, "--registry", registry], {
			stdio: "ignore"
		});
		return true;
	} catch {
		return false;
	}
}

Comment on lines +29 to +31
exec(`gh api repos/${process.env.GITHUB_REPOSITORY}/git/ref/tags/${tag}`, {
stdio: "ignore",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The tagExists function is vulnerable to command injection because it interpolates the tag variable directly into a shell command string. Since tag is derived from the version field in package.json, an attacker who can modify package.json (e.g., via a pull request) could execute arbitrary commands in the build/CI environment.

import { execFileSync } from "node:child_process";

export function tagExists(tag) {
	try {
		execFileSync("gh", ["api", `repos/${process.env.GITHUB_REPOSITORY}/git/ref/tags/${tag}`], {
			stdio: "ignore",
		});
		return true;
	} catch {
		return false;
	}
}

Comment on lines +72 to +74
exec(`npm publish "${tarballPath}" --registry=${GITHUB_URL}${tagArg}`, {
stdio: "inherit",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The npm publish command is constructed using string interpolation with the tarballPath and tagArg variables. If these variables contain shell metacharacters, it could lead to command injection. While tarballPath is currently generated in a temporary directory, tagArg is derived from the version in package.json. It is safer to pass arguments as an array to avoid shell interpretation.

import { execFileSync } from "node:child_process";

			const distTag = getNpmDistTag(version);
			const args = ["publish", tarballPath, "--registry", GITHUB_URL];
			if (distTag !== "latest") {
				args.push("--tag", distTag);
			}
			execFileSync("npm", args, {
				stdio: "inherit",
			});

Comment on lines +44 to +49
exec(
`npm publish "${tarballPath}" --provenance --registry=${NPM_URL}${tagArg}`,
{
stdio: "inherit",
}
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

Similar to the GitHub release script, the npm publish command here is vulnerable to command injection via string interpolation of tarballPath and tagArg. Using execFileSync with an array of arguments is the recommended remediation.

import { execFileSync } from "node:child_process";

			const distTag = getNpmDistTag(version);
			const args = ["publish", tarballPath, "--provenance", "--registry", NPM_URL];
			if (distTag !== "latest") {
				args.push("--tag", distTag);
			}
			execFileSync("npm", args, {
				stdio: "inherit",
			});

const token = process.env.DISCORD_TOKEN ?? process.env.BOT_TOKEN;
await client.login(token);
}
void init();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The init function is async but is called without handling potential promise rejections (void init()). If client.login(token) fails, this will result in an unhandled promise rejection, which can crash the Node.js process.

It's safer to handle potential errors, even in an example file.

Suggested change
void init();
init().catch((error) => {
console.error("Failed to initialize client:", error);
process.exit(1);
});

return result;
}

toJSON() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The method name toJSON is a bit misleading. Conventionally, toJSON methods return a value that is serializable to a JSON string. However, this method returns an object that includes a function (t), which is not serializable. This could be confusing for developers using the class.

Consider renaming it to something that better reflects its purpose, such as asPayload() or getContextPayload().

Suggested change
toJSON() {
asPayload() {

) {
return new Promise<void>((r) => {
setTimeout(() => {
message.delete().catch(() => {});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The .catch(() => {}) swallows any errors that might occur when trying to delete a message. For example, if the message was already deleted by a user or another process, an error would be thrown and silently ignored. This can make debugging difficult.

It's better to at least log the error to the console for visibility during development.

Suggested change
message.delete().catch(() => {});
message.delete().catch(console.warn);

Comment on lines +46 to +48
"noImplicitReturns": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The compiler options noUnusedLocals and noUnusedParameters are currently disabled. Enabling them helps maintain code quality by flagging dead code and unused variables, which can prevent bugs and improve readability.

I recommend enabling these options. For intentionally unused variables, you can prefix them with an underscore (e.g., _variableName) to signal intent and satisfy the compiler.

Suggested change
"noImplicitReturns": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": false,
"noUnusedLocals": true,
"noUnusedParameters": true,

"composite": false,
"sourceMap": false,

"verbatimModuleSyntax": false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The verbatimModuleSyntax option is set to false. The modern recommended setting for new projects is true. It enforces that your import statements are emitted as-is, which prevents certain classes of bugs related to module interoperability between CommonJS and ES modules, and makes the code's module-related behavior more predictable.

Suggested change
"verbatimModuleSyntax": false
"verbatimModuleSyntax": true

@vrdons vrdons deleted the feat/main branch March 8, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant