Skip to content

Commit

Permalink
Knip for dep checking - working example for build-cli package
Browse files Browse the repository at this point in the history
  • Loading branch information
pragya91 committed Mar 7, 2025
1 parent 8204812 commit 532f07a
Show file tree
Hide file tree
Showing 10 changed files with 375 additions and 572 deletions.
27 changes: 27 additions & 0 deletions build-tools/packages/build-cli/knip.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*!
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
* Licensed under the MIT License.
*/

// Enable TypeScript type-checking for this file.
// See https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check
// @ts-check

// Import the shared config from the root of the repo.
import sharedConfig from "../../../knip.base.ts";

export default {
include: [...sharedConfig.include],
ignoreDependencies: [
...sharedConfig.ignoreDependencies,

// Oclif plugins are used dynamically at runtime.
"@oclif/plugin-*",
// Danger is used at runtime in the dangerfile.
"danger",
// Types from this package are used in markdown.ts.
"mdast",
// This is needed by the fluid-build task integration in policy-check.
"tslib",
],
};
49 changes: 4 additions & 45 deletions build-tools/packages/build-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
"build:test:esm": "tsc --project ./src/test/tsconfig.json",
"check:biome": "biome check .",
"check:format": "npm run check:biome",
"check:knip": "knip --no-config-hints",
"knip:fix": "knip --fix --fix-type dependencies --no-config-hints",
"ci:build:docs": "api-extractor run",
"clean": "rimraf --glob dist lib oclif.manifest.json \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
"clean:manifest": "rimraf --glob oclif.manifest.json",
Expand Down Expand Up @@ -79,106 +81,63 @@
"temp-directory": "nyc/.nyc_output"
},
"dependencies": {
"@andrewbranch/untar.js": "^1.0.3",
"@fluid-tools/build-infrastructure": "workspace:~",
"@fluid-tools/version-tools": "workspace:~",
"@fluidframework/build-tools": "workspace:~",
"@fluidframework/bundle-size-tools": "workspace:~",
"@inquirer/prompts": "^7.0.1",
"@microsoft/api-extractor": "^7.47.11",
"@oclif/core": "^4.0.30",
"@oclif/plugin-autocomplete": "^3.2.7",
"@oclif/plugin-commands": "^4.1.5",
"@oclif/plugin-help": "^6.2.16",
"@oclif/plugin-not-found": "^3.2.24",
"@octokit/core": "^5.2.0",
"@octokit/rest": "^21.0.2",
"@rushstack/node-core-library": "^5.9.0",
"async": "^3.2.6",
"azure-devops-node-api": "^11.2.0",
"change-case": "^3.1.0",
"cosmiconfig": "^8.3.6",
"danger": "^12.3.3",
"date-fns": "^2.30.0",
"debug": "^4.3.7",
"depcheck": "^1.4.7",
"execa": "^5.1.1",
"fflate": "^0.8.2",
"fs-extra": "^11.2.0",
"github-slugger": "^2.0.0",
"globby": "^11.1.0",
"gray-matter": "^4.0.3",
"human-id": "^4.1.1",
"issue-parser": "^7.0.1",
"json5": "^2.2.3",
"jssm": "^5.104.1",
"jszip": "^3.10.1",
"latest-version": "^9.0.0",
"mdast": "^3.0.0",
"mdast-util-heading-range": "^4.0.0",
"mdast-util-to-string": "^4.0.0",
"minimatch": "^7.4.6",
"npm-check-updates": "^16.14.20",
"oclif": "^4.15.16",
"picocolors": "^1.1.1",
"prettier": "~3.2.5",
"prompts": "^2.4.2",
"read-pkg-up": "^7.0.1",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
"remark-github": "^12.0.0",
"remark-github-beta-blockquote-admonitions": "^3.1.1",
"remark-toc": "^9.0.0",
"replace-in-file": "^7.2.0",
"resolve.exports": "^2.0.2",
"semver": "^7.6.3",
"semver-utils": "^1.1.4",
"simple-git": "^3.27.0",
"sort-json": "^2.0.1",
"sort-package-json": "1.57.0",
"strip-ansi": "^6.0.1",
"table": "^6.8.2",
"ts-morph": "^22.0.0",
"type-fest": "^2.19.0",
"unist-util-visit": "^5.0.0",
"xml2js": "^0.5.0"
"type-fest": "^2.19.0"
},
"devDependencies": {
"@biomejs/biome": "~1.9.3",
"@fluidframework/build-common": "^2.0.3",
"@fluidframework/eslint-config-fluid": "^5.4.0",
"@oclif/test": "^4.1.0",
"@types/async": "^3.2.24",
"@types/chai": "^4.3.20",
"@types/chai-arrays": "^2.0.3",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/issue-parser": "^3.0.5",
"@types/mdast": "^4.0.4",
"@types/mocha": "^10.0.9",
"@types/node": "^18.19.59",
"@types/prettier": "^2.7.3",
"@types/prompts": "^2.4.9",
"@types/semver": "^7.5.8",
"@types/semver-utils": "^1.1.3",
"@types/sort-json": "^2.0.3",
"@types/unist": "^3.0.3",
"@types/xml2js": "^0.4.14",
"c8": "^7.14.0",
"chai": "^4.5.0",
"chai-arrays": "^2.2.0",
"concurrently": "^8.2.2",
"copyfiles": "^2.4.1",
"eslint": "~8.57.0",
"eslint-config-oclif": "^5.2.1",
"eslint-config-oclif-typescript": "^3.1.12",
"eslint-config-prettier": "~9.1.0",
"jssm-viz-cli": "^5.101.0",
"knip": "^5.45.0",
"mocha": "^10.7.3",
"mocha-multi-reporters": "^1.5.1",
"mocked-env": "^1.3.5",
"rimraf": "^4.4.1",
"ts-node": "^10.9.2",
"tslib": "^2.8.0",
"typescript": "~5.4.5"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ export class CheckPolicy extends BaseCommand<typeof CheckPolicy> {
// Resolvers are expected to be run serially to avoid any conflicts.
// eslint-disable-next-line no-await-in-loop
const resolveResult = await runWithPerf(handler.name, "resolve", async () =>
resolver(relPath, gitRoot, result),
resolver(relPath, gitRoot),
);

if (resolveResult?.message !== undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ export interface Handler {
resolver?: (
file: string,
root: string,
/* output from the handler */
handlerOutput: string,
) =>
| Promise<{ resolved: boolean; message?: string }>
| { resolved: boolean; message?: string };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import { createRequire } from "node:module";
import { EOL as newline } from "node:os";
import path from "node:path";
import {
findGitRootSync,
updatePackageJsonFile,
updatePackageJsonFileAsync,
} from "@fluid-tools/build-infrastructure";
import { findGitRootSync } from "@fluid-tools/build-infrastructure";
import { PackageJson, getApiExtractorConfigFilePath } from "@fluidframework/build-tools";
import depcheck from "depcheck";
import { writeJson } from "fs-extra/esm";
import JSON5 from "json5";
import replace from "replace-in-file";
Expand Down Expand Up @@ -1966,69 +1965,6 @@ export const handlers: Handler[] = [
}
});

return result;
},
},
{
name: "npm-check-unused-dependencies",
match,
handler: async (file: string): Promise<string | undefined> => {
const depcheckConfigFileName = ".depcheckrc.cjs";
const packageDir = path.resolve(path.dirname(file));
const depcheckConfigFilePath = path.resolve(
path.join(packageDir, depcheckConfigFileName),
);
const configExists = fs.existsSync(depcheckConfigFilePath);
let options: depcheck.Options = {};
if (configExists) {
try {
options = require(depcheckConfigFilePath) as depcheck.Options;
} catch (error) {
console.log(`Error reading ${depcheckConfigFileName} file for ${packageDir}`, error);
return;
}
}
try {
const result = await depcheck(packageDir, options);
const packageErrors: string[] = [];
if (result.devDependencies.length > 0) {
packageErrors.push(`[Unused devDependencies]:${result.devDependencies.join(",")}`);
}
if (result.dependencies.length > 0) {
packageErrors.push(`[Unused dependencies]:${result.dependencies.join(",")}`);
}
return packageErrors.length > 0 ? packageErrors.join(newline) : undefined;
} catch (error) {
return `Error running depcheck for ${packageDir}: ${error}`;
}
},
resolver: async (
file: string,
_root: string,
handlerOutput: string,
): Promise<{ resolved: boolean; message?: string }> => {
const result: { resolved: boolean; message?: string } = { resolved: true };
updatePackageJsonFile(path.dirname(file), (packageJson) => {
// Extract the errored dependencies from the error message output generated by the handler above.
const [devDependencyErrorString, dependencyErrorString] = handlerOutput.split(newline);
const devDependencyErroredPkgs = devDependencyErrorString?.split(":")[1]?.split(",");
const dependencyErroredPkgs = dependencyErrorString?.split(":")[1]?.split(",");

if (devDependencyErroredPkgs !== undefined && devDependencyErroredPkgs.length > 0) {
// Delete unused dev dependency declaration from package.json
for (const pkgName of devDependencyErroredPkgs) {
delete packageJson.devDependencies?.[pkgName];
}
}

if (dependencyErroredPkgs !== undefined && dependencyErroredPkgs.length > 0) {
// Delete unused dependency declaration from package.json
for (const pkgName of dependencyErroredPkgs) {
delete packageJson.dependencies?.[pkgName];
}
}
});

return result;
},
},
Expand Down
Loading

0 comments on commit 532f07a

Please sign in to comment.