diff --git a/README.md b/README.md index 4bd2ea746..cf5499d13 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,14 @@ This is where Exportman comes in: - [x] Resolves all (unused) files in your project and reports **unused files and exports**. - [x] Verifies that exported symbols are actually used in other files, even when part of an imported namespace. - [x] Finds duplicate exports of the same symbol. -- [ ] Supports JavaScript projects with CommonJS and ES Modules (TODO). +- [x] Supports JavaScript inside TypeScript projects (`"allowJs": true`) +- [ ] Supports JavaScript-only projects with CommonJS and ESM (no `tsconfig.json`) - TODO Exportman really shines in larger projects where you have much more files (such as `/docs`, `/tools` and `/scripts`) than only production code. The `includes` setting in `tsconfig.json` is often too broad, resulting in too many false negatives. Similar projects either detect only unimported files, or only unused exports. Most of them don't work by configuring entry files, an essential feature to produce good results. This also allows to unleash Exportman on a -specific part of your project, and scan/handle these separately. +specific part of your project, and work these separately. Exportman is another fresh take on keeping your projects clean & tidy. @@ -37,13 +38,13 @@ Create a configuration file, let's name it `.exportman.json` with these contents ```json { - "entryFiles": ["src/index.tsx"], - "filePatterns": ["src/**/*.{ts,tsx}", "!**/*.spec.{ts,tsx}"] + "entryFiles": ["src/index.ts"], + "filePatterns": ["src/**/*.ts", "!**/*.spec.ts"] } ``` -The `entryFiles` target the starting point(s) to resolve dependencies. The `filePatterns` should contain all files it -should match them against (including potentially unused files). +The `entryFiles` target the starting point(s) to resolve production code dependencies. The `filePatterns` should contain +all files it should match them against, including potentially unused files. Then run the checks: @@ -53,6 +54,22 @@ npx exportman --config .exportman This will analyze the project and output unused files, exports, types and duplicate exports. +Use `--onlyFiles` when configuring Exportman for faster initial results. + +## How It Works + +Exportman works by creating two sets of files: + +1. Production code is the set of files resolved from the `entryFiles`. +2. Project files are the full set of files matching the `filePatterns`. +3. The subset of project files that are not production code will be reported as unused files (in red). +4. Then the production code (in blue) will be scanned for unused exports. + +![How it works](./assets/how-it-works.drawio.svg) + +Clean and actionable reports are achieved when non-production code such as tests are excluded from the `filePatterns` +(using negation patterns such as `!**/*.test.ts`). + ## Options ``` @@ -81,12 +98,32 @@ More info: https://github.com/webpro/exportman ## More configuration examples +### Test files + +For best results, it is recommended to exclude files such as tests from the project files. When including tests and +other non-production files, they may prevent production files from being reported as unused. Not including them will +make it clear what production files can be removed (including dependent files!). + +The same goes for any type of non-production files, such as Storybook stories or end-to-end tests. + +To report dangling files and exports that are not used by any of the production or test files, include both to the set +of `entryFiles`: + +```json +{ + "entryFiles": ["src/index.ts", "src/**/*.spec.ts"], + "filePatterns": ["src/**/*.ts", "!**/*.e2e.ts"] +} +``` + +In theory this idea could be extended to report some kind of test coverage. + ### Monorepos #### Separate packages In repos with multiple packages, the `--cwd` option comes in handy. With similar package structures, the packages can be -configured conveniently using globs: +configured using globs: ```json { @@ -97,18 +134,20 @@ configured conveniently using globs: } ``` -Packages can also be explicitly configured per package directory. To scan the packages separately, using the first match -from the configuration file: +Packages can also be explicitly configured per package directory. + +To scan the packages separately, using the first match from the configuration file: ``` exportman --cwd packages/client --config exportman.json exportman --cwd packages/services --config exportman.json ``` -#### Connected projects (e.g. using Nx) +#### Connected projects A good example of a large project setup is a monorepo, such as created with Nx. Let's take an example project -configuration for an Nx project using Next.js, Jest and Storybook: +configuration for an Nx project using Next.js, Jest and Storybook. This can also be a JavaScript file, which allows to +add logic and/or comments: ```js const entryFiles = ['apps/**/pages/**/*.{js,ts,tsx}']; @@ -130,39 +169,8 @@ const filePatterns = [ module.exports = { entryFiles, filePatterns }; ``` -This should give good results about unused files and exports. After the first run, the configuration can be tweaked -further to the project structure. - -### Test Coverage - -This can also be turned around: which source files are not covered by tests? Here's an example configuration based on -the previous one: - -```js -const entryFiles = ['{apps,libs}/**/*.spec.{ts,tsx}']; - -const filePatterns = [ - '{apps,libs}/**/*.{ts,tsx}', - '!apps/**/pages/**/*.{ts,tsx}', - // Next.js - '!**/next.config.js', - '!**/apps/**/public/**', - '!**/apps/**/next-env.d.ts' - // Jest - '!**/jest.config.ts', - // Storybook - '!**/.storybook/**', - '!**/*.stories.tsx', -]; - -module.exports = { entryFiles, filePatterns }; -``` - -``` -npx exportman --config exportman.config --onlyFiles -``` - -This will output the production files that are not imported from test files or their dependencies, etc. +This should give good results about unused files and exports for the monorepo. After the first run, the configuration +can be tweaked further to the project structure. ## Example Output diff --git a/assets/how-it-works.drawio.svg b/assets/how-it-works.drawio.svg new file mode 100644 index 000000000..68194b2ad --- /dev/null +++ b/assets/how-it-works.drawio.svg @@ -0,0 +1,53 @@ + + + + + + + +
+
+
+ Project files +
+ (filePatterns) +
+
+
+
+
+
+ + Project files... + +
+
+ + + + +
+
+
+ Production code +
+ (entryFiles) +
+
+
+
+ + Production code... + +
+
+
+ + + + + Viewer does not support full SVG 1.1 + + + +
diff --git a/package.json b/package.json index 9bc14b9c9..40574db3f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,18 @@ "name": "exportman", "version": "0.0.3", "description": "Find unused files and exports in your TypeScript project", + "keywords": [ + "find", + "detect", + "unused", + "files", + "exports", + "types", + "duplicates", + "typescript", + "maintenance", + "unimported" + ], "main": "dist/index.js", "bin": { "exportman": "dist/cli.js" @@ -16,7 +28,6 @@ "files": [ "dist" ], - "keywords": [], "author": { "name": "Lars Kappert", "email": "lars@webpro.nl"