netzo / fresh-netzo

Full-stack Deno Fresh meta-framework for building business web apps like internal tools, dashboards, admin panels and automated workflows.
https://netzo.io
MIT License
52 stars 2 forks source link

[chore] cleanup linting errors #112

Open deer opened 7 months ago

deer commented 7 months ago

Similar to https://github.com/netzo/netzo/issues/88, but this time for deno lint. Currently we get:

deno lint
Found 101 problems
Checked 324 files

Note you can play around with deno lint --json and deno lint --compact to alter the output a bit.

I wanted to experiment with https://docs.deno.com/runtime/manual/tools/jupyter, so I started with --json and produced the following three cells. The integration seems a bit buggy, so the types are repeated in all three cells: cell1:

import $ from "https://deno.land/x/dax@0.39.1/mod.ts";

const test = await $`deno lint --json`.stdout("piped").stderr("piped").captureCombined().noThrow();

export interface Diagnostic {
    range: {
        start: { line: number, col: number, bytePos: number },
        end: { line: number, col: number, bytePos: number }
    },
    filename: string,
    message: string,
    code: string,
    hint: string
}

export interface LintResults {
    diagnostics: Diagnostic[];
}

const jsonOutput: LintResults = JSON.parse(test.combined);

output:

(nothing)

cell2:

interface Diagnostic {
  range: {
      start: { line: number, col: number, bytePos: number },
      end: { line: number, col: number, bytePos: number }
  },
  filename: string,
  message: string,
  code: string,
  hint: string
}

interface LintResults {
  diagnostics: Diagnostic[];
}

const groupedByCode = (jsonOutput as LintResults).diagnostics.reduce((acc, diagnostic) => {
  const { code } = diagnostic;
  if (!acc[code]) {
      acc[code] = [];
  }
  acc[code].push(diagnostic);
  return acc;
}, {} as Record<string, Diagnostic[]>);

for (const [code, errors] of Object.entries(groupedByCode)) {
  console.log(`${code}: ${errors.length}`);
}

output:

no-unused-vars: 22
no-explicit-any: 65
ban-types: 4
no-empty-interface: 3
no-window: 1
no-import-assertions: 3
require-await: 3

cell3:

interface Diagnostic {
    range: {
        start: { line: number, col: number, bytePos: number },
        end: { line: number, col: number, bytePos: number }
    },
    filename: string,
    message: string,
    code: string,
    hint: string
  }

  interface LintResults {
    diagnostics: Diagnostic[];
  }

const cwd = Deno.cwd();

const filenamesAndCountsByCode: Record<string, { files: string[], count: number }> = 
    Object.keys(groupedByCode).reduce((acc, code) => {
        const diagnostics = groupedByCode[code];
        const filenames = diagnostics.map(diagnostic => diagnostic.filename.replace(cwd, "."));

        const count = diagnostics.length;

        const uniqueFilenames = [...new Set(filenames)];

        acc[code] = {
            files: uniqueFilenames,
            count: count
        };

        return acc;
    }, {} as Record<string, { files: string[], count: number }>);

console.log(filenamesAndCountsByCode);

output:

{
  "no-unused-vars": {
    files: [
      "./lib/cli/src/generators/mod.ts",
      "./lib/components/blocks/form/types.ts",
      "./lib/components/blocks/table/use-table.ts",
      "./lib/plugins/api/plugin.ts",
      "./lib/plugins/auth/routes/mod.ts",
      "./lib/resources/custom.test.ts",
      "./lib/resources/custom.ts"
    ],
    count: 22
  },
  "no-explicit-any": {
    files: [
      "./lib/components/blocks/form/fields/array.tsx",
      "./lib/components/blocks/form/fields/enum.tsx",
      "./lib/components/blocks/form/fields/object.tsx",
      "./lib/components/blocks/form/fields/radio-group.tsx",
      "./lib/components/blocks/form/types.ts",
      "./lib/components/blocks/form/utils.ts",
      "./lib/hooks/use-ui.ts",
      "./lib/plugins/api/errors.ts",
      "./lib/plugins/api/utils.ts"
    ],
    count: 65
  },
  "ban-types": {
    files: [
      "./lib/components/blocks/table/use-table.ts",
      "./lib/resources/custom.ts"
    ],
    count: 4
  },
  "no-empty-interface": {
    files: [
      "./lib/components/command.tsx",
      "./lib/components/input.tsx",
      "./lib/components/textarea.tsx"
    ],
    count: 3
  },
  "no-window": { files: [ "./lib/hooks/use-dark-mode.ts" ], count: 1 },
  "no-import-assertions": { files: [ "./lib/plugins/unocss/preset-netzo.ts" ], count: 3 },
  "require-await": {
    files: [ "./lib/resources/custom.test.ts", "./lib/resources/custom.ts" ],
    count: 3
  }
}

This offers a slightly more targeted approach to dealing with the 101 errors, which might make it more manageable.

miguelrk commented 7 months ago

This is actually pretty cool! Pretty interesting to use dax+jupyter for auditing the codebase, it reads like magic...

It might actually be very useful to have this script under tasks/... something like lint:audit/lint:inspect? Not sure if its possible/ergonomic to launch jupyter from a task... anyways, this should already help towards getting linting errors to 0

deer commented 7 months ago

I've added an issue for getting the notebook into the codebase in some form. It might just be a file you have to work with, depending on whether it's possible to invoke it from the command line or not.