From fc13908c5780fd5087fa6470528d544f3089d33d Mon Sep 17 00:00:00 2001 From: Viktor Zdorovtsev Date: Sat, 19 Apr 2025 21:39:24 +0700 Subject: [PATCH 1/2] add error handler --- packages/steiger/package.json | 1 + packages/steiger/src/app.ts | 41 +++++++++------- packages/steiger/src/features/handle-error.ts | 48 +++++++++++++++++++ pnpm-lock.yaml | 3 ++ 4 files changed, 75 insertions(+), 18 deletions(-) create mode 100644 packages/steiger/src/features/handle-error.ts diff --git a/packages/steiger/package.json b/packages/steiger/package.json index 09fba59..8aa48df 100644 --- a/packages/steiger/package.json +++ b/packages/steiger/package.json @@ -54,6 +54,7 @@ "patronum": "^2.3.0", "picocolors": "^1.1.1", "prexit": "^2.3.0", + "tsconfck": "^3.1.4", "yargs": "^17.7.2", "zod": "^3.24.1", "zod-validation-error": "^3.4.0" diff --git a/packages/steiger/src/app.ts b/packages/steiger/src/app.ts index 05687d3..8d1f97b 100644 --- a/packages/steiger/src/app.ts +++ b/packages/steiger/src/app.ts @@ -8,6 +8,7 @@ import { $enabledRules, getEnabledRules, getGlobalIgnores } from './models/confi import { runRule } from './features/run-rule' import { removeGlobalIgnoreFromVfs } from './features/remove-global-ignores-from-vfs' import { calculateFinalSeverities } from './features/calculate-diagnostic-severities' +import { handleError } from './features/handle-error' // TODO: make this part of a plugin function getRuleDescriptionUrl(ruleName: string) { @@ -18,26 +19,30 @@ function getRuleDescriptionUrl(ruleName: string) { } async function runRules({ vfs, rules }: { vfs: Folder; rules: Array }) { - const vfsWithoutGlobalIgnores = removeGlobalIgnoreFromVfs(vfs, getGlobalIgnores()) + try { + const vfsWithoutGlobalIgnores = removeGlobalIgnoreFromVfs(vfs, getGlobalIgnores()) - const ruleResults = await Promise.all(rules.map((rule) => runRule(vfsWithoutGlobalIgnores, rule))) - return ruleResults.flatMap(({ diagnostics }, ruleResultsIndex) => { - const ruleName = rules[ruleResultsIndex].name - const severities = calculateFinalSeverities( - vfsWithoutGlobalIgnores, - ruleName, - diagnostics.map((d) => d.location.path), - ) - - return diagnostics - .sort((a, b) => a.location.path.localeCompare(b.location.path)) - .map((d, index) => ({ - ...d, + const ruleResults = await Promise.all(rules.map((rule) => runRule(vfsWithoutGlobalIgnores, rule))) + return ruleResults.flatMap(({ diagnostics }, ruleResultsIndex) => { + const ruleName = rules[ruleResultsIndex].name + const severities = calculateFinalSeverities( + vfsWithoutGlobalIgnores, ruleName, - getRuleDescriptionUrl, - severity: severities[index], - })) - }) + diagnostics.map((d) => d.location.path), + ) + + return diagnostics + .sort((a, b) => a.location.path.localeCompare(b.location.path)) + .map((d, index) => ({ + ...d, + ruleName, + getRuleDescriptionUrl, + severity: severities[index], + })) + }) + } catch (error) { + handleError(error, { vfs }) + } } export const linter = { diff --git a/packages/steiger/src/features/handle-error.ts b/packages/steiger/src/features/handle-error.ts new file mode 100644 index 0000000..f9d988e --- /dev/null +++ b/packages/steiger/src/features/handle-error.ts @@ -0,0 +1,48 @@ +import { readFileSync } from 'fs' +import { join } from 'path' +import { TSConfckParseError } from 'tsconfck' +import { Folder } from '@steiger/types' + +interface ErrorContext { + vfs: Folder +} + +interface PackageJson { + dependencies?: Record + devDependencies?: Record +} + +const readPackageJSON = (path: string) => JSON.parse(readFileSync(join(path, 'package.json'), 'utf-8')) as PackageJson + +async function checkNuxtConfigError(error: unknown, { vfs }: ErrorContext) { + if (!(error instanceof TSConfckParseError)) return false + if (error.code !== 'EXTENDS_RESOLVE') return false + if (!error.cause?.message?.includes('.nuxt/tsconfig')) return false + + try { + const projectRootPath = vfs.path + const packageJson = readPackageJSON(projectRootPath) + const hasNuxt = !!(packageJson.dependencies?.nuxt || packageJson.devDependencies?.nuxt) + if (!hasNuxt) return false + + console.error('\n\x1b[31mError: Unable to find Nuxt TypeScript configuration\x1b[0m') + console.error('\nThis appears to be a Nuxt project, but the TypeScript configuration files are missing.') + console.error('These files are auto-generated when you install dependencies.') + console.error('\nTo fix this:') + console.error('1. Run \x1b[36mnpm install\x1b[0m or \x1b[36myarn\x1b[0m or \x1b[36mpnpm install\x1b[0m') + console.error('2. Then run Steiger again\n') + return true + } catch { + return false + } +} + +export function handleError(error: unknown, context: ErrorContext): never { + const isHandled = [checkNuxtConfigError].some((checker) => checker(error, context)) + + if (isHandled) { + process.exit(1) + } + + throw error +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0001567..9924141 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -157,6 +157,9 @@ importers: prexit: specifier: ^2.3.0 version: 2.3.0 + tsconfck: + specifier: ^3.1.4 + version: 3.1.4(typescript@5.7.3) yargs: specifier: ^17.7.2 version: 17.7.2 From a9d1fcb2eca3f17b2c72b15d44452fc4d8d4e2c1 Mon Sep 17 00:00:00 2001 From: Viktor Zdorovtsev Date: Sat, 19 Apr 2025 21:39:39 +0700 Subject: [PATCH 2/2] add example nuxt app --- examples/nuxt-app/.gitignore | 24 ++++++++ examples/nuxt-app/README.md | 75 +++++++++++++++++++++++++ examples/nuxt-app/app.vue | 6 ++ examples/nuxt-app/nuxt.config.ts | 5 ++ examples/nuxt-app/package.json | 17 ++++++ examples/nuxt-app/public/favicon.ico | Bin 0 -> 4286 bytes examples/nuxt-app/public/robots.txt | 2 + examples/nuxt-app/server/tsconfig.json | 3 + examples/nuxt-app/tsconfig.json | 4 ++ 9 files changed, 136 insertions(+) create mode 100644 examples/nuxt-app/.gitignore create mode 100644 examples/nuxt-app/README.md create mode 100644 examples/nuxt-app/app.vue create mode 100644 examples/nuxt-app/nuxt.config.ts create mode 100644 examples/nuxt-app/package.json create mode 100644 examples/nuxt-app/public/favicon.ico create mode 100644 examples/nuxt-app/public/robots.txt create mode 100644 examples/nuxt-app/server/tsconfig.json create mode 100644 examples/nuxt-app/tsconfig.json diff --git a/examples/nuxt-app/.gitignore b/examples/nuxt-app/.gitignore new file mode 100644 index 0000000..4a7f73a --- /dev/null +++ b/examples/nuxt-app/.gitignore @@ -0,0 +1,24 @@ +# Nuxt dev/build outputs +.output +.data +.nuxt +.nitro +.cache +dist + +# Node dependencies +node_modules + +# Logs +logs +*.log + +# Misc +.DS_Store +.fleet +.idea + +# Local env files +.env +.env.* +!.env.example diff --git a/examples/nuxt-app/README.md b/examples/nuxt-app/README.md new file mode 100644 index 0000000..25b5821 --- /dev/null +++ b/examples/nuxt-app/README.md @@ -0,0 +1,75 @@ +# Nuxt Minimal Starter + +Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. + +## Setup + +Make sure to install dependencies: + +```bash +# npm +npm install + +# pnpm +pnpm install + +# yarn +yarn install + +# bun +bun install +``` + +## Development Server + +Start the development server on `http://localhost:3000`: + +```bash +# npm +npm run dev + +# pnpm +pnpm dev + +# yarn +yarn dev + +# bun +bun run dev +``` + +## Production + +Build the application for production: + +```bash +# npm +npm run build + +# pnpm +pnpm build + +# yarn +yarn build + +# bun +bun run build +``` + +Locally preview production build: + +```bash +# npm +npm run preview + +# pnpm +pnpm preview + +# yarn +yarn preview + +# bun +bun run preview +``` + +Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. diff --git a/examples/nuxt-app/app.vue b/examples/nuxt-app/app.vue new file mode 100644 index 0000000..09f935b --- /dev/null +++ b/examples/nuxt-app/app.vue @@ -0,0 +1,6 @@ + diff --git a/examples/nuxt-app/nuxt.config.ts b/examples/nuxt-app/nuxt.config.ts new file mode 100644 index 0000000..b2f16b5 --- /dev/null +++ b/examples/nuxt-app/nuxt.config.ts @@ -0,0 +1,5 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + compatibilityDate: '2024-11-01', + devtools: { enabled: true }, +}) diff --git a/examples/nuxt-app/package.json b/examples/nuxt-app/package.json new file mode 100644 index 0000000..971afba --- /dev/null +++ b/examples/nuxt-app/package.json @@ -0,0 +1,17 @@ +{ + "name": "nuxt-app", + "private": true, + "type": "module", + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "postinstall": "nuxt prepare" + }, + "dependencies": { + "nuxt": "^3.16.2", + "vue": "^3.5.13", + "vue-router": "^4.5.0" + } +} diff --git a/examples/nuxt-app/public/favicon.ico b/examples/nuxt-app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..18993ad91cfd43e03b074dd0b5cc3f37ab38e49c GIT binary patch literal 4286 zcmeHLOKuuL5PjK%MHWVi6lD zOGiREbCw`xmFozJ^aNatJY>w+g ze6a2@u~m#^BZm@8wco9#Crlli0uLb^3E$t2-WIc^#(?t)*@`UpuofJ(Uyh@F>b3Ph z$D^m8Xq~pTkGJ4Q`Q2)te3mgkWYZ^Ijq|hkiP^9`De={bQQ%heZC$QU2UpP(-tbl8 zPWD2abEew;oat@w`uP3J^YpsgT%~jT(Dk%oU}sa$7|n6hBjDj`+I;RX(>)%lm_7N{+B7Mu%H?422lE%MBJH!!YTN2oT7xr>>N-8OF$C&qU^ z>vLsa{$0X%q1fjOe3P1mCv#lN{xQ4_*HCSAZjTb1`}mlc+9rl8$B3OP%VT@mch_~G z7Y+4b{r>9e=M+7vSI;BgB?ryZDY4m>&wcHSn81VH1N~`0gvwH{ z8dv#hG|OK`>1;j7tM#B)Z7zDN?{6=dUal}$e