Skip to content

Commit

Permalink
auto fix missing dependencies (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
zzcwoshizz authored Feb 17, 2023
1 parent 70521e5 commit 22e005a
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 75 deletions.
6 changes: 6 additions & 0 deletions .changeset/brave-spoons-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@zcloak/lint': minor
'@zcloak/dev': minor
---

auto fix missing dependencies
6 changes: 6 additions & 0 deletions .changeset/real-bikes-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@zcloak/dev': minor
'@zcloak/lint': minor
---

test
20 changes: 18 additions & 2 deletions packages/dev/scripts/zcloak-dev-lint-dependencies.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@

import fs from 'fs';
import path from 'path';
import yargs from 'yargs';

import { lintDependencies } from '@zcloak/lint';
import { error } from '@zcloak/lint/feedback';
import { error, warn } from '@zcloak/lint/feedback';

console.log('$ zcloak-dev-lint-dependencies', process.argv.slice(2).join(' '));

const argv = yargs(process.argv.slice(2))
.options({
fix: {
description: 'Auto fix errors',
type: 'boolean'
}
})
.strict().argv;

(async () => {
process.chdir('packages');
const dirs = fs
Expand All @@ -19,6 +29,7 @@ console.log('$ zcloak-dev-lint-dependencies', process.argv.slice(2).join(' '));
);

const errors = [];
const warns = [];

const locals = [];

Expand All @@ -38,15 +49,20 @@ console.log('$ zcloak-dev-lint-dependencies', process.argv.slice(2).join(' '));
!fs.existsSync(path.join(process.cwd(), 'public')) &&
!fs.existsSync(path.join(process.cwd(), '.skip-build'))
) {
const { errors: _errors } = await lintDependencies(`packages/${dir}`, locals);
const { errors: _errors, warns: _warns } = await lintDependencies(
`packages/${dir}`,
argv.fix
);

errors.push(..._errors);
warns.push(..._warns);
}

process.chdir('..');
}

errors.forEach((e) => error(e));
warns.forEach((w) => warn(w));

if (errors.length > 0) {
process.exit(1);
Expand Down
107 changes: 34 additions & 73 deletions packages/lint/src/lintDependencies.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright 2021-2023 zcloak authors & contributors
// SPDX-License-Identifier: Apache-2.0

import fs from 'fs';
import { execSync } from 'child_process';
import glob from 'glob';
import { ImportedPackageType, parse as parseTs } from 'parse-imports-ts';
import path, { join } from 'path';
import { join } from 'path';
import throatFactory from 'throat';

import { error } from './feedback';
Expand All @@ -25,6 +25,7 @@ const ignoredDependencies = [
// other
'@jest/globals',
'react',
'react-dom',
'react-native'
];

Expand Down Expand Up @@ -153,37 +154,11 @@ async function getTestFiles(): Promise<string[]> {

interface Errors {
errors: string[];
warns: string[];
}

function getReferences(config: string): [string[], boolean] {
const configPath = path.join(process.cwd(), config);

if (fs.existsSync(configPath)) {
try {
return [
JSON.parse(fs.readFileSync(configPath, 'utf-8')).references.map(
({ path }: { path: string }) =>
path.replace('../', '').replace('/tsconfig.build.json', '')
),
true
];
} catch (error) {
console.error(`Unable to parse ${configPath}`);

throw error;
}
}

return [[], false];
}

function getErrors(
base: string,
locals: [string, string][],
packageJson: any,
imports: ImportDetails[]
): Errors {
const result: Errors = { errors: [] };
function getErrors(base: string, packageJson: any, imports: ImportDetails[], fix: boolean): Errors {
const result: Errors = { errors: [], warns: [] };

// Report any package used in the src folder that are not specified in the dependencies or peerDependencies.
imports.forEach((i) => {
Expand All @@ -201,11 +176,15 @@ function getErrors(
}

if (i.files.length > 0) {
result.errors.push(
`The package "${i.name}" is used in the files ${i.files
.map((file) => `"${base}/${file}"`)
.join(',')}. but it is missing from the dependencies in package.json.`
);
if (fix) {
execSync(`yarn add ${i.name}`);
} else {
result.errors.push(
`The package "${i.name}" is used in the files ${i.files
.map((file) => `"${base}/${file}"`)
.join(',')}. but it is missing from the dependencies in package.json.`
);
}
}
}

Expand All @@ -224,37 +203,16 @@ function getErrors(
}

if (i.files.length > 0) {
result.errors.push(
`Types from the package "${i.name}" are used in the files: ${i.files
.map((file) => `"${base}/${file}"`)
.join(',')}. But it is missing from the devDependencies in package.json.`
);
}
}
});

imports.forEach((i) => {
// Report local package in tsconfig.build.json
const local = locals.find(([, name]) => name === i.name);

if (local) {
const [references] = getReferences('tsconfig.build.json');

const ref = local[0];

if (references.includes(ref)) {
return;
if (fix) {
execSync(`yarn add -D ${i.name}`);
} else {
result.warns.push(
`Types from the package "${i.name}" are used in the files: ${i.files
.map((file) => `"${base}/${file}"`)
.join(',')}. But it is missing from the devDependencies in package.json.`
);
}
}
} else {
return;
}

if (i.files.length > 0) {
result.errors.push(
`The package "${i.name}" is used in the files ${i.files
.map((file) => `"${base}/${file}"`)
.join(',')}. but it is missing from the referrences in "${base}/tsconfig.build.json".`
);
}
});

Expand All @@ -270,20 +228,23 @@ function getErrors(
return;
}

result.errors.push(
`The package "${d}" is in the \`dependencies\` of package.json, but it is not used in the source folder. Remove it or move it to the \`devDependencies\`.`
);
if (fix) {
execSync(`yarn remove ${d}`);
} else {
result.warns.push(
`The package "${d}" is in the \`dependencies\` of "${base}/package.json", but it is not used in the source folder. Remove it or move it to the \`devDependencies\`.`
);
}
});

return result;
}

export async function lintDependencies(base: string, locals: [string, string][]): Promise<Errors> {
const pkgJsonPromise = readPackageJson();
export async function lintDependencies(base: string, fix = false): Promise<Errors> {
const packageJson = await readPackageJson();
const [sourceFiles, testFiles] = await Promise.all([getSourceFiles(), getTestFiles()]);
const files = getFileList(sourceFiles, testFiles);
const imports = await getImportsForFiles(files);
const packageJson = await pkgJsonPromise;

return getErrors(base, locals, packageJson, imports);
return getErrors(base, packageJson, imports, fix);
}

0 comments on commit 22e005a

Please sign in to comment.