diff --git a/apps/oxlint/src-js/bindings.d.ts b/apps/oxlint/src-js/bindings.d.ts index f6f01edf9a219..bb40670519105 100644 --- a/apps/oxlint/src-js/bindings.d.ts +++ b/apps/oxlint/src-js/bindings.d.ts @@ -11,10 +11,11 @@ export type JsLoadPluginCb = /** * NAPI entry point. * - * JS side passes in two callbacks: - * 1. `load_plugin`: Load a JS plugin from a file path. - * 2. `lint_file`: Lint a file. + * JS side passes in: + * 1. `args`: Command line arguments (process.argv.slice(2)) + * 2. `load_plugin`: Load a JS plugin from a file path. + * 3. `lint_file`: Lint a file. * * Returns `true` if linting succeeded without errors, `false` otherwise. */ -export declare function lint(loadPlugin: JsLoadPluginCb, lintFile: JsLintFileCb): Promise +export declare function lint(args: Array, loadPlugin: JsLoadPluginCb, lintFile: JsLintFileCb): Promise diff --git a/apps/oxlint/src-js/cli.ts b/apps/oxlint/src-js/cli.ts index 929d2a91f7776..2244f8e010ead 100644 --- a/apps/oxlint/src-js/cli.ts +++ b/apps/oxlint/src-js/cli.ts @@ -20,8 +20,11 @@ function lintFileWrapper(filePath: string, bufferId: number, buffer: Uint8Array return lintFile(filePath, bufferId, buffer, ruleIds); } -// Call Rust, passing `loadPlugin` and `lintFile` as callbacks -const success = await lint(loadPluginWrapper, lintFileWrapper); +// Get command line arguments, skipping first 2 (node binary and script path) +const args = process.argv.slice(2); + +// Call Rust, passing `loadPlugin` and `lintFile` as callbacks, and CLI arguments +const success = await lint(args, loadPluginWrapper, lintFileWrapper); // Note: It's recommended to set `process.exitCode` instead of calling `process.exit()`. // `process.exit()` kills the process immediately and `stdout` may not be flushed before process dies. diff --git a/apps/oxlint/src/run.rs b/apps/oxlint/src/run.rs index bce2905e6679d..bef2944bbc3f6 100644 --- a/apps/oxlint/src/run.rs +++ b/apps/oxlint/src/run.rs @@ -49,27 +49,30 @@ pub type JsLintFileCb = ThreadsafeFunction< /// NAPI entry point. /// -/// JS side passes in two callbacks: -/// 1. `load_plugin`: Load a JS plugin from a file path. -/// 2. `lint_file`: Lint a file. +/// JS side passes in: +/// 1. `args`: Command line arguments (process.argv.slice(2)) +/// 2. `load_plugin`: Load a JS plugin from a file path. +/// 3. `lint_file`: Lint a file. /// /// Returns `true` if linting succeeded without errors, `false` otherwise. #[expect(clippy::allow_attributes)] #[allow(clippy::trailing_empty_array, clippy::unused_async)] // https://github.com/napi-rs/napi-rs/issues/2758 #[napi] -pub async fn lint(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool { - lint_impl(load_plugin, lint_file).report() == ExitCode::SUCCESS +pub async fn lint(args: Vec, load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> bool { + lint_impl(args, load_plugin, lint_file).report() == ExitCode::SUCCESS } /// Run the linter. -fn lint_impl(load_plugin: JsLoadPluginCb, lint_file: JsLintFileCb) -> CliRunResult { +fn lint_impl( + args: Vec, + load_plugin: JsLoadPluginCb, + lint_file: JsLintFileCb, +) -> CliRunResult { init_tracing(); init_miette(); - // 1st arg is path to NodeJS binary. - // 2nd arg is path to `oxlint/.bin/oxlint` (in released packages) - // or `apps/oxlint/dist/cli.js` (in development). - let args = std::env::args_os().skip(2).collect::>(); + // Convert String args to OsString for compatibility with bpaf + let args: Vec = args.into_iter().map(std::ffi::OsString::from).collect(); let cmd = crate::cli::lint_command(); let command = match cmd.run_inner(&*args) {