chore(lint): switch to recommended baseline, fix errors, wire into CI

- typescript-eslint preset: strict -> recommended for a usable first-pass
  baseline (per PR discussion); ratchet up in a follow-up.
- Drop the projectService/parserOptions block. Neither `recommended` nor
  `strict` is type-aware, so it was unused; removing it also avoids the
  pnpm-workspace tsconfig-resolution failure mode flagged in review.
- Add Node + browser globals via the `globals` package so .mjs scripts and
  the dashboard stop hitting `no-undef`.
- Expand ignores: built bundles (**/public/**), Astro generated (.astro/),
  and .private/ (eval scratch). Cuts 2400+ errors in vendored output.
- Allow `_`-prefixed unused vars/args/caught errors; skip irregular
  whitespace inside comments (json-parser intentionally embeds ZWSP-escaped
  block-comment examples in JSDoc).
- Fix the residual 13 genuine errors: drop dead imports/vars, replace
  two `as any[]` in schema.ts with `Array<Record<string, unknown>>`,
  drop unused destructure in change-classifier, drop unused catch binding
  in extract-structure.mjs.
- Add EOF newline to eslint.config.mjs.
- Refresh pnpm-lock.yaml.
- Add `pnpm lint` step to .github/workflows/ci.yml so the tooling
  actually enforces something.

pnpm lint now exits 0 locally; 33+13 test files / 1445 tests still pass.
This commit is contained in:
Lum1104
2026-05-23 15:26:39 +08:00
parent 1bbfe99c64
commit a1261b4883
14 changed files with 799 additions and 34 deletions
+3
View File
@@ -20,6 +20,9 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Lint
run: pnpm lint
- name: Build core
run: pnpm --filter @understand-anything/core build
+41 -14
View File
@@ -1,29 +1,56 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import globals from 'globals';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strict,
{
files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'],
languageOptions: {
parserOptions: {
projectService: {
allowDefaultProject: ['*.config.*'],
},
},
},
},
{
ignores: [
'**/node_modules/**',
'**/dist/**',
'**/build/**',
'**/public/**',
'**/coverage/**',
'**/.understand-anything/**',
'**/.claude-plugin/**',
'**/.cursor-plugin/**',
'**/.copilot-plugin/**',
'**/coverage/**',
'**/.astro/**',
'.private/**',
],
},
);
eslint.configs.recommended,
...tseslint.configs.recommended,
{
languageOptions: {
globals: {
...globals.node,
},
},
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
},
],
'no-irregular-whitespace': ['error', { skipComments: true }],
},
},
{
files: ['understand-anything-plugin/packages/dashboard/**/*.{ts,tsx,js,jsx}'],
languageOptions: {
globals: {
...globals.browser,
},
},
},
{
files: ['**/*.test.ts', '**/*.test.tsx', '**/*.test.mjs', '**/__tests__/**/*.{ts,tsx,mjs}'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
);
+1
View File
@@ -14,6 +14,7 @@
"devDependencies": {
"@eslint/js": "^9.0.0",
"eslint": "^9.0.0",
"globals": "^17.6.0",
"typescript": "^5.7.0",
"typescript-eslint": "^8.0.0",
"vitest": "^3.1.0"
+748 -9
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -199,7 +199,7 @@ function injectTier3Node(node) {
}
}
function injectTier3Edge(edge, validNodeIds) {
function injectTier3Edge(edge, _validNodeIds) {
const r = Math.random();
if (r < 0.4) {
edge.target = "nonexistent-node-999999";
@@ -3,7 +3,6 @@ import {
parsePluginConfig,
serializePluginConfig,
type PluginConfig,
type PluginEntry,
DEFAULT_PLUGIN_CONFIG,
} from "../plugins/discovery.js";
@@ -1,7 +1,6 @@
import { describe, it, expect } from "vitest";
import {
validateGraph,
normalizeGraph,
sanitizeGraph,
autoFixGraph,
NODE_TYPE_ALIASES,
@@ -23,7 +23,7 @@ export function classifyUpdate(
totalFilesInGraph: number,
allKnownFiles: string[] = [],
): UpdateDecision {
const { newFiles, deletedFiles, structurallyChangedFiles, cosmeticOnlyFiles, unchangedFiles } = analysis;
const { newFiles, deletedFiles, structurallyChangedFiles, cosmeticOnlyFiles } = analysis;
const structuralCount = structurallyChangedFiles.length + newFiles.length + deletedFiles.length;
// No structural changes at all — skip
@@ -1,6 +1,6 @@
import type { StructuralAnalysis, CallGraphEntry } from "../../types.js";
import type { LanguageExtractor, TreeSitterNode } from "./types.js";
import { findChild, findChildren } from "./base-extractor.js";
import { findChild } from "./base-extractor.js";
/**
* Set of method names that Ruby uses for imports.
@@ -24,7 +24,6 @@ export class GraphQLParser implements AnalyzerPlugin {
private extractDefinitions(content: string): DefinitionInfo[] {
const definitions: DefinitionInfo[] = [];
const lines = content.split("\n");
// Match type, input, enum, interface, union, scalar definitions
const typeRegex = /^(type|input|enum|interface|union|scalar)\s+(\w+)/gm;
@@ -22,7 +22,6 @@ export class SQLParser implements AnalyzerPlugin {
private extractDefinitions(content: string): DefinitionInfo[] {
const definitions: DefinitionInfo[] = [];
const lines = content.split("\n");
// Match CREATE TABLE statements
const tableRegex = /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:`|")?(\w+)(?:`|")?/gi;
@@ -15,7 +15,6 @@ const require = createRequire(import.meta.url);
type TreeSitterParser = import("web-tree-sitter").Parser;
type TreeSitterLanguage = import("web-tree-sitter").Language;
type TreeSitterNode = import("web-tree-sitter").Node;
/**
* Config-driven tree-sitter plugin.
@@ -466,7 +466,7 @@ export function normalizeGraph(data: unknown): unknown {
const result = { ...d };
if (Array.isArray(d.nodes)) {
result.nodes = (d.nodes as any[]).map((node) => {
result.nodes = (d.nodes as Array<Record<string, unknown>>).map((node) => {
if (
typeof node === "object" &&
node !== null &&
@@ -480,7 +480,7 @@ export function normalizeGraph(data: unknown): unknown {
}
if (Array.isArray(d.edges)) {
result.edges = (d.edges as any[]).map((edge) => {
result.edges = (d.edges as Array<Record<string, unknown>>).map((edge) => {
if (
typeof edge === "object" &&
edge !== null &&
@@ -82,7 +82,7 @@ async function main() {
let content;
try {
content = readFileSync(absolutePath, 'utf-8');
} catch (err) {
} catch {
filesSkipped.push(file.path);
continue;
}