Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added packages/cli/assets/error.png
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This image is 1.77MB, not exactly small. Might be better if the file size can be reduced

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's your concern with this PR?

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/cli/binding/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,5 @@ module.exports.rewritePrettier = nativeBinding.rewritePrettier;
module.exports.rewriteScripts = nativeBinding.rewriteScripts;
module.exports.run = nativeBinding.run;
module.exports.runCommand = nativeBinding.runCommand;
module.exports.takeCheckFailureKind = nativeBinding.takeCheckFailureKind;
module.exports.vitePlusHeader = nativeBinding.vitePlusHeader;
2 changes: 2 additions & 0 deletions packages/cli/binding/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -369,5 +369,7 @@ export interface RunCommandResult {
pathAccesses: Record<string, PathAccess>;
}

export declare function takeCheckFailureKind(): string | null;

/** Render the Vite+ header using the Rust implementation. */
export declare function vitePlusHeader(): string;
16 changes: 16 additions & 0 deletions packages/cli/binding/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,13 @@ impl LintMessageKind {
Self::LintAndTypeCheck => "Lint or type issues found",
}
}

fn failure_kind(self) -> &'static str {
match self {
Self::LintOnly => "lint",
Self::LintAndTypeCheck => "type-aware",
}
}
}

fn parse_check_summary(line: &str) -> Option<CheckSummary> {
Expand Down Expand Up @@ -1098,6 +1105,7 @@ async fn execute_direct_subcommand(
"Formatting failed during fix",
);
}
crate::set_last_check_failure_kind(Some("formatting"));
return Ok(status);
}
}
Expand Down Expand Up @@ -1175,6 +1183,7 @@ async fn execute_direct_subcommand(
}
}
if status != ExitStatus::SUCCESS {
crate::set_last_check_failure_kind(Some(lint_message_kind.failure_kind()));
return Ok(status);
}
}
Expand Down Expand Up @@ -1211,6 +1220,7 @@ async fn execute_direct_subcommand(
&combined_output,
"Formatting failed after lint fixes were applied",
);
crate::set_last_check_failure_kind(Some("formatting"));
return Ok(status);
}
if let Some(started) = fmt_fix_started {
Expand Down Expand Up @@ -1663,6 +1673,12 @@ mod tests {
assert_eq!(kind.success_label(), "Found no warnings, lint errors, or type errors");
assert_eq!(kind.warning_heading(), "Lint or type warnings found");
assert_eq!(kind.issue_heading(), "Lint or type issues found");
assert_eq!(kind.failure_kind(), "type-aware");
}

#[test]
fn lint_message_kind_reports_plain_lint_failures() {
assert_eq!(LintMessageKind::LintOnly.failure_kind(), "lint");
}

#[test]
Expand Down
30 changes: 29 additions & 1 deletion packages/cli/binding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ mod package_manager;
#[allow(dead_code)]
mod utils;

use std::{collections::HashMap, error::Error as StdError, ffi::OsStr, fmt::Write as _, sync::Arc};
use std::{
collections::HashMap,
error::Error as StdError,
ffi::OsStr,
fmt::Write as _,
sync::{Arc, LazyLock, Mutex},
};

use napi::{anyhow, bindgen_prelude::*, threadsafe_function::ThreadsafeFunction};
use napi_derive::napi;
Expand All @@ -28,6 +34,21 @@ use crate::cli::{
BoxedResolverFn, CliOptions as ViteTaskCliOptions, ResolveCommandResult, ViteConfigResolverFn,
};

static LAST_CHECK_FAILURE_KIND: LazyLock<Mutex<Option<String>>> =
LazyLock::new(|| Mutex::new(None));

pub(crate) fn set_last_check_failure_kind(kind: Option<&str>) {
let mut last_failure_kind =
LAST_CHECK_FAILURE_KIND.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
*last_failure_kind = kind.map(str::to_owned);
}

fn take_last_check_failure_kind() -> Option<String> {
let mut last_failure_kind =
LAST_CHECK_FAILURE_KIND.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
last_failure_kind.take()
}

/// Module initialization - sets up tracing for debugging
#[napi_derive::module_init]
pub fn init() {
Expand Down Expand Up @@ -130,6 +151,8 @@ fn format_error_message(error: &(dyn StdError + 'static)) -> String {
/// and process JavaScript callbacks (via ThreadsafeFunction).
#[napi]
pub async fn run(options: CliOptions) -> Result<i32> {
set_last_check_failure_kind(None);

// Use provided cwd or current directory
let mut cwd = current_dir()?;
if let Some(options_cwd) = options.cwd {
Expand Down Expand Up @@ -198,6 +221,11 @@ pub async fn run(options: CliOptions) -> Result<i32> {
}
}

#[napi]
pub fn take_check_failure_kind() -> Option<String> {
take_last_check_failure_kind()
}

/// Render the Vite+ header using the Rust implementation.
#[napi]
pub fn vite_plus_header() -> String {
Expand Down
36 changes: 31 additions & 5 deletions packages/cli/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import { execSync } from 'node:child_process';
import { existsSync, globSync, readFileSync, readdirSync, statSync } from 'node:fs';
import { copyFile, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
import { copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { parseArgs } from 'node:util';
Expand Down Expand Up @@ -60,6 +60,7 @@ const napiArgs = process.argv

if (!skipTs) {
await buildCli();
await copyCliAssets();
buildGlobalModules();
generateLicenseFile({
title: 'Vite-Plus CLI license',
Expand Down Expand Up @@ -165,10 +166,11 @@ async function buildCli() {
console.error(formatDiagnostics(cjsDiagnostics, cjsHost));
process.exit(1);
}
await rename(
join(projectDir, 'dist/define-config.js'),
join(projectDir, 'dist/define-config.cjs'),
);
const defineConfigJsPath = join(projectDir, 'dist/define-config.js');
const defineConfigCjsPath = join(projectDir, 'dist/define-config.cjs');
if (existsSync(defineConfigJsPath)) {
await copyFile(defineConfigJsPath, defineConfigCjsPath);
}

const host = createCompilerHost(options);

Expand Down Expand Up @@ -196,6 +198,30 @@ async function buildCli() {
console.error(formatDiagnostics(diagnostics, host));
process.exit(1);
}

if (existsSync(defineConfigJsPath)) {
await copyFile(defineConfigJsPath, defineConfigCjsPath);
} else if (existsSync(defineConfigCjsPath)) {
await copyFile(defineConfigCjsPath, defineConfigJsPath);
}
}

async function copyCliAssets() {
const assetsDir = join(projectDir, 'assets');
if (!existsSync(assetsDir)) {
return;
}

const distAssetsDir = join(projectDir, 'dist', 'assets');
await mkdir(distAssetsDir, { recursive: true });

for (const entry of readdirSync(assetsDir)) {
const sourcePath = join(assetsDir, entry);
if (!statSync(sourcePath).isFile()) {
continue;
}
await copyFile(sourcePath, join(distAssetsDir, entry));
}
}

function buildGlobalModules() {
Expand Down
10 changes: 7 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@
"types": "./dist/test/internal/browser.d.ts",
"default": "./dist/test/internal/browser.js"
},
"./test/internal/module-runner": {
"types": "./dist/test/internal/module-runner.d.ts",
"default": "./dist/test/internal/module-runner.js"
},
"./test/runners": {
"types": "./dist/test/runners.d.ts",
"default": "./dist/test/runners.js"
Expand Down Expand Up @@ -131,9 +135,9 @@
"types": "./dist/test/snapshot.d.ts",
"default": "./dist/test/snapshot.js"
},
"./test/runtime": {
"types": "./dist/test/runtime.d.ts",
"default": "./dist/test/runtime.js"
"./test/mocker": {
"types": "./dist/test/mocker.d.ts",
"default": "./dist/test/mocker.js"
},
"./test/worker": {
"types": "./dist/test/worker.d.ts",
Expand Down
30 changes: 29 additions & 1 deletion packages/cli/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import path from 'node:path';

import { run } from '../binding/index.js';
import { detectWorkspace, run, takeCheckFailureKind } from '../binding/index.js';
import { applyToolInitConfigToViteConfig, inspectInitCommand } from './init-config.js';
import { doc } from './resolve-doc.js';
import { fmt } from './resolve-fmt.js';
Expand All @@ -21,6 +21,12 @@ import { pack } from './resolve-pack.js';
import { test } from './resolve-test.js';
import { resolveUniversalViteConfig } from './resolve-vite-config.js';
import { vite } from './resolve-vite.js';
import { recordCheckFailureAchievement } from './utils/check-achievements.js';
import {
normalizeCheckFailureKind,
printCheckFailureImage,
type CheckFailureKind,
} from './utils/check-failure-image.js';
import { accent, errorMsg, log } from './utils/terminal.js';

function getErrorMessage(err: unknown): string {
Expand All @@ -35,6 +41,22 @@ function getErrorMessage(err: unknown): string {
return String(err);
}

async function celebrateCheckFailure(failureKind: CheckFailureKind) {
let projectRoot = process.cwd();

try {
projectRoot = (await detectWorkspace(projectRoot)).root ?? projectRoot;
} catch {
// Fall back to the current working directory if workspace detection fails.
}

const achievementUpdate = recordCheckFailureAchievement(projectRoot, failureKind);
await printCheckFailureImage(process.stderr, process.env, {
achievementUpdate,
failureKind,
});
}

// Parse command line arguments
let args = process.argv.slice(2);

Expand Down Expand Up @@ -94,6 +116,9 @@ if (command === 'create') {
});

let finalExitCode = exitCode;
if (command === 'check' && finalExitCode !== 0) {
await celebrateCheckFailure(normalizeCheckFailureKind(takeCheckFailureKind()));
}
if (exitCode === 0) {
try {
const result = await applyToolInitConfigToViteConfig(command, args.slice(1));
Expand Down Expand Up @@ -126,6 +151,9 @@ if (command === 'create') {
process.exit(finalExitCode);
} catch (err) {
errorMsg(getErrorMessage(err));
if (command === 'check') {
await celebrateCheckFailure(normalizeCheckFailureKind(takeCheckFailureKind()));
}
process.exit(1);
}
}
Loading
Loading