Repository: webpro-nl/knip Branch: main Commit: 47210491cea2 Files: 3658 Total size: 2.4 MB Directory structure: gitextract_6vmhc_sa/ ├── .agents/ │ ├── MODULE_GRAPH.md │ └── PLUGINS.md ├── .gitattributes ├── .github/ │ ├── CODE_OF_CONDUCT.md │ ├── CONTRIBUTING.md │ ├── DEVELOPMENT.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── 01-bug_report.yaml │ │ ├── 02-regression.yaml │ │ ├── 03-feature_request.yaml │ │ ├── 04-documentation.yaml │ │ ├── 05-everything-else.yaml │ │ └── config.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── copilot-instructions.md │ └── workflows/ │ ├── ci-bun.yml │ ├── ci-ts-latest.yml │ ├── ci-ts-next.yml │ ├── ci.yml │ ├── integration.yml │ ├── markdown-link-check.json │ ├── markdown-link-check.yml │ └── patches/ │ ├── .gitkeep │ ├── TypeScript.patch │ ├── argos.patch │ ├── create-typescript-app.patch │ └── npmx.dev.patch ├── .gitignore ├── .idea/ │ └── runConfigurations/ │ ├── Debug_Bun_test.xml │ └── Debug_Node_test.xml ├── .oxfmtrc.json ├── .oxlintrc.json ├── .prettierignore ├── .release-it.json ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ └── settings.json ├── AGENTS.md ├── knip.json ├── license ├── package.json ├── packages/ │ ├── create-config/ │ │ ├── README.md │ │ ├── index.js │ │ └── package.json │ ├── docs/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── astro.config.ts │ │ ├── mock/ │ │ │ └── contributors.json │ │ ├── package.json │ │ ├── public/ │ │ │ ├── fonts/ │ │ │ │ ├── SourceSansPro-Regular.otf │ │ │ │ └── fonts.conf │ │ │ ├── manifest.json │ │ │ ├── robots.txt │ │ │ └── screenshots/ │ │ │ ├── fix.webm │ │ │ └── watch-fix.webm │ │ ├── remark/ │ │ │ ├── fixInternalLinks.ts │ │ │ └── transformDirectives.ts │ │ ├── scripts/ │ │ │ ├── generate-plugin-docs.ts │ │ │ ├── get-monthly-sponsorships-github.ts │ │ │ ├── get-monthly-sponsorships-opencollective.ts │ │ │ └── get-monthly-sponsorships.ts │ │ ├── src/ │ │ │ ├── assets/ │ │ │ │ └── testimonials.json │ │ │ ├── components/ │ │ │ │ ├── Contributors.astro │ │ │ │ ├── EmojiBlastButton.astro │ │ │ │ ├── Footer.astro │ │ │ │ ├── Head.astro │ │ │ │ ├── Post.astro │ │ │ │ ├── Posts.astro │ │ │ │ ├── Projects.astro │ │ │ │ ├── Sponsors.astro │ │ │ │ └── SponsorsChart.astro │ │ │ ├── content/ │ │ │ │ └── docs/ │ │ │ │ ├── blog/ │ │ │ │ │ ├── brief-history.md │ │ │ │ │ ├── for-editors-and-agents.md │ │ │ │ │ ├── knip-v3.mdx │ │ │ │ │ ├── knip-v4.mdx │ │ │ │ │ ├── knip-v5.mdx │ │ │ │ │ ├── knip-v6.md │ │ │ │ │ ├── migration-to-v1.md │ │ │ │ │ ├── release-notes-v2.md │ │ │ │ │ ├── slim-down-to-speed-up.md │ │ │ │ │ ├── state-of-knip.md │ │ │ │ │ └── two-years.mdx │ │ │ │ ├── explanations/ │ │ │ │ │ ├── comparison-and-migration.md │ │ │ │ │ ├── entry-files.md │ │ │ │ │ ├── plugins.md │ │ │ │ │ └── why-use-knip.md │ │ │ │ ├── features/ │ │ │ │ │ ├── auto-fix.mdx │ │ │ │ │ ├── compilers.md │ │ │ │ │ ├── integrated-monorepos.md │ │ │ │ │ ├── monorepos-and-workspaces.md │ │ │ │ │ ├── production-mode.md │ │ │ │ │ ├── reporters.md │ │ │ │ │ ├── rules-and-filters.md │ │ │ │ │ ├── script-parser.md │ │ │ │ │ └── source-mapping.md │ │ │ │ ├── guides/ │ │ │ │ │ ├── configuring-project-files.md │ │ │ │ │ ├── contributing.md │ │ │ │ │ ├── handling-issues.mdx │ │ │ │ │ ├── issue-reproduction.md │ │ │ │ │ ├── namespace-imports.md │ │ │ │ │ ├── performance.md │ │ │ │ │ ├── troubleshooting.md │ │ │ │ │ ├── using-knip-in-ci.md │ │ │ │ │ └── working-with-commonjs.md │ │ │ │ ├── index.mdx │ │ │ │ ├── overview/ │ │ │ │ │ ├── configuration.md │ │ │ │ │ ├── features.md │ │ │ │ │ ├── getting-started.mdx │ │ │ │ │ └── screenshots-videos.md │ │ │ │ ├── playground.mdx │ │ │ │ ├── reference/ │ │ │ │ │ ├── cli.md │ │ │ │ │ ├── configuration-hints.md │ │ │ │ │ ├── configuration.md │ │ │ │ │ ├── dynamic-configuration.mdx │ │ │ │ │ ├── faq.md │ │ │ │ │ ├── integrations.md │ │ │ │ │ ├── issue-types.md │ │ │ │ │ ├── jsdoc-tsdoc-tags.md │ │ │ │ │ ├── known-issues.md │ │ │ │ │ ├── plugins/ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── plugins.md │ │ │ │ │ └── related-tooling.md │ │ │ │ ├── sponsors.mdx │ │ │ │ ├── typescript/ │ │ │ │ │ ├── unused-dependencies.md │ │ │ │ │ └── unused-exports.md │ │ │ │ └── writing-a-plugin/ │ │ │ │ ├── argument-parsing.md │ │ │ │ ├── index.md │ │ │ │ └── inputs.md │ │ │ ├── content.config.ts │ │ │ ├── fonts/ │ │ │ │ └── font-face.css │ │ │ ├── pages/ │ │ │ │ ├── og/ │ │ │ │ │ └── [...route].ts │ │ │ │ └── sitemap.txt.ts │ │ │ ├── styles/ │ │ │ │ ├── cards.css │ │ │ │ ├── content.css │ │ │ │ ├── custom.css │ │ │ │ ├── expressive-code.css │ │ │ │ ├── hero.css │ │ │ │ ├── links.css │ │ │ │ ├── sponsors.css │ │ │ │ ├── theme-dark.css │ │ │ │ └── theme-light.css │ │ │ └── util/ │ │ │ └── post.ts │ │ └── tsconfig.json │ ├── knip/ │ │ ├── .gitignore │ │ ├── .release-it.json │ │ ├── README.md │ │ ├── bin/ │ │ │ ├── knip-bun.js │ │ │ └── knip.js │ │ ├── fixtures/ │ │ │ ├── barrel-namespace-chain/ │ │ │ │ ├── consumer.ts │ │ │ │ ├── fn-consumer.ts │ │ │ │ ├── index.ts │ │ │ │ ├── lib.ts │ │ │ │ ├── opaque-consumer.ts │ │ │ │ ├── package.json │ │ │ │ ├── protocol.ts │ │ │ │ ├── server.ts │ │ │ │ └── utils.ts │ │ │ ├── binaries/ │ │ │ │ ├── dir/ │ │ │ │ │ └── index.js │ │ │ │ ├── main.ts │ │ │ │ ├── require.js │ │ │ │ └── script.js │ │ │ ├── catalog-named/ │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── pnpm-workspace.yaml │ │ │ ├── catalog-named-empty/ │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── pnpm-workspace.yaml │ │ │ ├── catalog-named-package-json/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── catalog-named-package-json-root/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── catalog-pnpm/ │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ └── app/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── pnpm-workspace.yaml │ │ │ ├── catalog-yarn/ │ │ │ │ ├── .yarnrc.yml │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── app/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── cli/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── cli-preprocessor/ │ │ │ │ ├── index.js │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── cli-reporter/ │ │ │ │ ├── index.js │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── commonjs/ │ │ │ │ ├── dir/ │ │ │ │ │ ├── exports.js │ │ │ │ │ ├── mod.js │ │ │ │ │ ├── mod1.js │ │ │ │ │ ├── mod2.js │ │ │ │ │ └── mod3.js │ │ │ │ ├── index.js │ │ │ │ ├── odd.js │ │ │ │ ├── package.json │ │ │ │ └── ts-ext.ts │ │ │ ├── commonjs-tsconfig/ │ │ │ │ ├── dir/ │ │ │ │ │ ├── exports.js │ │ │ │ │ ├── module1.ts │ │ │ │ │ ├── module2.ts │ │ │ │ │ ├── module3.js │ │ │ │ │ ├── script1.js │ │ │ │ │ ├── script2.js │ │ │ │ │ └── script3.js │ │ │ │ ├── index.js │ │ │ │ ├── main.ts │ │ │ │ ├── package.json │ │ │ │ ├── ts-ext.ts │ │ │ │ └── tsconfig.json │ │ │ ├── compact-reporter/ │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── compilers/ │ │ │ │ ├── Component.vue │ │ │ │ ├── component.tsx │ │ │ │ ├── enum.ts │ │ │ │ ├── grid.css │ │ │ │ ├── index.ts │ │ │ │ ├── knip.ts │ │ │ │ ├── module.mdx │ │ │ │ ├── package.json │ │ │ │ ├── readme.md │ │ │ │ ├── styles.css │ │ │ │ ├── tsconfig.json │ │ │ │ ├── unused.css │ │ │ │ └── unused.md │ │ │ ├── compilers-manual/ │ │ │ │ ├── component.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── knip.ts │ │ │ │ ├── module.mdx │ │ │ │ ├── package.json │ │ │ │ ├── styles.scss │ │ │ │ └── tsconfig.json │ │ │ ├── compilers-prisma/ │ │ │ │ ├── package.json │ │ │ │ └── prisma/ │ │ │ │ └── schema.prisma │ │ │ ├── compilers-scss/ │ │ │ │ ├── _grid.scss │ │ │ │ ├── _partial.scss │ │ │ │ ├── buttons.scss │ │ │ │ ├── cards.sass │ │ │ │ ├── components.scss │ │ │ │ ├── indented.sass │ │ │ │ ├── index.ts │ │ │ │ ├── legacy.scss │ │ │ │ ├── mixins.scss │ │ │ │ ├── package.json │ │ │ │ ├── styles.scss │ │ │ │ ├── theme.scss │ │ │ │ ├── unused.scss │ │ │ │ ├── utils.scss │ │ │ │ └── variables.scss │ │ │ ├── compilers-tailwind/ │ │ │ │ ├── components.css │ │ │ │ ├── index.ts │ │ │ │ ├── local-js-plugin.js │ │ │ │ ├── local-ts-plugin.ts │ │ │ │ ├── package.json │ │ │ │ ├── styles.css │ │ │ │ └── unused.css │ │ │ ├── config-js-async/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.config.js │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-js-flat/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.js │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-json/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.json │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-mjs-async/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.mjs │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-mjs-flat/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.mjs │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-package-json/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── config-ts-async/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.ts │ │ │ │ ├── my-namespace.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── config-ts-flat/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.config.ts │ │ │ │ ├── my-namespace.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── config-ts-function/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.ts │ │ │ │ ├── my-namespace.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── config-yaml/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.yaml │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── configuration-hints/ │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ └── entry.js │ │ │ ├── configuration-hints-plugin/ │ │ │ │ ├── create-typescript-app.config.js │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── svgo.config.mjs │ │ │ ├── configuration-hints-plugin-override/ │ │ │ │ ├── create-typescript-app.config.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── svgo.config.js │ │ │ │ └── yarn.config.cjs │ │ │ ├── configuration-hints2/ │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ └── entry.js │ │ │ ├── cross-workspace-inputs/ │ │ │ │ ├── .github/ │ │ │ │ │ └── workflows/ │ │ │ │ │ └── test.yml │ │ │ │ ├── components/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── vitest.components.config.ts │ │ │ │ ├── e2e/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── playwright.e2e.config.ts │ │ │ │ │ └── tests/ │ │ │ │ │ └── feature.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── custom-paths-workspaces/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── fn.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── my-module.ts │ │ │ │ ├── package.json │ │ │ │ └── ws/ │ │ │ │ ├── index.ts │ │ │ │ ├── lib/ │ │ │ │ │ └── main.ts │ │ │ │ ├── package.json │ │ │ │ └── util/ │ │ │ │ └── lang.ts │ │ │ ├── definitely-typed/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── dependencies/ │ │ │ │ ├── entry.ts │ │ │ │ ├── knip.json │ │ │ │ ├── my-module.ts │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── unused-module.ts │ │ │ ├── dependencies-types/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── dts/ │ │ │ │ ├── assets.d.ts │ │ │ │ ├── block.html │ │ │ │ ├── index.ts │ │ │ │ ├── module-augmentation.ts │ │ │ │ ├── normal.ts │ │ │ │ ├── package.json │ │ │ │ ├── svg.d.ts │ │ │ │ ├── tsconfig.json │ │ │ │ └── types.d.ts │ │ │ ├── dts-baseurl-implicit-relative/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── Button.d.ts │ │ │ │ │ │ └── Button.jsx │ │ │ │ │ ├── dir/ │ │ │ │ │ │ └── subdir/ │ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── index.ts │ │ │ │ │ └── utils/ │ │ │ │ │ ├── fn.d.ts │ │ │ │ │ ├── fn.js │ │ │ │ │ ├── obj.cjs │ │ │ │ │ ├── obj.d.cts │ │ │ │ │ ├── str.d.mts │ │ │ │ │ └── str.mjs │ │ │ │ └── tsconfig.json │ │ │ ├── dts-compiled/ │ │ │ │ ├── knip.ts │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── App.tsx │ │ │ │ │ ├── ExampleQuery.graphql │ │ │ │ │ ├── ExampleQuery.graphql.d.ts │ │ │ │ │ ├── UnusedQuery.graphql │ │ │ │ │ ├── UnusedQuery.graphql.d.ts │ │ │ │ │ ├── main.tsx │ │ │ │ │ └── types.ts │ │ │ │ └── tsconfig.json │ │ │ ├── duplicate-dependencies/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── duplicate-exports-alias/ │ │ │ │ ├── helpers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── reexported.ts │ │ │ │ └── specifier-default.ts │ │ │ ├── empty-main/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── entry-exports-enum-members/ │ │ │ │ ├── fruit.ts │ │ │ │ ├── index.ts │ │ │ │ ├── main.ts │ │ │ │ ├── package.json │ │ │ │ └── tree.ts │ │ │ ├── entry-exports-namespace/ │ │ │ │ ├── index.ts │ │ │ │ ├── main.ts │ │ │ │ ├── mid.ts │ │ │ │ ├── ns.ts │ │ │ │ └── package.json │ │ │ ├── entry-files/ │ │ │ │ ├── cli.js │ │ │ │ ├── export-index.js │ │ │ │ ├── local-default.js │ │ │ │ ├── local-import.js │ │ │ │ ├── local-node.js │ │ │ │ ├── local-require.js │ │ │ │ ├── main.js │ │ │ │ └── package.json │ │ │ ├── entry-js/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── my-module.ts │ │ │ │ ├── my-namespace.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── enum-members/ │ │ │ │ ├── index.ts │ │ │ │ ├── members.ts │ │ │ │ └── package.json │ │ │ ├── enum-members-enumerated/ │ │ │ │ ├── directions.ts │ │ │ │ ├── fruits.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── export-default-type/ │ │ │ │ ├── class.js │ │ │ │ ├── const.js │ │ │ │ ├── function.js │ │ │ │ ├── index.js │ │ │ │ ├── let.js │ │ │ │ ├── package.json │ │ │ │ └── var.js │ │ │ ├── export-spread/ │ │ │ │ ├── array.ts │ │ │ │ ├── index.ts │ │ │ │ ├── object.ts │ │ │ │ └── package.json │ │ │ ├── exports/ │ │ │ │ ├── default-arrow-function.ts │ │ │ │ ├── default-class.ts │ │ │ │ ├── default-function.ts │ │ │ │ ├── default-generator-function.ts │ │ │ │ ├── default-named-class.ts │ │ │ │ ├── default-named-function.ts │ │ │ │ ├── default-named-generator-function.ts │ │ │ │ ├── default.ts │ │ │ │ ├── dynamic-import.ts │ │ │ │ ├── export-is.ts │ │ │ │ ├── index.ts │ │ │ │ ├── my-mix.ts │ │ │ │ ├── my-module.ts │ │ │ │ ├── my-namespace.ts │ │ │ │ ├── named-exports.ts │ │ │ │ ├── odd.ts │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── types.ts │ │ │ ├── exports-default-interface/ │ │ │ │ ├── enum.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── package.json │ │ │ │ └── type.ts │ │ │ ├── exports-special-characters/ │ │ │ │ ├── exports.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── exports-value-refs/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── refs.ts │ │ │ ├── exports-value-refs-default/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── refs.ts │ │ │ ├── extensions-css-ts/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── styles1.css.ts │ │ │ │ ├── styles1a.css.ts │ │ │ │ ├── styles2.css.ts │ │ │ │ ├── styles2a.css.ts │ │ │ │ ├── styles3.css.ts │ │ │ │ └── styles3a.css.ts │ │ │ ├── fix/ │ │ │ │ ├── .prettierrc │ │ │ │ ├── access.js │ │ │ │ ├── default-x.mjs │ │ │ │ ├── default.mjs │ │ │ │ ├── exports.js │ │ │ │ ├── ignored.ts │ │ │ │ ├── index.mjs │ │ │ │ ├── knip.ts │ │ │ │ ├── mod.ts │ │ │ │ ├── package.json │ │ │ │ ├── reexported.ts │ │ │ │ └── reexports.mjs │ │ │ ├── fix-members/ │ │ │ │ ├── class.ts │ │ │ │ ├── enums.ts │ │ │ │ ├── index.js │ │ │ │ ├── namespaces.ts │ │ │ │ └── package.json │ │ │ ├── fix-workspaces/ │ │ │ │ ├── exports.ts │ │ │ │ ├── ignored.ts │ │ │ │ ├── index.js │ │ │ │ ├── knip.ts │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── ignored/ │ │ │ │ │ ├── exports.ts │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ └── lib/ │ │ │ │ ├── exports.ts │ │ │ │ ├── ignored.ts │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── git-branch-file/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── gitignore/ │ │ │ │ ├── .gitignore │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── a/ │ │ │ │ ├── .gitignore │ │ │ │ ├── index.ts │ │ │ │ ├── libs/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ └── util/ │ │ │ │ │ └── type/ │ │ │ │ │ └── .gitignore │ │ │ │ └── package.json │ │ │ ├── glob/ │ │ │ │ ├── .gitignore │ │ │ │ └── a/ │ │ │ │ ├── .gitignore │ │ │ │ └── b/ │ │ │ │ ├── .gitignore │ │ │ │ └── c/ │ │ │ │ └── .gitignore │ │ │ ├── glob-worktree/ │ │ │ │ ├── .gitignore │ │ │ │ ├── mock-git-dir/ │ │ │ │ │ └── info/ │ │ │ │ │ └── exclude │ │ │ │ └── root/ │ │ │ │ ├── .gitignore │ │ │ │ ├── dot-git │ │ │ │ └── subdir/ │ │ │ │ └── .gitignore │ │ │ ├── ignore-dependencies-binaries/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.ts │ │ │ │ └── package.json │ │ │ ├── ignore-dependencies-binaries-json/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── ignore-dependencies-eslint/ │ │ │ │ ├── .eslintrc.js │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── ignore-exports-used-in-file/ │ │ │ │ ├── computed-access.ts │ │ │ │ ├── control-flow.ts │ │ │ │ ├── expressions.ts │ │ │ │ ├── imported.ts │ │ │ │ ├── index.ts │ │ │ │ ├── jsx.tsx │ │ │ │ ├── knip.json │ │ │ │ ├── loops.ts │ │ │ │ ├── more.ts │ │ │ │ ├── package.json │ │ │ │ ├── tagged-template.ts │ │ │ │ ├── tsconfig.json │ │ │ │ └── type-assertions.ts │ │ │ ├── ignore-exports-used-in-file-alias-exclude/ │ │ │ │ ├── exports.ts │ │ │ │ ├── index.ts │ │ │ │ ├── more.ts │ │ │ │ └── package.json │ │ │ ├── ignore-exports-used-in-file-false/ │ │ │ │ ├── imported.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── ignore-exports-used-in-file-id-chars/ │ │ │ │ ├── imported.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── ignore-exports-used-in-file-id-underscores/ │ │ │ │ ├── imported.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── namespace.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── ignore-exports-used-in-file-re-export/ │ │ │ │ ├── component.ts │ │ │ │ ├── index.ts │ │ │ │ ├── interface.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── ignore-exports-used-in-file-shorthand/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── antecedents.js │ │ │ │ ├── fn.js │ │ │ │ ├── index.js │ │ │ │ └── slice.js │ │ │ ├── ignore-exports-used-in-file-some/ │ │ │ │ ├── imported.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── ignore-exports-used-in-file-typeof-class/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── api.ts │ │ │ │ └── index.ts │ │ │ ├── ignore-files/ │ │ │ │ ├── apples/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── rooted.js │ │ │ │ │ ├── unused.js │ │ │ │ │ └── used.js │ │ │ │ ├── bananas/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── rooted.js │ │ │ │ │ ├── unused.js │ │ │ │ │ └── used.js │ │ │ │ ├── index.js │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── rooted.js │ │ │ │ ├── unused.js │ │ │ │ └── used.js │ │ │ ├── ignore-issues/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── generated/ │ │ │ │ │ └── types.ts │ │ │ │ ├── index.ts │ │ │ │ ├── model.generated.ts │ │ │ │ └── regular.ts │ │ │ ├── ignore-members/ │ │ │ │ ├── MyClass.ts │ │ │ │ ├── enums.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── ignore-negated/ │ │ │ │ ├── index.js │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ └── modules/ │ │ │ │ ├── A/ │ │ │ │ │ └── unusedFileA.js │ │ │ │ └── B/ │ │ │ │ └── unusedFileB.js │ │ │ ├── ignore-patterns/ │ │ │ │ ├── .gitignore │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── scripts/ │ │ │ │ └── build.ts │ │ │ ├── ignore-patterns-monorepo/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── lib/ │ │ │ │ ├── index.ts │ │ │ │ ├── output/ │ │ │ │ │ └── generated.ts │ │ │ │ └── package.json │ │ │ ├── ignore-unresolved/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.ts │ │ │ │ └── package.json │ │ │ ├── ignore-unresolved2/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── client/ │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ └── index.ts │ │ │ ├── import-equals/ │ │ │ │ ├── index.ts │ │ │ │ ├── local.ts │ │ │ │ ├── my-module.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── import-errors/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── import-meta-glob/ │ │ │ │ ├── animals/ │ │ │ │ │ ├── cat.ts │ │ │ │ │ ├── dog.ts │ │ │ │ │ └── horse.ts │ │ │ │ ├── flowers/ │ │ │ │ │ ├── rose.astro │ │ │ │ │ └── tulip.astro │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── shapes/ │ │ │ │ ├── circle.vue │ │ │ │ └── square.vue │ │ │ ├── import-named-default-id/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── utils.ts │ │ │ ├── import-star-iteration/ │ │ │ │ ├── fruit.ts │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── vegetables.ts │ │ │ ├── imports/ │ │ │ │ ├── aliased-binding.ts │ │ │ │ ├── await-import-call.ts │ │ │ │ ├── await-import.ts │ │ │ │ ├── catch.ts │ │ │ │ ├── default-and-named-binding.ts │ │ │ │ ├── default-identifier.ts │ │ │ │ ├── default-prop-access.ts │ │ │ │ ├── dir/ │ │ │ │ │ ├── import-b.ts │ │ │ │ │ ├── import-f.ts │ │ │ │ │ └── mod.ts │ │ │ │ ├── empty-named-bindings.ts │ │ │ │ ├── import-a.ts │ │ │ │ ├── import-c.ts │ │ │ │ ├── import-d.ts │ │ │ │ ├── import-e.ts │ │ │ │ ├── import-g.ts │ │ │ │ ├── import-meta-resolve.js │ │ │ │ ├── index.ts │ │ │ │ ├── named-object-binding.ts │ │ │ │ ├── no-substitution-tpl-literal.ts │ │ │ │ ├── object-bindings.ts │ │ │ │ ├── package.json │ │ │ │ ├── promise-like.ts │ │ │ │ ├── prop-access.ts │ │ │ │ ├── side-effects-call.ts │ │ │ │ ├── side-effects.ts │ │ │ │ ├── string-literal.ts │ │ │ │ ├── top-level-await-import.ts │ │ │ │ ├── top-level-side-effects-call.ts │ │ │ │ └── tsconfig.json │ │ │ ├── imports-destructure-spread/ │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── trees.js │ │ │ ├── imports-dynamic-access/ │ │ │ │ ├── fruits.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── imports-namespace/ │ │ │ │ ├── index.ts │ │ │ │ ├── namespace.ts │ │ │ │ ├── namespace10.ts │ │ │ │ ├── namespace2.ts │ │ │ │ ├── namespace3-opaque.ts │ │ │ │ ├── namespace3.ts │ │ │ │ ├── namespace4.ts │ │ │ │ ├── namespace5-opaque.ts │ │ │ │ ├── namespace5.ts │ │ │ │ ├── namespace6-opaque.ts │ │ │ │ ├── namespace6.ts │ │ │ │ ├── namespace7.ts │ │ │ │ ├── namespace8.ts │ │ │ │ ├── namespace9.ts │ │ │ │ ├── package.json │ │ │ │ └── re-exported-module.ts │ │ │ ├── imports-namespace-jsx/ │ │ │ │ ├── components.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── package.json │ │ │ ├── imports-namespace-with-nsexports/ │ │ │ │ ├── index.ts │ │ │ │ ├── namespace.ts │ │ │ │ ├── namespace2.ts │ │ │ │ ├── namespace3.ts │ │ │ │ ├── namespace4.ts │ │ │ │ ├── namespace5.ts │ │ │ │ ├── namespace6.ts │ │ │ │ ├── package.json │ │ │ │ └── re-exported-module.ts │ │ │ ├── imports-opaque/ │ │ │ │ ├── arrow.ts │ │ │ │ ├── assignment.ts │ │ │ │ ├── awaited-arrow.ts │ │ │ │ ├── awaited-assignment.ts │ │ │ │ ├── awaited-fn-arg.ts │ │ │ │ ├── awaited-return.ts │ │ │ │ ├── direct.ts │ │ │ │ ├── fn-arg.ts │ │ │ │ ├── index.ts │ │ │ │ ├── obj-spread.ts │ │ │ │ ├── package.json │ │ │ │ ├── return.ts │ │ │ │ ├── tsconfig.json │ │ │ │ └── variable.ts │ │ │ ├── imports-prop-access-call/ │ │ │ │ ├── exists.js │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── imports-self/ │ │ │ │ ├── exports.js │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── imports-typeof/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── include-entry-exports/ │ │ │ │ ├── cli.js │ │ │ │ ├── index.ts │ │ │ │ ├── main.ts │ │ │ │ ├── mod.ts │ │ │ │ └── package.json │ │ │ ├── include-entry-exports-scripts/ │ │ │ │ ├── knip.json │ │ │ │ ├── next.config.js │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── pages/ │ │ │ │ │ └── index.js │ │ │ │ ├── script1.ts │ │ │ │ ├── script2.ts │ │ │ │ └── script3.ts │ │ │ ├── include-entry-reexports/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── app/ │ │ │ │ │ ├── index.mjs │ │ │ │ │ └── package.json │ │ │ │ └── shared/ │ │ │ │ ├── index.mjs │ │ │ │ ├── module-a.mjs │ │ │ │ ├── module-b.mjs │ │ │ │ └── package.json │ │ │ ├── include-libs/ │ │ │ │ ├── components.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── loadable.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── js-only/ │ │ │ │ ├── dangling.js │ │ │ │ ├── index.js │ │ │ │ ├── my-namespace.js │ │ │ │ └── package.json │ │ │ ├── jsdoc/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── jsdoc-exports/ │ │ │ │ ├── index.ts │ │ │ │ ├── module.test.js │ │ │ │ ├── module.ts │ │ │ │ └── package.json │ │ │ ├── jsx/ │ │ │ │ ├── App.tsx │ │ │ │ ├── Component.tsx │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── load-cjs/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── load-esm/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── load-esm-ts/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── load-json5/ │ │ │ │ └── config.json5 │ │ │ ├── module-block/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── types.ts │ │ │ ├── module-register/ │ │ │ │ ├── ignored-loader.js │ │ │ │ ├── index.ts │ │ │ │ ├── loader.js │ │ │ │ └── package.json │ │ │ ├── module-resolution-baseurl-implicit-relative/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ └── main.ts │ │ │ │ │ ├── hello/ │ │ │ │ │ │ └── world.ts │ │ │ │ │ └── index.ts │ │ │ │ └── tsconfig.json │ │ │ ├── module-resolution-non-std/ │ │ │ │ ├── .gitignore │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── globals.css │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── styles/ │ │ │ │ │ │ ├── aliased.css │ │ │ │ │ │ └── base.css │ │ │ │ │ └── unused.ts │ │ │ │ └── tsconfig.json │ │ │ ├── module-resolution-non-std-absolute/ │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ ├── x-other/ │ │ │ │ │ ├── absolute.css │ │ │ │ │ └── package.json │ │ │ │ └── x-self/ │ │ │ │ ├── absolute.css │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── module-resolution-non-std-implicit/ │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── dir/ │ │ │ │ │ └── main.ts │ │ │ │ ├── global.css │ │ │ │ ├── index.ts │ │ │ │ └── styles/ │ │ │ │ └── base.css │ │ │ ├── module-resolution-tsconfig-paths/ │ │ │ │ ├── aliased-dir/ │ │ │ │ │ └── a.ts │ │ │ │ ├── components/ │ │ │ │ │ ├── IndexComponent/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── MyComponent.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── internal-package/ │ │ │ │ │ └── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── unprefixed/ │ │ │ │ └── module.ts │ │ │ ├── negated-production-paths/ │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── npm-scripts/ │ │ │ │ ├── .gitignore │ │ │ │ ├── entry.ts │ │ │ │ ├── ignore.js │ │ │ │ ├── package.json │ │ │ │ └── script.js │ │ │ ├── ns-spread-reexport/ │ │ │ │ ├── aliased-import.ts │ │ │ │ ├── animals.ts │ │ │ │ ├── colors.ts │ │ │ │ ├── consumer.ts │ │ │ │ ├── destructured.ts │ │ │ │ ├── fruits.ts │ │ │ │ ├── hello.resolver.ts │ │ │ │ ├── index.ts │ │ │ │ ├── member-access.ts │ │ │ │ ├── mixed-usage.ts │ │ │ │ ├── ns-alias-reexport.ts │ │ │ │ ├── package.json │ │ │ │ ├── resolvers.barrel.ts │ │ │ │ ├── resolvers.ts │ │ │ │ └── utils.ts │ │ │ ├── package-entry-points/ │ │ │ │ ├── .gitignore │ │ │ │ ├── feature/ │ │ │ │ │ ├── internal/ │ │ │ │ │ │ ├── no-entry.js │ │ │ │ │ │ └── system/ │ │ │ │ │ │ ├── unused.ts │ │ │ │ │ │ └── used.ts │ │ │ │ │ └── my-feature.js │ │ │ │ ├── lib/ │ │ │ │ │ ├── deep/ │ │ │ │ │ │ ├── er/ │ │ │ │ │ │ │ └── file.js │ │ │ │ │ │ └── main.js │ │ │ │ │ └── index.js │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── app.ts │ │ │ │ │ ├── public/ │ │ │ │ │ │ └── lib/ │ │ │ │ │ │ └── rary/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── lost.js │ │ │ │ │ └── runtime/ │ │ │ │ │ ├── deep/ │ │ │ │ │ │ └── deno.ts │ │ │ │ │ └── node.ts │ │ │ │ └── tsconfig.json │ │ │ ├── path-aliases/ │ │ │ │ ├── abc/ │ │ │ │ │ └── main.js │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── data.ext │ │ │ │ │ ├── fn.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── my-module.ts │ │ │ │ └── package.json │ │ │ ├── path-aliases2/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── ts/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ └── shared/ │ │ │ │ │ └── file.ts │ │ │ │ ├── tsconfig.json │ │ │ │ ├── vite/ │ │ │ │ │ ├── component/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ ├── dir/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ └── file.ts │ │ │ │ ├── vite.config.ts │ │ │ │ ├── vitest/ │ │ │ │ │ ├── component/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ ├── dir/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ └── file.ts │ │ │ │ ├── webpack/ │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ ├── file.ts │ │ │ │ │ ├── match.ts │ │ │ │ │ ├── shared/ │ │ │ │ │ │ └── file.ts │ │ │ │ │ └── wild/ │ │ │ │ │ └── file.ts │ │ │ │ └── webpack.config.ts │ │ │ ├── pathless/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ └── module-a.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── same.ts │ │ │ │ └── tsconfig.json │ │ │ ├── peer-dependencies/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-circular/ │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-optional/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-optional-host/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-optional-ignored/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-optional-strict/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── peer-dependencies-optional-strict-unreferenced/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── plugin-config/ │ │ │ │ ├── index.ts │ │ │ │ ├── index.vitest.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── vitest.config.ts │ │ │ ├── plugin-disable/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── vite.config.ts │ │ │ │ └── ws/ │ │ │ │ ├── package.json │ │ │ │ └── playwright.config.ts │ │ │ ├── plugin-negated-entry-globs/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ └── pages/ │ │ │ │ ├── _stories/ │ │ │ │ │ └── index.stories.ts │ │ │ │ ├── _util.ts │ │ │ │ ├── about/ │ │ │ │ │ └── index.astro │ │ │ │ ├── blog/ │ │ │ │ │ ├── _util/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── _util.ts │ │ │ │ │ └── index.astro │ │ │ │ └── index.astro │ │ │ ├── plugin-overlap/ │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── typedoc.json │ │ │ ├── plugins/ │ │ │ │ ├── _template/ │ │ │ │ │ └── package.json │ │ │ │ ├── angular/ │ │ │ │ │ ├── angular.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app/ │ │ │ │ │ │ │ └── app.component.spec.ts │ │ │ │ │ │ ├── main.ts │ │ │ │ │ │ ├── polyfill.js │ │ │ │ │ │ └── script.js │ │ │ │ │ ├── tsconfig.app.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── tsconfig.spec.json │ │ │ │ ├── angular2/ │ │ │ │ │ ├── angular.json │ │ │ │ │ ├── another-karma.conf.js │ │ │ │ │ ├── karma.conf.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── browser.ts │ │ │ │ │ │ ├── environments/ │ │ │ │ │ │ │ ├── environment.development.ts │ │ │ │ │ │ │ └── environment.ts │ │ │ │ │ │ ├── main.server.ts │ │ │ │ │ │ └── server.ts │ │ │ │ │ └── tsconfig.app.json │ │ │ │ ├── angular3/ │ │ │ │ │ ├── angular.json │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── main-for-non-prod.ts │ │ │ │ │ ├── main-for-testing.ts │ │ │ │ │ ├── main.server-for-non-prod.ts │ │ │ │ │ ├── main.server.ts │ │ │ │ │ ├── main.ts │ │ │ │ │ ├── polyfill-for-non-prod.js │ │ │ │ │ ├── polyfill.js │ │ │ │ │ ├── script-for-non-prod.js │ │ │ │ │ ├── script.js │ │ │ │ │ └── server.ts │ │ │ │ ├── astro/ │ │ │ │ │ ├── .astro/ │ │ │ │ │ │ └── types.d.ts │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ ├── BaseHead.astro │ │ │ │ │ │ │ ├── Footer.astro │ │ │ │ │ │ │ ├── FormattedDate.astro │ │ │ │ │ │ │ ├── Header.astro │ │ │ │ │ │ │ └── HeaderLink.astro │ │ │ │ │ │ ├── consts.ts │ │ │ │ │ │ ├── content/ │ │ │ │ │ │ │ ├── blog/ │ │ │ │ │ │ │ │ ├── first-post.md │ │ │ │ │ │ │ │ └── using-mdx.mdx │ │ │ │ │ │ │ └── config.ts │ │ │ │ │ │ ├── env.d.ts │ │ │ │ │ │ ├── layouts/ │ │ │ │ │ │ │ ├── BlogPost.astro │ │ │ │ │ │ │ └── Layout.astro │ │ │ │ │ │ ├── pages/ │ │ │ │ │ │ │ ├── _top-level-dir-unused/ │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ ├── _top-level-file-unused.ts │ │ │ │ │ │ │ ├── about/ │ │ │ │ │ │ │ │ └── mdx-with-layout.mdx │ │ │ │ │ │ │ ├── about.astro │ │ │ │ │ │ │ ├── blog/ │ │ │ │ │ │ │ │ ├── [...slug].astro │ │ │ │ │ │ │ │ ├── _nested-unused-file.ts │ │ │ │ │ │ │ │ ├── _util/ │ │ │ │ │ │ │ │ │ ├── nested/ │ │ │ │ │ │ │ │ │ │ └── deeply-nested-unused-file.ts │ │ │ │ │ │ │ │ │ └── unused-component.astro │ │ │ │ │ │ │ │ └── index.astro │ │ │ │ │ │ │ ├── index.astro │ │ │ │ │ │ │ └── rss.xml.js │ │ │ │ │ │ └── styles/ │ │ │ │ │ │ └── global.css │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── astro-db/ │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── db/ │ │ │ │ │ │ ├── config.ts │ │ │ │ │ │ └── seed.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── pages/ │ │ │ │ │ │ └── index.astro │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── astro-og-canvas/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ ├── astro-sharp-image-service/ │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── pages/ │ │ │ │ │ └── index.astro │ │ │ │ ├── ava/ │ │ │ │ │ ├── ava.config.mjs │ │ │ │ │ └── package.json │ │ │ │ ├── ava2/ │ │ │ │ │ ├── __tests__/ │ │ │ │ │ │ ├── __helpers__/ │ │ │ │ │ │ │ └── index.cjs │ │ │ │ │ │ └── mod.cjs │ │ │ │ │ ├── ava.config.mjs │ │ │ │ │ ├── index.cjs │ │ │ │ │ ├── mod.cjs │ │ │ │ │ ├── package.json │ │ │ │ │ └── test.js │ │ │ │ ├── ava3/ │ │ │ │ │ ├── ava.config.mjs │ │ │ │ │ ├── index.cjs │ │ │ │ │ ├── mod.cjs │ │ │ │ │ ├── mod.test.js │ │ │ │ │ ├── mod.test.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── mod.test.js │ │ │ │ │ │ └── mod.test.ts │ │ │ │ │ ├── test.js │ │ │ │ │ └── test.ts │ │ │ │ ├── babel/ │ │ │ │ │ ├── .babelrc │ │ │ │ │ ├── .babelrc.js │ │ │ │ │ ├── babel.config.cts │ │ │ │ │ ├── babel.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── biome/ │ │ │ │ │ ├── biome.json │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── shared/ │ │ │ │ │ └── base.json │ │ │ │ ├── biome-workspace/ │ │ │ │ │ ├── biome.jsonc │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── packages/ │ │ │ │ │ └── stub/ │ │ │ │ │ ├── biome.json │ │ │ │ │ └── package.json │ │ │ │ ├── bumpp/ │ │ │ │ │ ├── bump.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── bun/ │ │ │ │ │ ├── index.spec.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── bun2/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── index.check.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── bun3/ │ │ │ │ │ ├── bunfig.toml │ │ │ │ │ ├── index.spec.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── preload.ts │ │ │ │ │ ├── setup-env.ts │ │ │ │ │ └── setup.ts │ │ │ │ ├── bun4/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── test/ │ │ │ │ │ └── index.test.ts │ │ │ │ ├── capacitor/ │ │ │ │ │ ├── android/ │ │ │ │ │ │ └── capacitor.settings.gradle │ │ │ │ │ ├── capacitor.config.json │ │ │ │ │ ├── capacitor.config.ts │ │ │ │ │ ├── ios/ │ │ │ │ │ │ └── App/ │ │ │ │ │ │ └── Podfile │ │ │ │ │ └── package.json │ │ │ │ ├── changelogen/ │ │ │ │ │ ├── changelog.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── changelogithub/ │ │ │ │ │ ├── changelogithub.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── changesets/ │ │ │ │ │ ├── .changeset/ │ │ │ │ │ │ └── config.json │ │ │ │ │ └── package.json │ │ │ │ ├── commitizen/ │ │ │ │ │ ├── .czrc │ │ │ │ │ └── package.json │ │ │ │ ├── commitlint/ │ │ │ │ │ ├── .commitlintrc.json │ │ │ │ │ ├── commitlint.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── convex/ │ │ │ │ │ ├── convex/ │ │ │ │ │ │ ├── _generated/ │ │ │ │ │ │ │ └── dataModel.d.ts │ │ │ │ │ │ ├── auth.config.ts │ │ │ │ │ │ └── schema.ts │ │ │ │ │ └── package.json │ │ │ │ ├── create-typescript-app/ │ │ │ │ │ ├── create-typescript-app.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── cspell/ │ │ │ │ │ ├── .cspell.json │ │ │ │ │ └── package.json │ │ │ │ ├── cucumber/ │ │ │ │ │ ├── cucumber.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── steps/ │ │ │ │ │ └── step.ts │ │ │ │ ├── cypress/ │ │ │ │ │ ├── cypress/ │ │ │ │ │ │ └── support/ │ │ │ │ │ │ ├── commands.ts │ │ │ │ │ │ └── e2e.ts │ │ │ │ │ ├── cypress.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── cypress-multi-reporter/ │ │ │ │ │ ├── cypress/ │ │ │ │ │ │ └── support/ │ │ │ │ │ │ ├── commands.ts │ │ │ │ │ │ └── e2e.ts │ │ │ │ │ ├── cypress.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── reporter-config.json │ │ │ │ ├── cypress2/ │ │ │ │ │ ├── cypress/ │ │ │ │ │ │ └── support/ │ │ │ │ │ │ ├── commands.ts │ │ │ │ │ │ ├── component.ts │ │ │ │ │ │ └── e2e.ts │ │ │ │ │ ├── cypress.config.js │ │ │ │ │ ├── e2e/ │ │ │ │ │ │ └── mod.e2e.js │ │ │ │ │ ├── mod.component.js │ │ │ │ │ └── package.json │ │ │ │ ├── danger/ │ │ │ │ │ ├── dangerfile.js │ │ │ │ │ └── package.json │ │ │ │ ├── dependency-cruiser/ │ │ │ │ │ ├── .dependency-cruiser.js │ │ │ │ │ ├── baseline.config.js │ │ │ │ │ ├── custom-depcruise-config.js │ │ │ │ │ ├── dependency-cruise.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── docusaurus/ │ │ │ │ │ ├── blog/ │ │ │ │ │ │ └── 2021-08-01-mdx-blog-post.mdx │ │ │ │ │ ├── docs/ │ │ │ │ │ │ └── tutorial-basics/ │ │ │ │ │ │ └── markdown-features.mdx │ │ │ │ │ ├── docusaurus.config.js │ │ │ │ │ ├── docusaurus.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── sidebars.js │ │ │ │ │ ├── sidebars.ts │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ └── HomepageFeatures/ │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── pages/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── static/ │ │ │ │ │ ├── css/ │ │ │ │ │ │ ├── custom.css │ │ │ │ │ │ └── theme.css │ │ │ │ │ └── js/ │ │ │ │ │ ├── analytics.js │ │ │ │ │ └── custom.js │ │ │ │ ├── drizzle/ │ │ │ │ │ ├── drizzle.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── schema/ │ │ │ │ │ │ └── users.ts │ │ │ │ │ └── schema.ts │ │ │ │ ├── eleventy/ │ │ │ │ │ ├── _data/ │ │ │ │ │ │ └── global.cjs │ │ │ │ │ ├── _includes/ │ │ │ │ │ │ └── footer.njk │ │ │ │ │ ├── eleventy.config.cjs │ │ │ │ │ ├── package.json │ │ │ │ │ └── pages/ │ │ │ │ │ └── index.njk │ │ │ │ ├── eleventy2/ │ │ │ │ │ ├── _data/ │ │ │ │ │ │ └── global.cjs │ │ │ │ │ ├── _includes/ │ │ │ │ │ │ └── footer.njk │ │ │ │ │ ├── eleventy.config.cjs │ │ │ │ │ ├── package.json │ │ │ │ │ └── pages/ │ │ │ │ │ └── index.njk │ │ │ │ ├── eleventy3/ │ │ │ │ │ ├── .eleventy.js │ │ │ │ │ ├── _includes/ │ │ │ │ │ │ └── footer.njk │ │ │ │ │ ├── package.json │ │ │ │ │ ├── pages/ │ │ │ │ │ │ └── index.njk │ │ │ │ │ └── src/ │ │ │ │ │ ├── _includes/ │ │ │ │ │ │ └── abc.js │ │ │ │ │ ├── _plugins/ │ │ │ │ │ │ └── syntax-highlighter.js │ │ │ │ │ ├── assets/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── static/ │ │ │ │ │ └── index.js │ │ │ │ ├── eleventy4/ │ │ │ │ │ ├── .eleventy.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── _siteData/ │ │ │ │ │ │ └── global.cjs │ │ │ │ │ └── assets/ │ │ │ │ │ └── index.js │ │ │ │ ├── eslint/ │ │ │ │ │ ├── .eslintrc.cjs │ │ │ │ │ ├── .eslintrc.js │ │ │ │ │ ├── .eslintrc.json │ │ │ │ │ ├── .eslintrc.yml │ │ │ │ │ ├── base.eslint.json │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── eslint2/ │ │ │ │ │ ├── eslint.config.ts │ │ │ │ │ ├── knip.json │ │ │ │ │ └── package.json │ │ │ │ ├── eslint3/ │ │ │ │ │ ├── eslint.config.js │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── eslint4/ │ │ │ │ │ ├── eslint.config.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── eslint5/ │ │ │ │ │ ├── eslint.config.ts │ │ │ │ │ ├── knip.json │ │ │ │ │ └── package.json │ │ │ │ ├── expo/ │ │ │ │ │ ├── app.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── app/ │ │ │ │ │ └── index.ts │ │ │ │ ├── expo2/ │ │ │ │ │ ├── app.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── routes/ │ │ │ │ │ └── index.js │ │ │ │ ├── expo3/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── _layout.ts │ │ │ │ │ ├── app.json │ │ │ │ │ └── package.json │ │ │ │ ├── expressive-code/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── next.config.mjs │ │ │ │ │ └── package.json │ │ │ │ ├── expressive-code2/ │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── ec.config.mjs │ │ │ │ │ └── package.json │ │ │ │ ├── expressive-code3/ │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── ec.config.mjs │ │ │ │ │ └── package.json │ │ │ │ ├── gatsby/ │ │ │ │ │ ├── gatsby-config.js │ │ │ │ │ ├── gatsby-node.js │ │ │ │ │ └── package.json │ │ │ │ ├── github-action/ │ │ │ │ │ ├── action.yml │ │ │ │ │ ├── dist/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── main.ts │ │ │ │ ├── github-actions/ │ │ │ │ │ ├── .github/ │ │ │ │ │ │ ├── actions/ │ │ │ │ │ │ │ ├── composite/ │ │ │ │ │ │ │ │ └── action.yml │ │ │ │ │ │ │ ├── node-a/ │ │ │ │ │ │ │ │ ├── action.yml │ │ │ │ │ │ │ │ ├── dist/ │ │ │ │ │ │ │ │ │ └── pre.js │ │ │ │ │ │ │ │ ├── main.js │ │ │ │ │ │ │ │ └── post.js │ │ │ │ │ │ │ └── node-b/ │ │ │ │ │ │ │ ├── action.yaml │ │ │ │ │ │ │ └── main.js │ │ │ │ │ │ └── workflows/ │ │ │ │ │ │ ├── test.yml │ │ │ │ │ │ └── working-directory.yml │ │ │ │ │ ├── comment.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── scripts/ │ │ │ │ │ ├── check-dependencies.js │ │ │ │ │ ├── from-working-dir-with-path.js │ │ │ │ │ ├── from-working-dir.js │ │ │ │ │ ├── get-release-notes.js │ │ │ │ │ └── no-working-dir.js │ │ │ │ ├── github-actions-workspaces/ │ │ │ │ │ ├── .github/ │ │ │ │ │ │ └── workflows/ │ │ │ │ │ │ └── dir.yml │ │ │ │ │ ├── package.json │ │ │ │ │ └── packages/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── package.json │ │ │ │ │ └── lib/ │ │ │ │ │ └── package.json │ │ │ │ ├── graphql-codegen/ │ │ │ │ │ ├── codegen.ts │ │ │ │ │ ├── codegen.yaml │ │ │ │ │ └── package.json │ │ │ │ ├── graphql-codegen-graphql-config/ │ │ │ │ │ ├── .graphqlrc │ │ │ │ │ ├── graphql.config.toml │ │ │ │ │ ├── graphql.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── graphql-codegen-graphql-config2/ │ │ │ │ │ └── package.json │ │ │ │ ├── hardhat/ │ │ │ │ │ ├── hardhat.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── husky-lint-staged/ │ │ │ │ │ └── package.json │ │ │ │ ├── husky-v8/ │ │ │ │ │ ├── .husky/ │ │ │ │ │ │ ├── post-checkout │ │ │ │ │ │ ├── pre-commit │ │ │ │ │ │ ├── pre-push │ │ │ │ │ │ └── pre-rebase │ │ │ │ │ └── package.json │ │ │ │ ├── husky-v9/ │ │ │ │ │ ├── .husky/ │ │ │ │ │ │ ├── post-checkout │ │ │ │ │ │ ├── pre-commit │ │ │ │ │ │ ├── pre-push │ │ │ │ │ │ └── pre-rebase │ │ │ │ │ └── package.json │ │ │ │ ├── husky-v9-1/ │ │ │ │ │ ├── .husky/ │ │ │ │ │ │ └── pre-commit │ │ │ │ │ └── package.json │ │ │ │ ├── i18next-parser/ │ │ │ │ │ ├── custom.config.js │ │ │ │ │ ├── i18next-parser.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── jest/ │ │ │ │ │ ├── customSuiteProperties.cjs │ │ │ │ │ ├── jest.config.js │ │ │ │ │ ├── jest.config.shared.js │ │ │ │ │ ├── jest.setup.js │ │ │ │ │ ├── jest.transform.js │ │ │ │ │ ├── local-preset/ │ │ │ │ │ │ └── jest-preset.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── snapshotResolver.js │ │ │ │ ├── jest2/ │ │ │ │ │ ├── jest.config.js │ │ │ │ │ ├── jest.environment.js │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── project1/ │ │ │ │ │ ├── customProperties.cjs │ │ │ │ │ ├── jest.config.js │ │ │ │ │ └── setupFiles/ │ │ │ │ │ └── setup.js │ │ │ │ ├── jest3/ │ │ │ │ │ ├── __mocks__/ │ │ │ │ │ │ └── used.js │ │ │ │ │ ├── index.spec.ts │ │ │ │ │ ├── jest.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── karma/ │ │ │ │ │ ├── karma.conf.js │ │ │ │ │ └── package.json │ │ │ │ ├── karma2/ │ │ │ │ │ ├── karma.conf.js │ │ │ │ │ ├── out-of-base-path/ │ │ │ │ │ │ └── example.spec.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── another-example.spec.js │ │ │ │ │ ├── example.spec.js │ │ │ │ │ └── excluded.spec.js │ │ │ │ ├── karma3/ │ │ │ │ │ ├── karma-plugin.js │ │ │ │ │ ├── karma.conf.js │ │ │ │ │ └── package.json │ │ │ │ ├── knex/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── knexfile.js │ │ │ │ │ ├── migrations/ │ │ │ │ │ │ └── 20231201_create_users_table.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── seeds/ │ │ │ │ │ └── 01_users.js │ │ │ │ ├── ladle/ │ │ │ │ │ ├── .ladle/ │ │ │ │ │ │ ├── components.tsx │ │ │ │ │ │ ├── config.mjs │ │ │ │ │ │ └── vite.config.ts │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── basic.stories.tsx │ │ │ │ │ │ └── control.stories.tsx │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lefthook/ │ │ │ │ │ ├── example.mjs │ │ │ │ │ ├── lefthook.yml │ │ │ │ │ └── package.json │ │ │ │ ├── lefthook-ci/ │ │ │ │ │ ├── lefthook.yml │ │ │ │ │ └── package.json │ │ │ │ ├── lefthook-v1/ │ │ │ │ │ ├── _git/ │ │ │ │ │ │ ├── HEAD │ │ │ │ │ │ ├── config │ │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ │ └── prepare-commit-msg │ │ │ │ │ │ ├── objects/ │ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ │ └── refs/ │ │ │ │ │ │ └── heads/ │ │ │ │ │ │ └── .gitkeep │ │ │ │ │ ├── lefthook.yml │ │ │ │ │ └── package.json │ │ │ │ ├── lint-staged/ │ │ │ │ │ ├── .lintstagedrc.js │ │ │ │ │ └── package.json │ │ │ │ ├── lint-staged-comment/ │ │ │ │ │ ├── .lintstagedrc.json │ │ │ │ │ └── package.json │ │ │ │ ├── linthtml/ │ │ │ │ │ ├── .linthtmlrc.js │ │ │ │ │ ├── index.html │ │ │ │ │ └── package.json │ │ │ │ ├── lockfile-lint/ │ │ │ │ │ ├── .lockfile-lintrc.js │ │ │ │ │ └── package.json │ │ │ │ ├── lost-pixel/ │ │ │ │ │ ├── lostpixel.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── markdownlint/ │ │ │ │ │ ├── .markdownlint.json │ │ │ │ │ └── package.json │ │ │ │ ├── mdx/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── mdxlint/ │ │ │ │ │ ├── .mdxlintrc.mjs │ │ │ │ │ └── package.json │ │ │ │ ├── metro/ │ │ │ │ │ ├── custom-metro-transformer.js │ │ │ │ │ ├── metro.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── app/ │ │ │ │ │ └── index.js │ │ │ │ ├── metro-defaults/ │ │ │ │ │ ├── metro.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── app/ │ │ │ │ │ └── index.js │ │ │ │ ├── metro-react-native/ │ │ │ │ │ ├── metro.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── app/ │ │ │ │ │ └── index.js │ │ │ │ ├── mocha/ │ │ │ │ │ ├── .mocharc.json │ │ │ │ │ ├── .mocharc.yml │ │ │ │ │ ├── example.test.ts │ │ │ │ │ ├── hooks.ts │ │ │ │ │ └── package.json │ │ │ │ ├── moonrepo/ │ │ │ │ │ ├── .moon/ │ │ │ │ │ │ ├── tasks/ │ │ │ │ │ │ │ └── typescript.yml │ │ │ │ │ │ └── tasks.yml │ │ │ │ │ ├── apps/ │ │ │ │ │ │ └── a/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── libs/ │ │ │ │ │ │ └── b/ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── server/ │ │ │ │ │ │ └── server.ts │ │ │ │ │ ├── moon.yml │ │ │ │ │ ├── package.json │ │ │ │ │ ├── pnpm-workspace.yaml │ │ │ │ │ ├── tools/ │ │ │ │ │ │ ├── build.ts │ │ │ │ │ │ └── linters/ │ │ │ │ │ │ └── lint-readme.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── msw/ │ │ │ │ │ ├── bob/ │ │ │ │ │ │ └── mockServiceWorker.js │ │ │ │ │ ├── mocks/ │ │ │ │ │ │ ├── browser.ts │ │ │ │ │ │ ├── handlers.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── server.ts │ │ │ │ │ └── package.json │ │ │ │ ├── nano-staged/ │ │ │ │ │ ├── .nano-staged.js │ │ │ │ │ └── package.json │ │ │ │ ├── nest/ │ │ │ │ │ ├── knip.json │ │ │ │ │ ├── nest-cli.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app.controller.spec.ts │ │ │ │ │ │ ├── app.controller.ts │ │ │ │ │ │ ├── app.module.ts │ │ │ │ │ │ ├── app.service.ts │ │ │ │ │ │ └── main.ts │ │ │ │ │ └── test/ │ │ │ │ │ ├── app.e2e-spec.ts │ │ │ │ │ └── jest-e2e.json │ │ │ │ ├── netlify/ │ │ │ │ │ ├── netlify.toml │ │ │ │ │ └── package.json │ │ │ │ ├── next/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── api/ │ │ │ │ │ │ │ └── auth/ │ │ │ │ │ │ │ ├── route.ts │ │ │ │ │ │ │ └── util.ts │ │ │ │ │ │ ├── home/ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ └── sitemap.ts │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ ├── sitemap.ts │ │ │ │ │ │ └── unused.ts │ │ │ │ │ ├── instrumentation.ts │ │ │ │ │ ├── middleware.ts │ │ │ │ │ ├── next.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── pages/ │ │ │ │ │ ├── [[...route]].tsx │ │ │ │ │ ├── home.tsx │ │ │ │ │ └── unused.jsx │ │ │ │ ├── next-intl/ │ │ │ │ │ ├── i18n/ │ │ │ │ │ │ └── request.ts │ │ │ │ │ └── package.json │ │ │ │ ├── next-mdx/ │ │ │ │ │ ├── mdx-components.tsx │ │ │ │ │ ├── next.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── next-middleware/ │ │ │ │ │ ├── next.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ └── middleware.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── next-page-extensions/ │ │ │ │ │ ├── next.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── instrumentation.page.ts │ │ │ │ │ ├── middleware.page.ts │ │ │ │ │ └── unused.ts │ │ │ │ ├── nitro/ │ │ │ │ │ ├── .nitro/ │ │ │ │ │ │ └── types/ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── nitro.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ └── fn.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── node/ │ │ │ │ │ └── package.json │ │ │ │ ├── node-modules-inspector/ │ │ │ │ │ ├── .nmrc.js │ │ │ │ │ ├── node-modules-inspector.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── node-test-runner/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── index.test.js │ │ │ │ │ └── package.json │ │ │ │ ├── nodemon/ │ │ │ │ │ └── package.json │ │ │ │ ├── npm-package-json-lint/ │ │ │ │ │ ├── .npmpackagejsonlintrc.json │ │ │ │ │ └── package.json │ │ │ │ ├── nuxt/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── app.tsx │ │ │ │ │ ├── app.vue │ │ │ │ │ ├── nuxt.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── api/ │ │ │ │ │ │ │ └── health.get.ts │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ └── db.ts │ │ │ │ │ ├── shared/ │ │ │ │ │ │ ├── types/ │ │ │ │ │ │ │ └── api.ts │ │ │ │ │ │ └── utils/ │ │ │ │ │ │ └── capitalize.ts │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── utils/ │ │ │ │ │ └── fn.ts │ │ │ │ ├── nuxt-auto-import/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── app.vue │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── AppHeader.vue │ │ │ │ │ │ └── StatusBadge.vue │ │ │ │ │ ├── composables/ │ │ │ │ │ │ ├── useCounter.ts │ │ │ │ │ │ └── useTheme.ts │ │ │ │ │ ├── nuxt.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── utils/ │ │ │ │ │ └── format.ts │ │ │ │ ├── nuxt-auto-import-disabled/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── app.vue │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── AppHeader.vue │ │ │ │ │ │ └── StatusBadge.vue │ │ │ │ │ ├── composables/ │ │ │ │ │ │ ├── useCounter.ts │ │ │ │ │ │ └── useTheme.ts │ │ │ │ │ ├── nuxt.config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── utils/ │ │ │ │ │ └── format.ts │ │ │ │ ├── nuxt-config/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── app.vue │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── Button.vue │ │ │ │ │ ├── custom-utils/ │ │ │ │ │ │ └── logger.ts │ │ │ │ │ ├── local-module/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── my-plugins/ │ │ │ │ │ │ └── auth.ts │ │ │ │ │ ├── nuxt.config.ts │ │ │ │ │ ├── other-components/ │ │ │ │ │ │ └── Card.vue │ │ │ │ │ ├── package.json │ │ │ │ │ ├── some-layer/ │ │ │ │ │ │ └── nuxt.config.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── nx/ │ │ │ │ │ ├── apps/ │ │ │ │ │ │ ├── a/ │ │ │ │ │ │ │ ├── project.json │ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ │ └── b/ │ │ │ │ │ │ ├── project.json │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── knip.json │ │ │ │ │ ├── libs/ │ │ │ │ │ │ └── b/ │ │ │ │ │ │ ├── .eslintrc.json │ │ │ │ │ │ ├── jest.config.ts │ │ │ │ │ │ ├── project.json │ │ │ │ │ │ ├── tsconfig.build.json │ │ │ │ │ │ ├── tsconfig.lib.json │ │ │ │ │ │ ├── vitest.config.ts │ │ │ │ │ │ └── webpack.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.base.json │ │ │ │ ├── nx-crystal/ │ │ │ │ │ ├── nx.json │ │ │ │ │ └── package.json │ │ │ │ ├── nyc/ │ │ │ │ │ ├── .nycrc.json │ │ │ │ │ └── package.json │ │ │ │ ├── oclif/ │ │ │ │ │ └── package.json │ │ │ │ ├── openapi-ts/ │ │ │ │ │ ├── openapi-ts.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── oxfmt/ │ │ │ │ │ ├── .oxfmtrc-1.jsonc │ │ │ │ │ ├── .oxfmtrc.json │ │ │ │ │ ├── .oxfmtrc.jsonc │ │ │ │ │ └── package.json │ │ │ │ ├── oxlint/ │ │ │ │ │ ├── .oxlintrc-0.json │ │ │ │ │ ├── .oxlintrc-3.json │ │ │ │ │ ├── .oxlintrc-4.json │ │ │ │ │ ├── oxlint-5.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── parcel/ │ │ │ │ │ ├── .parcelrc │ │ │ │ │ └── package.json │ │ │ │ ├── payload/ │ │ │ │ │ ├── migrations/ │ │ │ │ │ │ └── 20260218.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── payload-types.ts │ │ │ │ │ ├── payload.config.ts │ │ │ │ │ └── src/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── (payload)/ │ │ │ │ │ │ └── importMap.js │ │ │ │ │ └── components/ │ │ │ │ │ └── ImportMapComponent.tsx │ │ │ │ ├── playwright/ │ │ │ │ │ ├── custom-reporter.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── playwright.config.ts │ │ │ │ │ └── test/ │ │ │ │ │ └── some.spec.ts │ │ │ │ ├── playwright-ct/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── playwright/ │ │ │ │ │ │ ├── common.css │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── playwright-ct.config.ts │ │ │ │ │ └── test/ │ │ │ │ │ └── some.spec.ts │ │ │ │ ├── playwright-ct2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── playwright-ct.config.ts │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── unused.spec.ts │ │ │ │ │ └── tests/ │ │ │ │ │ └── component/ │ │ │ │ │ └── some.spec.ts │ │ │ │ ├── playwright2/ │ │ │ │ │ ├── integration/ │ │ │ │ │ │ └── some-test.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── playwright.config.ts │ │ │ │ ├── plop/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── plopfile.js │ │ │ │ │ └── template.hbs │ │ │ │ ├── pm2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── pm2.config.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── another.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── unused.js │ │ │ │ ├── pm2-ecosystem/ │ │ │ │ │ ├── ecosystem.config.json │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── another.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── unused.js │ │ │ │ ├── pnpm/ │ │ │ │ │ ├── .pnpmfile.cjs │ │ │ │ │ └── package.json │ │ │ │ ├── pnpm2/ │ │ │ │ │ ├── .pnpmfile.cjs │ │ │ │ │ ├── package.json │ │ │ │ │ └── pnpm-workspace.yaml │ │ │ │ ├── postcss/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── postcss.config.js │ │ │ │ ├── postcss-cjs/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── postcss.config.cjs │ │ │ │ ├── postcss-next/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── postcss.config.json │ │ │ │ ├── postcss-tailwindcss/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── postcss.config.js │ │ │ │ ├── postcss-tailwindcss2/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── postcss.config.mjs │ │ │ │ ├── preconstruct/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── other.js │ │ │ │ ├── prettier/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── prettier.config.js │ │ │ │ ├── prettier-json5/ │ │ │ │ │ ├── .prettierrc.json5 │ │ │ │ │ └── package.json │ │ │ │ ├── prettier-reexport/ │ │ │ │ │ ├── knip.json │ │ │ │ │ ├── package.json │ │ │ │ │ └── prettier.config.js │ │ │ │ ├── prisma/ │ │ │ │ │ ├── .config/ │ │ │ │ │ │ └── prisma.ts │ │ │ │ │ ├── config/ │ │ │ │ │ │ └── prisma.custom-config.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── prisma/ │ │ │ │ │ │ ├── schema-dot-config.prisma │ │ │ │ │ │ ├── schema-package-json.prisma │ │ │ │ │ │ ├── schema-root-config.prisma │ │ │ │ │ │ ├── schema-script.prisma │ │ │ │ │ │ ├── seed-dot-config.ts │ │ │ │ │ │ ├── seed-package-json.ts │ │ │ │ │ │ └── seed-root-config.ts │ │ │ │ │ ├── prisma-multi-schema/ │ │ │ │ │ │ ├── model/ │ │ │ │ │ │ │ ├── post.prisma │ │ │ │ │ │ │ └── user.prisma │ │ │ │ │ │ └── schema.prisma │ │ │ │ │ └── prisma.config.ts │ │ │ │ ├── prisma2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── prisma/ │ │ │ │ │ │ └── schema.prisma │ │ │ │ │ └── schema.prisma │ │ │ │ ├── qwik/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ └── router-head.tsx │ │ │ │ │ │ ├── entry.dev.tsx │ │ │ │ │ │ ├── entry.preview.tsx │ │ │ │ │ │ ├── entry.ssr.tsx │ │ │ │ │ │ ├── root.tsx │ │ │ │ │ │ └── routes/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── layout.tsx │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── qwik-custom-dirs/ │ │ │ │ │ ├── docs/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ └── mdx-note.tsx │ │ │ │ │ │ ├── entry.dev.tsx │ │ │ │ │ │ ├── entry.preview.tsx │ │ │ │ │ │ ├── entry.ssr.tsx │ │ │ │ │ │ ├── extra-pages/ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── pages/ │ │ │ │ │ │ │ ├── guide.mdx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── root.tsx │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── raycast/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── search-bookmarks.tsx │ │ │ │ │ ├── shared/ │ │ │ │ │ │ └── load-bookmarks.ts │ │ │ │ │ ├── tools/ │ │ │ │ │ │ └── organize-tabs.ts │ │ │ │ │ └── unused.ts │ │ │ │ ├── react-cosmos/ │ │ │ │ │ ├── __fixtures__/ │ │ │ │ │ │ └── any.mdx │ │ │ │ │ ├── cosmos.config.json │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── cosmos.decorator.tsx │ │ │ │ │ └── my-cosmos-plugin.ts │ │ │ │ ├── react-native/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── react-native.config.js │ │ │ │ ├── react-router/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── root.tsx │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ ├── $/ │ │ │ │ │ │ │ │ └── route.tsx │ │ │ │ │ │ │ ├── $.tsx │ │ │ │ │ │ │ ├── another-route.tsx │ │ │ │ │ │ │ ├── home.tsx │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── main+/ │ │ │ │ │ │ │ │ └── nested+/ │ │ │ │ │ │ │ │ └── _index.tsx │ │ │ │ │ │ │ └── route.(with).$special[.chars].tsx │ │ │ │ │ │ └── routes.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── react-router.config.ts │ │ │ │ ├── react-router-with-server-entry/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── entry.server.tsx │ │ │ │ │ │ ├── root.tsx │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ └── home.tsx │ │ │ │ │ │ └── routes.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── react-router.config.ts │ │ │ │ ├── relay/ │ │ │ │ │ ├── __generated__/ │ │ │ │ │ │ └── artifact.graphql.ts │ │ │ │ │ ├── myrelay.config.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── unused.ts │ │ │ │ │ ├── used.ts │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── relay2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── relay.config.js │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── __generated__/ │ │ │ │ │ │ └── artifact.graphql.ts │ │ │ │ │ ├── unused.ts │ │ │ │ │ ├── used.ts │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── release-it/ │ │ │ │ │ ├── .release-it.json │ │ │ │ │ ├── bin/ │ │ │ │ │ │ └── release-notes.js │ │ │ │ │ └── package.json │ │ │ │ ├── remark/ │ │ │ │ │ └── package.json │ │ │ │ ├── remix/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── entry.client.tsx │ │ │ │ │ │ ├── entry.server.tsx │ │ │ │ │ │ ├── root.tsx │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── utils.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── remix.config.js │ │ │ │ │ ├── remix.init/ │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── server.js │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── rollup/ │ │ │ │ │ ├── do-not-bundle.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── rollup.config.js │ │ │ │ ├── rsbuild/ │ │ │ │ │ ├── entry-1.ts │ │ │ │ │ ├── entry-2.ts │ │ │ │ │ ├── entry-3.ts │ │ │ │ │ ├── entry-4.ts │ │ │ │ │ ├── entry-5.ts │ │ │ │ │ ├── entry-6.ts │ │ │ │ │ ├── entry-7.ts │ │ │ │ │ ├── entry-8.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── pre-entry-1.ts │ │ │ │ │ ├── pre-entry-2.ts │ │ │ │ │ ├── pre-entry-3.ts │ │ │ │ │ └── rsbuild.config.ts │ │ │ │ ├── rslib/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── rslib.config.ts │ │ │ │ ├── rspack/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── rspack.config.js │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── entry.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── rstest/ │ │ │ │ │ ├── included.test.ts │ │ │ │ │ ├── not-included.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── rstest.config.ts │ │ │ │ ├── rstest2/ │ │ │ │ │ ├── __mocks__/ │ │ │ │ │ │ └── lodash.ts │ │ │ │ │ ├── excluded.test.ts │ │ │ │ │ ├── included.test.ts │ │ │ │ │ ├── not-included.spec.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── rstest.config.ts │ │ │ │ ├── sanity/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── sanity.blueprint.ts │ │ │ │ │ ├── sanity.cli.ts │ │ │ │ │ ├── sanity.config.ts │ │ │ │ │ └── schema.ts │ │ │ │ ├── semantic-release/ │ │ │ │ │ ├── .releaserc │ │ │ │ │ └── package.json │ │ │ │ ├── sentry/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── sentry.client.config.ts │ │ │ │ │ ├── sentry.edge.config.ts │ │ │ │ │ └── sentry.server.config.ts │ │ │ │ ├── simple-git-hooks/ │ │ │ │ │ └── package.json │ │ │ │ ├── size-limit/ │ │ │ │ │ ├── .size-limit.cjs │ │ │ │ │ └── package.json │ │ │ │ ├── sst/ │ │ │ │ │ ├── handlers/ │ │ │ │ │ │ ├── auth.ts │ │ │ │ │ │ ├── other-auth.ts │ │ │ │ │ │ └── some-route.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── sst.config.ts │ │ │ │ │ └── stacks/ │ │ │ │ │ ├── AuthHandlerStack.ts │ │ │ │ │ └── AuthStack.ts │ │ │ │ ├── sst2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── route.ts │ │ │ │ │ └── sst.config.ts │ │ │ │ ├── starlight/ │ │ │ │ │ ├── astro.config.mjs │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── Footer.astro │ │ │ │ │ │ └── Head.astro │ │ │ │ │ └── package.json │ │ │ │ ├── storybook/ │ │ │ │ │ ├── .storybook/ │ │ │ │ │ │ ├── main.js │ │ │ │ │ │ ├── preview.js │ │ │ │ │ │ └── vitest.setup.ts │ │ │ │ │ ├── addon/ │ │ │ │ │ │ └── register.js │ │ │ │ │ └── package.json │ │ │ │ ├── storybook2/ │ │ │ │ │ ├── .rnstorybook/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── main.ts │ │ │ │ │ │ ├── preview.tsx │ │ │ │ │ │ └── storybook.requires.ts │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── Button/ │ │ │ │ │ │ ├── Button.stories.tsx │ │ │ │ │ │ └── Button.tsx │ │ │ │ │ └── package.json │ │ │ │ ├── stryker/ │ │ │ │ │ ├── .stryker.conf.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── stryker.conf.cjs │ │ │ │ │ ├── stryker.conf.json │ │ │ │ │ └── stryker.conf.mjs │ │ │ │ ├── stylelint/ │ │ │ │ │ ├── .stylelintrc │ │ │ │ │ └── package.json │ │ │ │ ├── stylelint2/ │ │ │ │ │ ├── .stylelintrc.cjs │ │ │ │ │ ├── .stylelintrc.mjs │ │ │ │ │ ├── myCustomPlugin.js │ │ │ │ │ ├── myExtendableConfig.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── stylelint.config.js │ │ │ │ ├── stylelint3/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── stylelint.config.mjs │ │ │ │ ├── svelte/ │ │ │ │ │ ├── .svelte-kit/ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app.d.ts │ │ │ │ │ │ ├── app.html │ │ │ │ │ │ ├── hooks.client.ts │ │ │ │ │ │ ├── hooks.server.ts │ │ │ │ │ │ ├── instrumentation.server.ts │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ ├── component.svelte │ │ │ │ │ │ │ └── store.svelte.ts │ │ │ │ │ │ ├── params/ │ │ │ │ │ │ │ └── lang.ts │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ ├── +layout.svelte │ │ │ │ │ │ │ ├── +page.svelte │ │ │ │ │ │ │ ├── +page.ts │ │ │ │ │ │ │ ├── Counter.svelte │ │ │ │ │ │ │ ├── Header.svelte │ │ │ │ │ │ │ ├── login/ │ │ │ │ │ │ │ │ └── +server.ts │ │ │ │ │ │ │ └── styles.css │ │ │ │ │ │ └── service-worker.ts │ │ │ │ │ ├── svelte.config.js │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── sveltekit/ │ │ │ │ │ ├── .svelte-kit/ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app.d.ts │ │ │ │ │ │ ├── app.html │ │ │ │ │ │ ├── hooks.client.ts │ │ │ │ │ │ ├── hooks.server.ts │ │ │ │ │ │ ├── instrumentation.server.ts │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ ├── component.svelte │ │ │ │ │ │ │ └── store.svelte.ts │ │ │ │ │ │ ├── params/ │ │ │ │ │ │ │ └── lang.ts │ │ │ │ │ │ ├── routes/ │ │ │ │ │ │ │ ├── +layout.svelte │ │ │ │ │ │ │ ├── +page.svelte │ │ │ │ │ │ │ ├── +page.ts │ │ │ │ │ │ │ ├── Counter.svelte │ │ │ │ │ │ │ ├── Header.svelte │ │ │ │ │ │ │ ├── login/ │ │ │ │ │ │ │ │ └── +server.ts │ │ │ │ │ │ │ └── styles.css │ │ │ │ │ │ └── service-worker.ts │ │ │ │ │ ├── svelte.config.js │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── sveltekit2/ │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── lib/ │ │ │ │ │ │ └── helper.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── routes/ │ │ │ │ │ │ └── +page.svelte │ │ │ │ │ └── svelte.config.js │ │ │ │ ├── svgo/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── svgo.config.js │ │ │ │ ├── svgr/ │ │ │ │ │ ├── .svgrrc │ │ │ │ │ └── package.json │ │ │ │ ├── swc/ │ │ │ │ │ ├── .swcrc │ │ │ │ │ └── package.json │ │ │ │ ├── syncpack/ │ │ │ │ │ └── package.json │ │ │ │ ├── tailwind/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── tailwind.config.js │ │ │ │ ├── tailwind2/ │ │ │ │ │ ├── index.html │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── styles.css │ │ │ │ ├── tanstack-router/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── routeTree.gen.ts │ │ │ │ │ │ └── routes/ │ │ │ │ │ │ ├── __root.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── posts/ │ │ │ │ │ │ └── $postId.tsx │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── tsr.config.json │ │ │ │ ├── taskfile/ │ │ │ │ │ ├── Taskfile.yml │ │ │ │ │ ├── check.ts │ │ │ │ │ ├── nested/ │ │ │ │ │ │ └── Taskfile.yml │ │ │ │ │ ├── package.json │ │ │ │ │ ├── scripts/ │ │ │ │ │ │ ├── build.js │ │ │ │ │ │ ├── deep.js │ │ │ │ │ │ ├── deploy.js │ │ │ │ │ │ ├── dev.js │ │ │ │ │ │ ├── nested.js │ │ │ │ │ │ └── shared.js │ │ │ │ │ └── shared/ │ │ │ │ │ ├── Taskfile.yml │ │ │ │ │ └── deep/ │ │ │ │ │ └── Taskfile.yml │ │ │ │ ├── taskfile2/ │ │ │ │ │ ├── custom-taskfile.yml │ │ │ │ │ ├── knip.json │ │ │ │ │ ├── package.json │ │ │ │ │ ├── scripts/ │ │ │ │ │ │ ├── custom-build.js │ │ │ │ │ │ ├── custom-test.js │ │ │ │ │ │ └── subtask.js │ │ │ │ │ └── tasks/ │ │ │ │ │ └── subtask.yml │ │ │ │ ├── travis/ │ │ │ │ │ ├── .travis.yml │ │ │ │ │ └── package.json │ │ │ │ ├── tsdown/ │ │ │ │ │ ├── entry-1.ts │ │ │ │ │ ├── entry-2.ts │ │ │ │ │ ├── entry-3.ts │ │ │ │ │ ├── entry-4.ts │ │ │ │ │ ├── entry-5.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsdown.config-3.ts │ │ │ │ │ ├── tsdown.config-4.ts │ │ │ │ │ ├── tsdown.config.json │ │ │ │ │ └── tsdown.config.ts │ │ │ │ ├── tsgo/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── tsup/ │ │ │ │ │ ├── entry-1.ts │ │ │ │ │ ├── entry-2.ts │ │ │ │ │ ├── entry-3.ts │ │ │ │ │ ├── entry-4.ts │ │ │ │ │ ├── entry-5.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsup.config-3.ts │ │ │ │ │ ├── tsup.config-4.ts │ │ │ │ │ ├── tsup.config.json │ │ │ │ │ └── tsup.config.ts │ │ │ │ ├── tsx/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── test/ │ │ │ │ │ ├── a.ts │ │ │ │ │ └── dir/ │ │ │ │ │ └── b.ts │ │ │ │ ├── typedoc/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── typedoc.json │ │ │ │ ├── typescript/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.app.json │ │ │ │ │ ├── tsconfig.base.json │ │ │ │ │ ├── tsconfig.ext.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ ├── tsconfig.jsx-import-source-preact.json │ │ │ │ │ ├── tsconfig.jsx-import-source-react.json │ │ │ │ │ ├── tsconfig.jsx-preserve.json │ │ │ │ │ └── tsconfig.jsx.json │ │ │ │ ├── typescript2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── packages/ │ │ │ │ │ │ ├── lib/ │ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ │ ├── src/ │ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── unbuild/ │ │ │ │ │ ├── build.config.ts │ │ │ │ │ └── package.json │ │ │ │ ├── unocss/ │ │ │ │ │ ├── main.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── unocss.config.ts │ │ │ │ ├── vercel-og/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ └── api/ │ │ │ │ │ │ └── og/ │ │ │ │ │ │ └── route.jsx │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ └── pages/ │ │ │ │ │ └── api/ │ │ │ │ │ └── og.tsx │ │ │ │ ├── vike/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── pages/ │ │ │ │ │ │ ├── _error/ │ │ │ │ │ │ │ └── +Page.tsx │ │ │ │ │ │ ├── about/ │ │ │ │ │ │ │ ├── +Page.tsx │ │ │ │ │ │ │ └── code.css │ │ │ │ │ │ ├── index/ │ │ │ │ │ │ │ ├── +Page.tsx │ │ │ │ │ │ │ └── Counter.tsx │ │ │ │ │ │ └── star-wars/ │ │ │ │ │ │ ├── @id/ │ │ │ │ │ │ │ ├── +Page.tsx │ │ │ │ │ │ │ └── +data.ts │ │ │ │ │ │ ├── index/ │ │ │ │ │ │ │ ├── +Page.tsx │ │ │ │ │ │ │ └── +data.ts │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── renderer/ │ │ │ │ │ │ ├── +config.ts │ │ │ │ │ │ ├── +onPageTransitionEnd.ts │ │ │ │ │ │ ├── +onPageTransitionStart.ts │ │ │ │ │ │ ├── +onRenderClient.tsx │ │ │ │ │ │ ├── +onRenderHtml.tsx │ │ │ │ │ │ ├── Layout.css │ │ │ │ │ │ ├── Layout.tsx │ │ │ │ │ │ ├── Link.tsx │ │ │ │ │ │ ├── getPageTitle.ts │ │ │ │ │ │ ├── useData.ts │ │ │ │ │ │ └── usePageContext.tsx │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── root.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── vite/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── vite-env.d.ts │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── vite2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── mock.desktop.js │ │ │ │ │ │ └── mock.desktop.ts │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── vite3/ │ │ │ │ │ ├── index.html │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── App.tsx │ │ │ │ │ └── unused.ts │ │ │ │ ├── vite4/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── component.ts │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── main.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── vitepress/ │ │ │ │ │ ├── .vitepress/ │ │ │ │ │ │ ├── config.mts │ │ │ │ │ │ └── theme/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.md │ │ │ │ │ └── package.json │ │ │ │ ├── vitest/ │ │ │ │ │ ├── __mocks__/ │ │ │ │ │ │ └── mockedModule.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── setupTests.ts │ │ │ │ │ │ └── vite-env.d.ts │ │ │ │ │ ├── test/ │ │ │ │ │ │ ├── basic.bench.ts │ │ │ │ │ │ ├── basic.spec-d.ts │ │ │ │ │ │ ├── basic.spec.ts │ │ │ │ │ │ └── basic.test-d.ts │ │ │ │ │ ├── vite.config.ts │ │ │ │ │ ├── vitest-default-coverage.config.ts │ │ │ │ │ ├── vitest.config.ts │ │ │ │ │ └── vitest.workspace.ts │ │ │ │ ├── vitest-npm-script/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest2/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── basic.spec.ts │ │ │ │ │ │ └── unit.vitest.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest3/ │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── basic.test.ts │ │ │ │ │ │ └── unit.test.tsx │ │ │ │ │ ├── vite.config.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest4/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── unused.test.ts │ │ │ │ │ ├── tests/ │ │ │ │ │ │ ├── adder.test.ts │ │ │ │ │ │ └── setup.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest5/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── index.test.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── vite.config.ts │ │ │ │ ├── vitest6/ │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── fiep.ts │ │ │ │ │ │ └── setup.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── unused.test.ts │ │ │ │ │ └── tests/ │ │ │ │ │ └── adder.test.ts │ │ │ │ ├── vitest7/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── index.test.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest8/ │ │ │ │ │ ├── my-env.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── custom-env.test.ts │ │ │ │ │ │ ├── index.test.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vitest9/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── packages/ │ │ │ │ │ │ └── client/ │ │ │ │ │ │ ├── e2e/ │ │ │ │ │ │ │ ├── another-setup.js │ │ │ │ │ │ │ └── client.test.ts │ │ │ │ │ │ ├── e2e-setup.ts │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── vitest.config.e2e.ts │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── example.test.ts │ │ │ │ │ │ └── unit.setup.ts │ │ │ │ │ └── vitest.config.ts │ │ │ │ ├── vue/ │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── vue.config.js │ │ │ │ ├── vue-webpack/ │ │ │ │ │ ├── child1.vue │ │ │ │ │ ├── child2.vue │ │ │ │ │ ├── child3.vue │ │ │ │ │ ├── knip.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── parent.vue │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── vue.config.js │ │ │ │ ├── webdriver-io/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── wdio.conf.js │ │ │ │ ├── webpack/ │ │ │ │ │ ├── merge.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── app-dep.ts │ │ │ │ │ │ ├── app.tsx │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ ├── button.js │ │ │ │ │ │ │ └── input.js │ │ │ │ │ │ ├── entry.js │ │ │ │ │ │ ├── module1.js │ │ │ │ │ │ ├── my-custom-loader.js │ │ │ │ │ │ ├── routes.ts │ │ │ │ │ │ ├── subpath-entry.ts │ │ │ │ │ │ ├── unused.ts │ │ │ │ │ │ └── vendor.js │ │ │ │ │ ├── webpack.babel.js │ │ │ │ │ ├── webpack.common.js │ │ │ │ │ ├── webpack.config.js │ │ │ │ │ ├── webpack.dev.js │ │ │ │ │ └── webpack.prod.js │ │ │ │ ├── webpack-cli/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── webpack.config.js │ │ │ │ ├── webpack-reexport/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── webpack.config.js │ │ │ │ ├── webpack2/ │ │ │ │ │ ├── entry.dev.js │ │ │ │ │ ├── entry.prod.js │ │ │ │ │ ├── package.json │ │ │ │ │ ├── webpack.dev.js │ │ │ │ │ └── webpack.prod.js │ │ │ │ ├── wireit/ │ │ │ │ │ ├── apps/ │ │ │ │ │ │ ├── example-configuration/ │ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ │ ├── rollup.config.json │ │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ │ └── missing/ │ │ │ │ │ │ └── package.json │ │ │ │ │ └── package.json │ │ │ │ ├── wrangler/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── worker-test-entry.ts │ │ │ │ │ └── wrangler.toml │ │ │ │ ├── xo/ │ │ │ │ │ ├── .xo-config.js │ │ │ │ │ ├── package.json │ │ │ │ │ └── xo.config.cjs │ │ │ │ ├── yarn/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── yarn.config.cjs │ │ │ │ ├── yarn-berry/ │ │ │ │ │ ├── .gitgnore │ │ │ │ │ ├── .yarn/ │ │ │ │ │ │ ├── plugins/ │ │ │ │ │ │ │ └── @yarnpkg/ │ │ │ │ │ │ │ ├── plugin-bar.cjs │ │ │ │ │ │ │ └── plugin-foo.cjs │ │ │ │ │ │ └── releases/ │ │ │ │ │ │ └── yarn-4.12.0.cjs │ │ │ │ │ ├── .yarnrc.yml │ │ │ │ │ ├── package.json │ │ │ │ │ └── yarn.config.cjs │ │ │ │ └── yorkie/ │ │ │ │ └── package.json │ │ │ ├── pragma/ │ │ │ │ ├── index.test.ts │ │ │ │ ├── index.ts │ │ │ │ ├── jsx.tsx │ │ │ │ ├── local-env.js │ │ │ │ ├── package.json │ │ │ │ ├── reference-types.ts │ │ │ │ └── tsconfig.json │ │ │ ├── preprocessors/ │ │ │ │ ├── identity.ts │ │ │ │ └── minimal.ts │ │ │ ├── re-exports/ │ │ │ │ ├── 1-entry.ts │ │ │ │ ├── 2-re-export-star.ts │ │ │ │ ├── 3-re-export-named.ts │ │ │ │ ├── 4-my-module.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-aliased-ns/ │ │ │ │ ├── 1-first.ts │ │ │ │ ├── 2-second.ts │ │ │ │ ├── 3-barrel.ts │ │ │ │ ├── 4-collect.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-cjs/ │ │ │ │ ├── 1-entry.js │ │ │ │ ├── 2-re-export-star.js │ │ │ │ ├── 3-my-module.js │ │ │ │ └── package.json │ │ │ ├── re-exports-deep/ │ │ │ │ ├── 1-entry.ts │ │ │ │ ├── 2-re-export-star.ts │ │ │ │ ├── 3-re-export-named.ts │ │ │ │ ├── 4-re-export-star.ts │ │ │ │ ├── 5-re-export-named.ts │ │ │ │ ├── 6-re-export-star.ts │ │ │ │ ├── 7-my-module.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-default-renamed/ │ │ │ │ ├── default-reexported/ │ │ │ │ │ ├── blueberry.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── pear.ts │ │ │ │ ├── index.ts │ │ │ │ ├── named-reexported/ │ │ │ │ │ ├── apricot.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── peach.ts │ │ │ │ ├── not-reexported/ │ │ │ │ │ └── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-default-renamed-deep/ │ │ │ │ ├── deep.ts │ │ │ │ ├── default-reexported/ │ │ │ │ │ ├── blueberry.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── pear.ts │ │ │ │ │ └── pineapple.ts │ │ │ │ ├── index.ts │ │ │ │ ├── intermediate.ts │ │ │ │ ├── named-reexported/ │ │ │ │ │ ├── apricot.ts │ │ │ │ │ ├── coconut.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── peach.ts │ │ │ │ ├── not-reexported/ │ │ │ │ │ └── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-destructure-spread/ │ │ │ │ ├── animal.ts │ │ │ │ ├── animals.ts │ │ │ │ ├── farm.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-enum/ │ │ │ │ ├── index.ts │ │ │ │ ├── mid.ts │ │ │ │ ├── myEnum.ts │ │ │ │ ├── myNextEnum.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-enum-members-workspace/ │ │ │ │ ├── index.ts │ │ │ │ ├── lib/ │ │ │ │ │ ├── enums.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── package.json │ │ │ ├── re-exports-enum-unused/ │ │ │ │ ├── index.ts │ │ │ │ ├── mid.ts │ │ │ │ ├── myEnum.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-export-declaration/ │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── exporter/ │ │ │ │ │ ├── exporterA.ts │ │ │ │ │ ├── exporterB.ts │ │ │ │ │ ├── exporterC.ts │ │ │ │ │ ├── exporterD.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── re-exports-export-ns/ │ │ │ │ ├── 1-root.ts │ │ │ │ ├── 2-psuedo-re-exporter.ts │ │ │ │ ├── 3-branch.ts │ │ │ │ ├── 4-leaf-A.ts │ │ │ │ ├── 4-leaf-B.ts │ │ │ │ ├── 4-leaf-C.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-ignore-exports-used-in-file/ │ │ │ │ ├── export.ts │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── reexport.ts │ │ │ ├── re-exports-ns-member/ │ │ │ │ ├── index.ts │ │ │ │ ├── member-ab.ts │ │ │ │ ├── member-cd.ts │ │ │ │ ├── package.json │ │ │ │ ├── sub2-pseudo.ts │ │ │ │ ├── sub2-sub.ts │ │ │ │ └── sub3.ts │ │ │ ├── re-exports-ns-type/ │ │ │ │ ├── assets.tsx │ │ │ │ ├── barrel.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── package.json │ │ │ │ ├── pluginA.ts │ │ │ │ ├── pluginB.ts │ │ │ │ ├── styled.ts │ │ │ │ └── tsconfig.json │ │ │ ├── re-exports-ns-type2/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── schema.ts │ │ │ │ └── types.ts │ │ │ ├── re-exports-pseudo/ │ │ │ │ ├── index.ts │ │ │ │ ├── left.ts │ │ │ │ ├── package.json │ │ │ │ ├── pseudo.ts │ │ │ │ └── right.ts │ │ │ ├── re-exports-public/ │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-recursive/ │ │ │ │ ├── barrel.ts │ │ │ │ ├── cycle-a.ts │ │ │ │ ├── cycle-b.ts │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-renamed/ │ │ │ │ ├── fileA.ts │ │ │ │ ├── fileB.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-spread/ │ │ │ │ ├── animal.ts │ │ │ │ ├── animals.ts │ │ │ │ ├── farm.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-twice/ │ │ │ │ ├── dir/ │ │ │ │ │ ├── default.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── named.ts │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── re-exports-with-decorator/ │ │ │ │ ├── barrel.ts │ │ │ │ ├── decorator.ts │ │ │ │ ├── entry.ts │ │ │ │ ├── my-module.ts │ │ │ │ └── package.json │ │ │ ├── rules/ │ │ │ │ ├── exports.ts │ │ │ │ ├── index.ts │ │ │ │ ├── ns.ts │ │ │ │ ├── package.json │ │ │ │ └── unused.ts │ │ │ ├── script-visitors-bun/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── script.ts │ │ │ ├── script-visitors-execa/ │ │ │ │ ├── execa-docs.mjs │ │ │ │ ├── main.js │ │ │ │ ├── methods.mjs │ │ │ │ ├── node.mjs │ │ │ │ ├── options.mjs │ │ │ │ ├── package.json │ │ │ │ └── script.js │ │ │ ├── script-visitors-zx/ │ │ │ │ ├── main.js │ │ │ │ ├── node.mjs │ │ │ │ ├── package.json │ │ │ │ ├── script.js │ │ │ │ └── zx-docs.mjs │ │ │ ├── self-reference/ │ │ │ │ ├── .gitignore │ │ │ │ ├── entry.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ └── module.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── self-reference-from-plugin/ │ │ │ │ ├── .eslintrc.json │ │ │ │ ├── .gitignore │ │ │ │ ├── data.json │ │ │ │ ├── entry.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lokal.js │ │ │ │ └── package.json │ │ │ ├── session/ │ │ │ │ ├── Harness.Parallel.Host.ts │ │ │ │ ├── Harness.Parallel.Worker.ts │ │ │ │ ├── Harness.Parallel.ts │ │ │ │ ├── Harness.ts │ │ │ │ ├── a.ts │ │ │ │ ├── b.ts │ │ │ │ ├── c.ts │ │ │ │ ├── default-export.ts │ │ │ │ ├── diamond-base.ts │ │ │ │ ├── diamond-left.ts │ │ │ │ ├── diamond-right.ts │ │ │ │ ├── diamond-top.ts │ │ │ │ ├── flowers.ts │ │ │ │ ├── host.ts │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── overload-1.ts │ │ │ │ ├── overload-2.ts │ │ │ │ ├── overload-3.ts │ │ │ │ ├── package.json │ │ │ │ ├── rose.ts │ │ │ │ ├── runner.ts │ │ │ │ ├── src/ │ │ │ │ │ ├── core/ │ │ │ │ │ │ └── app/ │ │ │ │ │ │ └── types.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types/ │ │ │ │ │ └── public/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── internal.ts │ │ │ │ ├── theme-reexport.ts │ │ │ │ ├── theme.ts │ │ │ │ └── worker.ts │ │ │ ├── session-dependencies/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── utils.ts │ │ │ │ └── tsconfig.json │ │ │ ├── session-re-exports/ │ │ │ │ ├── app/ │ │ │ │ │ ├── consumer-2.ts │ │ │ │ │ ├── consumer-3.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── pkg/ │ │ │ │ ├── internal/ │ │ │ │ │ └── consumer-1.ts │ │ │ │ ├── package.json │ │ │ │ └── public/ │ │ │ │ ├── barrel.ts │ │ │ │ └── implementation.ts │ │ │ ├── skip-exports-analysis/ │ │ │ │ ├── e2e/ │ │ │ │ │ └── used.e2e.js │ │ │ │ ├── lib/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── used.js │ │ │ │ │ └── used.test.js │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── index.js │ │ │ │ ├── used.js │ │ │ │ └── used.test.js │ │ │ ├── subpath-import/ │ │ │ │ ├── entry.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── dep-polyfill.d.ts │ │ │ │ │ └── dep-polyfill.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── subpath-import-from-plugin/ │ │ │ │ ├── .eslintrc.json │ │ │ │ ├── entry.ts │ │ │ │ ├── knip.json │ │ │ │ ├── lib/ │ │ │ │ │ ├── dep-polyfill.d.ts │ │ │ │ │ └── dep-polyfill.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── subpath-imports-outdir/ │ │ │ │ ├── dist/ │ │ │ │ │ └── src/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── index.js │ │ │ │ │ └── test/ │ │ │ │ │ ├── test1.d.ts │ │ │ │ │ ├── test1.js │ │ │ │ │ ├── test2.d.ts │ │ │ │ │ └── test2.js │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── test/ │ │ │ │ │ ├── test1.ts │ │ │ │ │ └── test2.ts │ │ │ │ └── tsconfig.json │ │ │ ├── subpath-patterns/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── entry.ts │ │ │ │ │ └── internals/ │ │ │ │ │ ├── unused.ts │ │ │ │ │ ├── used.alt │ │ │ │ │ ├── used.ext │ │ │ │ │ └── used.ts │ │ │ │ └── tsconfig.json │ │ │ ├── tagged-template-literal/ │ │ │ │ ├── Component.astro │ │ │ │ ├── ScriptTag.astro │ │ │ │ ├── app.ts │ │ │ │ ├── index.astro │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── tags-cli/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ ├── tags.ts │ │ │ │ └── unimported.ts │ │ │ ├── tags-exclude/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── tags.ts │ │ │ ├── tags-include/ │ │ │ │ ├── index.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── tags.ts │ │ │ ├── trace/ │ │ │ │ ├── barrel.ts │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ ├── package.json │ │ │ │ ├── require.ts │ │ │ │ ├── shared.ts │ │ │ │ └── string.ts │ │ │ ├── treat-config-hints-as-errors/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── treat-config-hints-as-errors2/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── ts-namespace/ │ │ │ │ ├── index.ts │ │ │ │ ├── members.ts │ │ │ │ ├── merged.ts │ │ │ │ ├── modules.ts │ │ │ │ ├── package.json │ │ │ │ └── types.ts │ │ │ ├── tsc-files-mode/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── declare-global.ts │ │ │ │ │ ├── declare-module.ts │ │ │ │ │ ├── excluded.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── module.ts │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-extends/ │ │ │ │ ├── boilerplate/ │ │ │ │ │ └── tsconfig.base.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── frontend/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.tsx │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-include-dir/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── helper.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.d.ts │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-nested-paths/ │ │ │ │ ├── package.json │ │ │ │ ├── shared/ │ │ │ │ │ └── utils.ts │ │ │ │ ├── src/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── handler.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── ui/ │ │ │ │ │ ├── button.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-paths-extends/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── cli.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── lib/ │ │ │ │ │ │ └── main.ts │ │ │ │ │ └── util/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tsconfig.base.json │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-preset-strict/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── tsconfig-rootdirs/ │ │ │ │ ├── generated/ │ │ │ │ │ └── src/ │ │ │ │ │ └── index.generated.ts │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tsconfig.json │ │ │ │ └── tsconfig.source.json │ │ │ ├── type-in-type/ │ │ │ │ ├── index.ts │ │ │ │ ├── module.ts │ │ │ │ ├── package.json │ │ │ │ └── types.ts │ │ │ ├── type-in-value-export/ │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── api.ts │ │ │ │ └── index.ts │ │ │ ├── types/ │ │ │ │ ├── index.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── url-import-meta-url/ │ │ │ │ ├── file.css │ │ │ │ ├── file.js │ │ │ │ ├── index.ts │ │ │ │ ├── knip.js │ │ │ │ └── package.json │ │ │ ├── workspaces/ │ │ │ │ ├── apps/ │ │ │ │ │ ├── backend/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── frontend/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── ignored-workspace/ │ │ │ │ │ └── package.json │ │ │ │ ├── docs/ │ │ │ │ │ ├── dangling.ts │ │ │ │ │ └── package.json │ │ │ │ ├── local/ │ │ │ │ │ └── tsconfig/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.base.json │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── shared/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ │ └── types.ts │ │ │ │ │ └── tools/ │ │ │ │ │ ├── ignored/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── utils.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-bun-test/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── lib/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tests/ │ │ │ │ │ └── index.test.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-circular/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── lib-a/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── lib-b/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── lib-c/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── workspaces-circular-symlinks/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── lib-a/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── lib-b/ │ │ │ │ ├── index.ts │ │ │ │ └── package.json │ │ │ ├── workspaces-cross-reference/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── lib-a/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── mod-a.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ └── lib-b/ │ │ │ │ ├── index.ts │ │ │ │ ├── mod-b.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-dts/ │ │ │ │ ├── .gitignore │ │ │ │ ├── knip.ts │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── client/ │ │ │ │ │ │ ├── client.d.ts │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── server/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ ├── server.d.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── shared/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── unused-function.js │ │ │ │ │ │ └── used-function.js │ │ │ │ │ ├── tsconfig.build.json │ │ │ │ │ └── tsconfig.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-entry-files/ │ │ │ │ ├── .storybook/ │ │ │ │ │ └── main.ts │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── client/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── index.stories.tsx │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── shared/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-ignored/ │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── a/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── b1/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── b2/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── c/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── d1/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── d2/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── deep/ │ │ │ │ │ │ ├── er/ │ │ │ │ │ │ │ └── h2/ │ │ │ │ │ │ │ └── package.json │ │ │ │ │ │ └── unignored/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── e/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── flat/ │ │ │ │ │ │ └── i1/ │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── g/ │ │ │ │ │ │ └── main.c │ │ │ │ │ └── production/ │ │ │ │ │ └── package.json │ │ │ │ └── pnpm-workspace.yaml │ │ │ ├── workspaces-include-entry-exports/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── app/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ └── lib/ │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── workspaces-module-resolution/ │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── workspace-a/ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ ├── src/ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── workspace-b/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── exports.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── self.ts │ │ │ │ │ │ └── used-fn.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-nested/ │ │ │ │ ├── L-1-1/ │ │ │ │ │ ├── L-1-2/ │ │ │ │ │ │ ├── L-1-3/ │ │ │ │ │ │ │ ├── .eslintrc.json │ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ │ └── package.json │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── package.json │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── package.json │ │ │ ├── workspaces-noconfig-plugin/ │ │ │ │ ├── lib/ │ │ │ │ │ ├── package.json │ │ │ │ │ └── src/ │ │ │ │ │ ├── util.test.ts │ │ │ │ │ └── util.ts │ │ │ │ ├── package.json │ │ │ │ └── src/ │ │ │ │ ├── index.ts │ │ │ │ └── util.test.ts │ │ │ ├── workspaces-node-test/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── lib/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tests/ │ │ │ │ │ └── index.test.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-paths/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── lib-a/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ │ └── module-a.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── same.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lib-b/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ │ └── module-b.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lib-c/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ │ └── module.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lib-d/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ │ └── module.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lib-e/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── dir/ │ │ │ │ │ │ │ └── module-e.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── lib-f/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── same.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── lib-g/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── same.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-paths-compilers/ │ │ │ │ ├── knip.ts │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ └── app/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ ├── components/ │ │ │ │ │ │ │ ├── App.vue │ │ │ │ │ │ │ ├── Child.vue │ │ │ │ │ │ │ └── Sub.vue │ │ │ │ │ │ ├── main.ts │ │ │ │ │ │ ├── pages/ │ │ │ │ │ │ │ └── Home.vue │ │ │ │ │ │ └── router.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-plugin-circular/ │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ └── lib/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── tsconfig.app.json │ │ │ │ │ ├── tsconfig.json │ │ │ │ │ └── tsconfig.spec.json │ │ │ │ └── tsconfig.base.json │ │ │ ├── workspaces-plugin-config/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── backend/ │ │ │ │ │ ├── config/ │ │ │ │ │ │ └── vitest.config.ts │ │ │ │ │ ├── eslint.config.js │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── index.vitest.ts │ │ │ │ │ ├── jest.config.js │ │ │ │ │ └── package.json │ │ │ │ ├── frontend/ │ │ │ │ │ ├── .eslintrc.js │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── component.js │ │ │ │ │ │ └── component.test.js │ │ │ │ │ ├── config/ │ │ │ │ │ │ └── vitest.config.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── index.vitest.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── postcss.config.js │ │ │ │ │ └── rollup.config.ts │ │ │ │ ├── shared/ │ │ │ │ │ ├── ava.config.js │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── component.ava.js │ │ │ │ │ │ ├── component.js │ │ │ │ │ │ ├── component.tales.js │ │ │ │ │ │ ├── epic/ │ │ │ │ │ │ │ ├── component.fable.tsx │ │ │ │ │ │ │ └── component.stories.mdx │ │ │ │ │ │ └── storybook/ │ │ │ │ │ │ ├── main.ts │ │ │ │ │ │ ├── manager.ts │ │ │ │ │ │ └── preview.ts │ │ │ │ │ ├── dev-entry.js │ │ │ │ │ ├── jest-setup.ts │ │ │ │ │ ├── package.json │ │ │ │ │ ├── production-entry.js │ │ │ │ │ └── webpack.config.js │ │ │ │ └── tailwind/ │ │ │ │ ├── package.json │ │ │ │ └── postcss.js │ │ │ ├── workspaces-plugin-overlap/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ └── workspace-a/ │ │ │ │ ├── package.json │ │ │ │ ├── tsconfig.json │ │ │ │ └── typedoc.json │ │ │ ├── workspaces-pnpm/ │ │ │ │ ├── apps/ │ │ │ │ │ ├── app-a/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── package.json │ │ │ │ │ └── app-b/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── docs/ │ │ │ │ │ ├── dangling.ts │ │ │ │ │ └── package.json │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── lib-a/ │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ └── package.json │ │ │ │ │ └── lib-b/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ └── pnpm-workspace.yaml │ │ │ ├── workspaces-root/ │ │ │ │ ├── app/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── package.json │ │ │ │ ├── scripts/ │ │ │ │ │ └── index.ts │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-self-and-cross-ref/ │ │ │ │ ├── .gitignore │ │ │ │ ├── package.json │ │ │ │ ├── packages/ │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ ├── src/ │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ ├── lib/ │ │ │ │ │ │ ├── package.json │ │ │ │ │ │ ├── src/ │ │ │ │ │ │ │ ├── alpha.ts │ │ │ │ │ │ │ ├── beta.ts │ │ │ │ │ │ │ └── index.ts │ │ │ │ │ │ └── tsconfig.json │ │ │ │ │ └── shared/ │ │ │ │ │ ├── package.json │ │ │ │ │ ├── src/ │ │ │ │ │ │ └── polyfills/ │ │ │ │ │ │ └── polyfills.client.ts │ │ │ │ │ └── tsconfig.json │ │ │ │ ├── pnpm-workspace.yaml │ │ │ │ ├── tsconfig.base.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-self-reference/ │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── eslint-config-x-self-reference/ │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── entry.ts │ │ │ │ │ ├── package.json │ │ │ │ │ └── tsconfig.json │ │ │ │ └── from-plugin/ │ │ │ │ ├── .eslintrc.json │ │ │ │ ├── data.json │ │ │ │ ├── entry.ts │ │ │ │ ├── file.js │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ ├── workspaces-tooling/ │ │ │ │ ├── knip.json │ │ │ │ ├── package.json │ │ │ │ └── packages/ │ │ │ │ ├── backend/ │ │ │ │ │ ├── .eslintrc.js │ │ │ │ │ ├── index.ts │ │ │ │ │ └── package.json │ │ │ │ ├── eslint-config-custom/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── package.json │ │ │ │ └── frontend/ │ │ │ │ ├── .eslintrc.js │ │ │ │ ├── index.ts │ │ │ │ ├── jest.config.js │ │ │ │ ├── jest.setup.js │ │ │ │ └── package.json │ │ │ ├── zero-config/ │ │ │ │ ├── exclude.ts │ │ │ │ ├── index.ts │ │ │ │ ├── my-module.ts │ │ │ │ ├── my-namespace.ts │ │ │ │ ├── package.json │ │ │ │ └── tsconfig.json │ │ │ └── מסמכים/ │ │ │ ├── .gitignore │ │ │ ├── package.json │ │ │ └── src/ │ │ │ └── index.ts │ │ ├── package.json │ │ ├── rmdir.js │ │ ├── schema-jsonc.json │ │ ├── schema.json │ │ ├── scripts/ │ │ │ ├── create-new-plugin.ts │ │ │ ├── generate-plugin-defs.js │ │ │ ├── run-test.ts │ │ │ ├── tsconfig.json │ │ │ └── verify-fixtures.ts │ │ ├── src/ │ │ │ ├── CacheConsultant.ts │ │ │ ├── CatalogCounselor.ts │ │ │ ├── ConfigurationChief.ts │ │ │ ├── ConsoleStreamer.ts │ │ │ ├── DependencyDeputy.ts │ │ │ ├── IssueCollector.ts │ │ │ ├── IssueFixer.ts │ │ │ ├── JsonCatalogPeeker.ts │ │ │ ├── PackagePeeker.ts │ │ │ ├── ProjectPrincipal.ts │ │ │ ├── WorkspaceWorker.ts │ │ │ ├── YamlCatalogPeeker.ts │ │ │ ├── binaries/ │ │ │ │ ├── bash-parser.ts │ │ │ │ ├── fallback.ts │ │ │ │ ├── index.ts │ │ │ │ ├── plugins.ts │ │ │ │ ├── resolvers/ │ │ │ │ │ ├── bun.ts │ │ │ │ │ ├── bunx.ts │ │ │ │ │ ├── find.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── npm.ts │ │ │ │ │ ├── npx.ts │ │ │ │ │ ├── pnpm.ts │ │ │ │ │ ├── pnpx.ts │ │ │ │ │ └── yarn.ts │ │ │ │ └── util.ts │ │ │ ├── cli.ts │ │ │ ├── compilers/ │ │ │ │ ├── compilers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── mdx.ts │ │ │ │ ├── scss.ts │ │ │ │ └── types.ts │ │ │ ├── constants.ts │ │ │ ├── graph/ │ │ │ │ ├── analyze.ts │ │ │ │ └── build.ts │ │ │ ├── graph-explorer/ │ │ │ │ ├── cache.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── explorer.ts │ │ │ │ ├── operations/ │ │ │ │ │ ├── build-exports-tree.ts │ │ │ │ │ ├── find-cycles.ts │ │ │ │ │ ├── get-contention.ts │ │ │ │ │ ├── get-dependency-usage.ts │ │ │ │ │ ├── get-usage.ts │ │ │ │ │ ├── has-strictly-ns-references.ts │ │ │ │ │ ├── is-referenced.ts │ │ │ │ │ └── resolve-definition.ts │ │ │ │ ├── utils.ts │ │ │ │ ├── visitors.ts │ │ │ │ ├── walk-down.ts │ │ │ │ └── walk-up.ts │ │ │ ├── index.ts │ │ │ ├── manifest/ │ │ │ │ ├── helpers.ts │ │ │ │ └── index.ts │ │ │ ├── plugins/ │ │ │ │ ├── _template/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── angular/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── update-types.sh │ │ │ │ ├── astro/ │ │ │ │ │ ├── compiler-mdx.ts │ │ │ │ │ ├── compiler.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── astro-db/ │ │ │ │ │ └── index.ts │ │ │ │ ├── astro-og-canvas/ │ │ │ │ │ └── index.ts │ │ │ │ ├── ava/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── babel/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── biome/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── bumpp/ │ │ │ │ │ └── index.ts │ │ │ │ ├── bun/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── c8/ │ │ │ │ │ └── index.ts │ │ │ │ ├── capacitor/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── changelogen/ │ │ │ │ │ └── index.ts │ │ │ │ ├── changelogithub/ │ │ │ │ │ └── index.ts │ │ │ │ ├── changesets/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── commitizen/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── commitlint/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── convex/ │ │ │ │ │ └── index.ts │ │ │ │ ├── create-typescript-app/ │ │ │ │ │ └── index.ts │ │ │ │ ├── cspell/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── cucumber/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── cypress/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── danger/ │ │ │ │ │ └── index.ts │ │ │ │ ├── dependency-cruiser/ │ │ │ │ │ └── index.ts │ │ │ │ ├── docusaurus/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── dotenv/ │ │ │ │ │ └── index.ts │ │ │ │ ├── drizzle/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── eleventy/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── eslint/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── resolveFromAST.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── execa/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── visitors/ │ │ │ │ │ └── execa.ts │ │ │ │ ├── expo/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── expressive-code/ │ │ │ │ │ └── index.ts │ │ │ │ ├── gatsby/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── github-action/ │ │ │ │ │ └── index.ts │ │ │ │ ├── github-actions/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── glob/ │ │ │ │ │ └── index.ts │ │ │ │ ├── graphql-codegen/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── hardhat/ │ │ │ │ │ └── index.ts │ │ │ │ ├── husky/ │ │ │ │ │ └── index.ts │ │ │ │ ├── i18next-parser/ │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── jest/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── karma/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── knex/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── ladle/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── lefthook/ │ │ │ │ │ └── index.ts │ │ │ │ ├── lint-staged/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── linthtml/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── lockfile-lint/ │ │ │ │ │ └── index.ts │ │ │ │ ├── lost-pixel/ │ │ │ │ │ └── index.ts │ │ │ │ ├── markdownlint/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── mdx/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── mdxlint/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── metro/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── mocha/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── moonrepo/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── msw/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── nano-staged/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── nest/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── netlify/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── next/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── next-intl/ │ │ │ │ │ └── index.ts │ │ │ │ ├── next-mdx/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── nitro/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── node/ │ │ │ │ │ └── index.ts │ │ │ │ ├── node-modules-inspector/ │ │ │ │ │ └── index.ts │ │ │ │ ├── nodemon/ │ │ │ │ │ └── index.ts │ │ │ │ ├── npm-package-json-lint/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── nuxt/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── nx/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── nyc/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── oclif/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── openapi-ts/ │ │ │ │ │ └── index.ts │ │ │ │ ├── oxfmt/ │ │ │ │ │ └── index.ts │ │ │ │ ├── oxlint/ │ │ │ │ │ └── index.ts │ │ │ │ ├── parcel/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── payload/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── playwright/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── playwright-ct/ │ │ │ │ │ └── index.ts │ │ │ │ ├── playwright-test/ │ │ │ │ │ └── index.ts │ │ │ │ ├── plop/ │ │ │ │ │ └── index.ts │ │ │ │ ├── pm2/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── pnpm/ │ │ │ │ │ └── index.ts │ │ │ │ ├── postcss/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── preconstruct/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── prettier/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── prisma/ │ │ │ │ │ ├── compiler.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── qwik/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── raycast/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── react-cosmos/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── react-native/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── react-router/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── relay/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── release-it/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── remark/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── remix/ │ │ │ │ │ └── index.ts │ │ │ │ ├── rollup/ │ │ │ │ │ └── index.ts │ │ │ │ ├── rsbuild/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── rslib/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── rspack/ │ │ │ │ │ └── index.ts │ │ │ │ ├── rstest/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── sanity/ │ │ │ │ │ └── index.ts │ │ │ │ ├── semantic-release/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── sentry/ │ │ │ │ │ └── index.ts │ │ │ │ ├── simple-git-hooks/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── size-limit/ │ │ │ │ │ └── index.ts │ │ │ │ ├── sst/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── starlight/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── resolveFromAST.ts │ │ │ │ ├── storybook/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── stryker/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── stylelint/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── svelte/ │ │ │ │ │ ├── compiler.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── sveltekit/ │ │ │ │ │ └── index.ts │ │ │ │ ├── svgo/ │ │ │ │ │ └── index.ts │ │ │ │ ├── svgr/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── swc/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── syncpack/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tailwind/ │ │ │ │ │ ├── compiler.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── tanstack-router/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── taskfile/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── travis/ │ │ │ │ │ └── index.ts │ │ │ │ ├── ts-node/ │ │ │ │ │ └── index.ts │ │ │ │ ├── tsdown/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── resolveFromAST.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── tsup/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── resolveFromAST.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── tsx/ │ │ │ │ │ └── index.ts │ │ │ │ ├── typedoc/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── typescript/ │ │ │ │ │ └── index.ts │ │ │ │ ├── unbuild/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── unocss/ │ │ │ │ │ └── index.ts │ │ │ │ ├── vercel-og/ │ │ │ │ │ └── index.ts │ │ │ │ ├── vike/ │ │ │ │ │ └── index.ts │ │ │ │ ├── vite/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── visitors/ │ │ │ │ │ └── importMetaGlob.ts │ │ │ │ ├── vitepress/ │ │ │ │ │ └── index.ts │ │ │ │ ├── vitest/ │ │ │ │ │ ├── helpers.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── vue/ │ │ │ │ │ ├── compiler.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── webdriver-io/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── webpack/ │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── visitors/ │ │ │ │ │ └── requireContext.ts │ │ │ │ ├── wireit/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── wrangler/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── xo/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── yarn/ │ │ │ │ │ └── index.ts │ │ │ │ ├── yorkie/ │ │ │ │ │ └── index.ts │ │ │ │ └── zx/ │ │ │ │ ├── index.ts │ │ │ │ └── visitors/ │ │ │ │ └── zx.ts │ │ │ ├── plugins.ts │ │ │ ├── reporters/ │ │ │ │ ├── codeclimate.ts │ │ │ │ ├── codeowners.ts │ │ │ │ ├── compact.ts │ │ │ │ ├── disclosure.ts │ │ │ │ ├── github-actions.ts │ │ │ │ ├── index.ts │ │ │ │ ├── json.ts │ │ │ │ ├── markdown.ts │ │ │ │ ├── symbols.ts │ │ │ │ ├── trace.ts │ │ │ │ ├── util/ │ │ │ │ │ ├── configuration-hints.ts │ │ │ │ │ └── util.ts │ │ │ │ └── watch.ts │ │ │ ├── run.ts │ │ │ ├── schema/ │ │ │ │ ├── configuration.ts │ │ │ │ └── plugins.ts │ │ │ ├── session/ │ │ │ │ ├── build-maps.ts │ │ │ │ ├── file-descriptor.ts │ │ │ │ ├── index.ts │ │ │ │ ├── package-json-descriptor.ts │ │ │ │ ├── session.ts │ │ │ │ └── types.ts │ │ │ ├── types/ │ │ │ │ ├── PluginNames.ts │ │ │ │ ├── args.ts │ │ │ │ ├── config.ts │ │ │ │ ├── entries.ts │ │ │ │ ├── exports.ts │ │ │ │ ├── issues.ts │ │ │ │ ├── module-graph.ts │ │ │ │ ├── options.ts │ │ │ │ ├── package-json.ts │ │ │ │ ├── project.ts │ │ │ │ ├── tsconfig-json.ts │ │ │ │ └── workspace.ts │ │ │ ├── types.ts │ │ │ ├── typescript/ │ │ │ │ ├── SourceFileManager.ts │ │ │ │ ├── ast-helpers.ts │ │ │ │ ├── follow-imports.ts │ │ │ │ ├── get-imports-and-exports.ts │ │ │ │ ├── resolve-module-names.ts │ │ │ │ └── visitors/ │ │ │ │ ├── calls.ts │ │ │ │ ├── exports.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── imports.ts │ │ │ │ ├── jsdoc.ts │ │ │ │ ├── local-refs.ts │ │ │ │ ├── members.ts │ │ │ │ ├── script-visitors.ts │ │ │ │ └── walk.ts │ │ │ ├── util/ │ │ │ │ ├── Performance.ts │ │ │ │ ├── array.ts │ │ │ │ ├── catalog.ts │ │ │ │ ├── cli-arguments.ts │ │ │ │ ├── codeowners.ts │ │ │ │ ├── create-input-handler.ts │ │ │ │ ├── create-options.ts │ │ │ │ ├── create-workspace-graph.ts │ │ │ │ ├── debug.ts │ │ │ │ ├── empty.ts │ │ │ │ ├── errors.ts │ │ │ │ ├── file-entry-cache.ts │ │ │ │ ├── fs.ts │ │ │ │ ├── get-included-issue-types.ts │ │ │ │ ├── git.ts │ │ │ │ ├── glob-core.ts │ │ │ │ ├── glob.ts │ │ │ │ ├── graph-sequencer.ts │ │ │ │ ├── input.ts │ │ │ │ ├── issue-initializers.ts │ │ │ │ ├── jiti.ts │ │ │ │ ├── load-config.ts │ │ │ │ ├── load-tsconfig.ts │ │ │ │ ├── loader.ts │ │ │ │ ├── log.ts │ │ │ │ ├── map-workspaces.ts │ │ │ │ ├── math.ts │ │ │ │ ├── module-graph.ts │ │ │ │ ├── modules.ts │ │ │ │ ├── object.ts │ │ │ │ ├── package-json.ts │ │ │ │ ├── package-name.ts │ │ │ │ ├── parse-and-convert-gitignores.ts │ │ │ │ ├── path.ts │ │ │ │ ├── plugin-config.ts │ │ │ │ ├── plugin.ts │ │ │ │ ├── regex.ts │ │ │ │ ├── remove-export.ts │ │ │ │ ├── reporter.ts │ │ │ │ ├── require.ts │ │ │ │ ├── resolve.ts │ │ │ │ ├── string.ts │ │ │ │ ├── table.ts │ │ │ │ ├── tag.ts │ │ │ │ ├── to-source-path.ts │ │ │ │ ├── trace.ts │ │ │ │ ├── watch.ts │ │ │ │ ├── workspace-file-filter.ts │ │ │ │ ├── workspace-selectors.ts │ │ │ │ └── workspace.ts │ │ │ └── version.ts │ │ ├── test/ │ │ │ ├── barrel-namespace-chain.test.ts │ │ │ ├── catalog.empty.test.ts │ │ │ ├── catalog.package-json.test.ts │ │ │ ├── catalog.pnpm.test.ts │ │ │ ├── catalog.yarn.test.ts │ │ │ ├── cli/ │ │ │ │ ├── cli-config.test.ts │ │ │ │ ├── cli-include.test.ts │ │ │ │ ├── cli-preprocessor.test.ts │ │ │ │ ├── cli-reporter-codeclimate.test.ts │ │ │ │ ├── cli-reporter-codeclimate2.test.ts │ │ │ │ ├── cli-reporter-codeclimate3.test.ts │ │ │ │ ├── cli-reporter-codeclimate4.test.ts │ │ │ │ ├── cli-reporter-compact.test.ts │ │ │ │ ├── cli-reporter-github-actions.test.ts │ │ │ │ ├── cli-reporter-json-catalog.test.ts │ │ │ │ ├── cli-reporter-json.test.ts │ │ │ │ ├── cli-reporter-json2.test.ts │ │ │ │ ├── cli-reporter-json3.test.ts │ │ │ │ ├── cli-reporter-json4.test.ts │ │ │ │ ├── cli-reporter-markdown.test.ts │ │ │ │ ├── cli-reporter-symbols-catalog.test.ts │ │ │ │ ├── cli-reporter-symbols-pathlike.test.ts │ │ │ │ ├── cli-reporter.test.ts │ │ │ │ ├── cli-trace.test.ts │ │ │ │ ├── cli-treat-config-hints-as-errors.test.ts │ │ │ │ └── cli.test.ts │ │ │ ├── commonjs-tsconfig.test.ts │ │ │ ├── commonjs.test.ts │ │ │ ├── compilers.manual.test.ts │ │ │ ├── compilers.prisma.test.ts │ │ │ ├── compilers.scss.test.ts │ │ │ ├── compilers.tailwind.test.ts │ │ │ ├── compilers.test.ts │ │ │ ├── configuration-hints.test.ts │ │ │ ├── configuration-hints2.test.ts │ │ │ ├── cross-workspace-inputs.test.ts │ │ │ ├── custom-paths-workspaces.test.ts │ │ │ ├── definitely-typed.test.ts │ │ │ ├── dependencies-types.test.ts │ │ │ ├── dependencies.test.ts │ │ │ ├── dts-baseurl-implicit-relative.test.ts │ │ │ ├── dts-compiled.test.ts │ │ │ ├── dts.test.ts │ │ │ ├── duplicate-dependencies.test.ts │ │ │ ├── duplicate-exports-alias.test.ts │ │ │ ├── empty-main.test.ts │ │ │ ├── entry-exports-enum-members.test.ts │ │ │ ├── entry-exports-namespace.test.ts │ │ │ ├── entry-files.test.ts │ │ │ ├── entry-js.test.ts │ │ │ ├── enum-members-enumerated.test.ts │ │ │ ├── enum-members.test.ts │ │ │ ├── export-spread.test.ts │ │ │ ├── exports-default-interface.test.ts │ │ │ ├── exports-default-type.test.ts │ │ │ ├── exports-special-characters.test.ts │ │ │ ├── exports-value-refs-default.test.ts │ │ │ ├── exports-value-refs.test.ts │ │ │ ├── exports.test.ts │ │ │ ├── extensions-css-ts.test.ts │ │ │ ├── fix/ │ │ │ │ ├── fix-catalog-json-root.test.ts │ │ │ │ ├── fix-catalog-json.test.ts │ │ │ │ ├── fix-catalog-yaml.test.ts │ │ │ │ ├── fix-exclude-dependencies.test.ts │ │ │ │ ├── fix-members.test.ts │ │ │ │ ├── fix-workspaces.test.ts │ │ │ │ ├── fix.test.ts │ │ │ │ └── format.test.ts │ │ │ ├── git-branch-file.test.ts │ │ │ ├── gitignore.test.ts │ │ │ ├── graph-explorer/ │ │ │ │ ├── contention.test.ts │ │ │ │ ├── cycles.test.ts │ │ │ │ ├── trace-export.test.ts │ │ │ │ ├── walk-down.test.ts │ │ │ │ └── walk-up.test.ts │ │ │ ├── helpers/ │ │ │ │ ├── assertAndRemoveProperty.ts │ │ │ │ ├── baseCounters.ts │ │ │ │ ├── baseNodeObjects.ts │ │ │ │ ├── copy-fixture.ts │ │ │ │ ├── create-options.ts │ │ │ │ ├── diff.ts │ │ │ │ ├── exec.ts │ │ │ │ └── resolve.ts │ │ │ ├── ignore-dependencies-binaries-json.test.ts │ │ │ ├── ignore-dependencies-binaries.test.ts │ │ │ ├── ignore-exports-used-in-file-alias-exclude.test.ts │ │ │ ├── ignore-exports-used-in-file-id-chars.test.ts │ │ │ ├── ignore-exports-used-in-file-id-underscores.test.ts │ │ │ ├── ignore-exports-used-in-file-re-export.test.ts │ │ │ ├── ignore-exports-used-in-file-shorthand.test.ts │ │ │ ├── ignore-exports-used-in-file-some.test.ts │ │ │ ├── ignore-exports-used-in-file-typeof-class.test.ts │ │ │ ├── ignore-exports-used-in-file.test.ts │ │ │ ├── ignore-files.test.ts │ │ │ ├── ignore-issues.test.ts │ │ │ ├── ignore-members.test.ts │ │ │ ├── ignore-negated.test.ts │ │ │ ├── ignore-patterns.test.ts │ │ │ ├── ignore-unresolved.test.ts │ │ │ ├── ignore-unresolved2.test.ts │ │ │ ├── import-equals.test.ts │ │ │ ├── import-errors.test.ts │ │ │ ├── import-meta-glob.test.ts │ │ │ ├── import-named-default-id.test.ts │ │ │ ├── import-star-iteration.test.ts │ │ │ ├── imports-destructure-spread.test.ts │ │ │ ├── imports-dynamic-access.test.ts │ │ │ ├── imports-namespace-jsx.test.ts │ │ │ ├── imports-namespace-with-nsexports.test.ts │ │ │ ├── imports-namespace.test.ts │ │ │ ├── imports-opaque.test.ts │ │ │ ├── imports-prop-access-call.test.ts │ │ │ ├── imports-self.test.ts │ │ │ ├── imports-typeof.test.ts │ │ │ ├── imports.test.ts │ │ │ ├── include-entry-exports-scripts.test.ts │ │ │ ├── include-entry-exports.test.ts │ │ │ ├── include-entry-reexports.test.ts │ │ │ ├── include-libs.test.ts │ │ │ ├── js-only.test.ts │ │ │ ├── jsdoc-exports.test.ts │ │ │ ├── jsdoc.test.ts │ │ │ ├── jsx.test.ts │ │ │ ├── module-block.test.ts │ │ │ ├── module-register.test.ts │ │ │ ├── module-resolution-baseurl-implicit-relative.test.ts │ │ │ ├── module-resolution-non-std-absolute.test.ts │ │ │ ├── module-resolution-non-std-implicit.test.ts │ │ │ ├── module-resolution-non-std.test.ts │ │ │ ├── module-resolution-tsconfig-paths.test.ts │ │ │ ├── negated-production-paths.test.ts │ │ │ ├── npm-scripts.test.ts │ │ │ ├── ns-spread-reexport.test.ts │ │ │ ├── package-entry-points.test.ts │ │ │ ├── path-aliases.test.ts │ │ │ ├── path-aliases2.test.ts │ │ │ ├── pathless.test.ts │ │ │ ├── peer-dependencies-circular.test.ts │ │ │ ├── peer-dependencies-optional-host.test.ts │ │ │ ├── peer-dependencies-optional-ignored.test.ts │ │ │ ├── peer-dependencies-optional-strict.test.ts │ │ │ ├── peer-dependencies-optional.test.ts │ │ │ ├── peer-dependencies.test.ts │ │ │ ├── plugin-config.test.ts │ │ │ ├── plugin-disable.test.ts │ │ │ ├── plugin-negated-entry-globs.test.ts │ │ │ ├── plugin-overlap.test.ts │ │ │ ├── plugins/ │ │ │ │ ├── _template.test.ts │ │ │ │ ├── angular.test.ts │ │ │ │ ├── angular2.test.ts │ │ │ │ ├── angular3.test.ts │ │ │ │ ├── astro-db.test.ts │ │ │ │ ├── astro-og-canvas.test.ts │ │ │ │ ├── astro-sharp-image-service.test.ts │ │ │ │ ├── astro.test.ts │ │ │ │ ├── ava.test.ts │ │ │ │ ├── ava2.test.ts │ │ │ │ ├── ava3.test.ts │ │ │ │ ├── babel.test.ts │ │ │ │ ├── biome-workspace.test.ts │ │ │ │ ├── biome.test.ts │ │ │ │ ├── bumpp.test.ts │ │ │ │ ├── bun.test.ts │ │ │ │ ├── bun2.test.ts │ │ │ │ ├── bun3.test.ts │ │ │ │ ├── bun4.test.ts │ │ │ │ ├── capacitor.test.ts │ │ │ │ ├── changelogen.test.ts │ │ │ │ ├── changelogithub.test.ts │ │ │ │ ├── changesets.test.ts │ │ │ │ ├── commitizen.test.ts │ │ │ │ ├── commitlint.test.ts │ │ │ │ ├── convex.test.ts │ │ │ │ ├── create-typescript-app.test.ts │ │ │ │ ├── cspell.test.ts │ │ │ │ ├── cucumber.test.ts │ │ │ │ ├── cypress-multi-reporter.test.ts │ │ │ │ ├── cypress.test.ts │ │ │ │ ├── cypress2.test.ts │ │ │ │ ├── danger.test.ts │ │ │ │ ├── dependency-cruiser.test.ts │ │ │ │ ├── docusaurus.test.ts │ │ │ │ ├── drizzle.test.ts │ │ │ │ ├── eleventy.test.ts │ │ │ │ ├── eleventy2.test.ts │ │ │ │ ├── eleventy3.test.ts │ │ │ │ ├── eleventy4.test.ts │ │ │ │ ├── eslint.test.ts │ │ │ │ ├── eslint2.test.ts │ │ │ │ ├── eslint3.test.ts │ │ │ │ ├── eslint4.test.ts │ │ │ │ ├── eslint5.test.ts │ │ │ │ ├── expo.test.ts │ │ │ │ ├── expo2.test.ts │ │ │ │ ├── expo3.test.ts │ │ │ │ ├── expressive-code.test.ts │ │ │ │ ├── fooi.test.ts │ │ │ │ ├── gatsby.test.ts │ │ │ │ ├── github-action.test.ts │ │ │ │ ├── github-actions-workspaces.test.ts │ │ │ │ ├── github-actions.test.ts │ │ │ │ ├── graphql-codegen-graphql-config.test.ts │ │ │ │ ├── graphql-codegen-graphql-config2.test.ts │ │ │ │ ├── graphql-codegen.test.ts │ │ │ │ ├── hardhat.test.ts │ │ │ │ ├── husky-legacy.test.ts │ │ │ │ ├── husky-v8.test.ts │ │ │ │ ├── husky-v9-1.test.ts │ │ │ │ ├── husky-v9.test.ts │ │ │ │ ├── i18next-parser.test.ts │ │ │ │ ├── jest.test.ts │ │ │ │ ├── jest2.test.ts │ │ │ │ ├── jest3.test.ts │ │ │ │ ├── karma.test.ts │ │ │ │ ├── karma2.test.ts │ │ │ │ ├── karma3.test.ts │ │ │ │ ├── knex.test.ts │ │ │ │ ├── ladle.test.ts │ │ │ │ ├── lefthook-ci.test.ts │ │ │ │ ├── lefthook-v1.test.ts │ │ │ │ ├── lefthook.test.ts │ │ │ │ ├── lint-staged.test.ts │ │ │ │ ├── linthtml.test.ts │ │ │ │ ├── lockfile-lint.test.ts │ │ │ │ ├── lost-pixel.test.ts │ │ │ │ ├── markdownlint.test.ts │ │ │ │ ├── mdx.test.ts │ │ │ │ ├── mdxlint.test.ts │ │ │ │ ├── metro-defaults.test.ts │ │ │ │ ├── metro-react-native.test.ts │ │ │ │ ├── metro.test.ts │ │ │ │ ├── mocha.test.ts │ │ │ │ ├── moonrepo.test.ts │ │ │ │ ├── msw.test.ts │ │ │ │ ├── nano-staged.test.ts │ │ │ │ ├── nest.test.ts │ │ │ │ ├── netlify.test.ts │ │ │ │ ├── next-intl.test.ts │ │ │ │ ├── next-mdx.test.ts │ │ │ │ ├── next-middleware.test.ts │ │ │ │ ├── next-page-extensions.test.ts │ │ │ │ ├── next.test.ts │ │ │ │ ├── nitro.test.ts │ │ │ │ ├── node-modules-inspector.test.ts │ │ │ │ ├── node-test-runner.test.ts │ │ │ │ ├── node.test.ts │ │ │ │ ├── nodemon.test.ts │ │ │ │ ├── npm-package-json-lint.test.ts │ │ │ │ ├── nuxt-auto-import-disabled.test.ts │ │ │ │ ├── nuxt-auto-import.test.ts │ │ │ │ ├── nuxt-config.test.ts │ │ │ │ ├── nuxt.test.ts │ │ │ │ ├── nx-crystal.test.ts │ │ │ │ ├── nx.test.ts │ │ │ │ ├── nyc.test.ts │ │ │ │ ├── oclif.test.ts │ │ │ │ ├── openapi-ts.test.ts │ │ │ │ ├── oxfmt.test.ts │ │ │ │ ├── oxlint.test.ts │ │ │ │ ├── parcel.test.ts │ │ │ │ ├── payload.test.ts │ │ │ │ ├── playwright-ct.test.ts │ │ │ │ ├── playwright-ct2.test.ts │ │ │ │ ├── playwright.test.ts │ │ │ │ ├── playwright2.test.ts │ │ │ │ ├── plop.test.ts │ │ │ │ ├── pm2.test.ts │ │ │ │ ├── pnpm.test.ts │ │ │ │ ├── pnpm2.test.ts │ │ │ │ ├── postcss-cjs.test.ts │ │ │ │ ├── postcss-next.test.ts │ │ │ │ ├── postcss-tailwindcss.test.ts │ │ │ │ ├── postcss-tailwindcss2.test.ts │ │ │ │ ├── postcss.test.ts │ │ │ │ ├── preconstruct.test.ts │ │ │ │ ├── prettier-re-exports.test.ts │ │ │ │ ├── prettier.test.ts │ │ │ │ ├── prisma.test.ts │ │ │ │ ├── prisma2.test.ts │ │ │ │ ├── qwik.test.ts │ │ │ │ ├── raycast.test.ts │ │ │ │ ├── react-cosmos.test.ts │ │ │ │ ├── react-native.test.ts │ │ │ │ ├── react-router.test.ts │ │ │ │ ├── relay.test.ts │ │ │ │ ├── relay2.test.ts │ │ │ │ ├── release-it.test.ts │ │ │ │ ├── remark.test.ts │ │ │ │ ├── remix.test.ts │ │ │ │ ├── rollup.test.ts │ │ │ │ ├── rsbuild.test.ts │ │ │ │ ├── rslib.test.ts │ │ │ │ ├── rspack.test.ts │ │ │ │ ├── rstest.test.ts │ │ │ │ ├── rstest2.test.ts │ │ │ │ ├── sanity.test.ts │ │ │ │ ├── semantic-release.test.ts │ │ │ │ ├── sentry.test.ts │ │ │ │ ├── simple-git-hooks.test.ts │ │ │ │ ├── size-limit.test.ts │ │ │ │ ├── sst.test.ts │ │ │ │ ├── sst2.test.ts │ │ │ │ ├── starlight.test.ts │ │ │ │ ├── storybook.test.ts │ │ │ │ ├── storybook2.test.ts │ │ │ │ ├── stryker.test.ts │ │ │ │ ├── stylelint.test.ts │ │ │ │ ├── stylelint2.test.ts │ │ │ │ ├── stylelint3.test.ts │ │ │ │ ├── svelte.test.ts │ │ │ │ ├── sveltekit.test.ts │ │ │ │ ├── svgo.test.ts │ │ │ │ ├── svgr.test.ts │ │ │ │ ├── swc.test.ts │ │ │ │ ├── syncpack.test.ts │ │ │ │ ├── tailwind.test.ts │ │ │ │ ├── tailwind2.test.ts │ │ │ │ ├── tanstack-router.test.ts │ │ │ │ ├── taskfile.test.ts │ │ │ │ ├── taskfile2.test.ts │ │ │ │ ├── travis.test.ts │ │ │ │ ├── tsdown.test.ts │ │ │ │ ├── tsgo.test.ts │ │ │ │ ├── tsup.test.ts │ │ │ │ ├── tsx.test.ts │ │ │ │ ├── typedoc.test.ts │ │ │ │ ├── typescript.test.ts │ │ │ │ ├── typescript2.test.ts │ │ │ │ ├── unbuild.test.ts │ │ │ │ ├── unocss.test.ts │ │ │ │ ├── vercel-og.test.ts │ │ │ │ ├── vike.test.ts │ │ │ │ ├── vite.test.ts │ │ │ │ ├── vite2.test.ts │ │ │ │ ├── vite3.test.ts │ │ │ │ ├── vite4.test.ts │ │ │ │ ├── vitepress.test.ts │ │ │ │ ├── vitest-npm-script.test.ts │ │ │ │ ├── vitest.test.ts │ │ │ │ ├── vitest2.test.ts │ │ │ │ ├── vitest3.test.ts │ │ │ │ ├── vitest4.test.ts │ │ │ │ ├── vitest5.test.ts │ │ │ │ ├── vitest6.test.ts │ │ │ │ ├── vitest7.test.ts │ │ │ │ ├── vitest8.test.ts │ │ │ │ ├── vitest9.test.ts │ │ │ │ ├── vue-webpack.test.ts │ │ │ │ ├── vue.test.ts │ │ │ │ ├── webdriver-io.test.ts │ │ │ │ ├── webpack-cli.test.ts │ │ │ │ ├── webpack-re-exports.test.ts │ │ │ │ ├── webpack.test.ts │ │ │ │ ├── webpack2.test.ts │ │ │ │ ├── wireit.test.ts │ │ │ │ ├── wrangler.test.ts │ │ │ │ ├── xo.test.ts │ │ │ │ ├── yarn-berry.test.ts │ │ │ │ ├── yarn.test.ts │ │ │ │ └── yorkie.test.ts │ │ │ ├── pragma.test.ts │ │ │ ├── re-exports-aliased-ns.test.ts │ │ │ ├── re-exports-cjs.test.ts │ │ │ ├── re-exports-deep.test.ts │ │ │ ├── re-exports-default-renamed-deep.test.ts │ │ │ ├── re-exports-default-renamed.test.ts │ │ │ ├── re-exports-destructure-spread.test.ts │ │ │ ├── re-exports-enum-members-workspace.test.ts │ │ │ ├── re-exports-enum-unused.test.ts │ │ │ ├── re-exports-enum.test.ts │ │ │ ├── re-exports-export-declaration.test.ts │ │ │ ├── re-exports-export-ns.test.ts │ │ │ ├── re-exports-ignore-exports-used-in-file.test.ts │ │ │ ├── re-exports-ns-member.test.ts │ │ │ ├── re-exports-pseudo.test.ts │ │ │ ├── re-exports-public.test.ts │ │ │ ├── re-exports-recursive.test.ts │ │ │ ├── re-exports-renamed.test.ts │ │ │ ├── re-exports-spread.test.ts │ │ │ ├── re-exports-twice.test.ts │ │ │ ├── re-exports-with-decorator.test.ts │ │ │ ├── re-exports.test.ts │ │ │ ├── rules.test.ts │ │ │ ├── script-visitors-bun.test.ts │ │ │ ├── script-visitors-execa.test.ts │ │ │ ├── script-visitors-zx.test.ts │ │ │ ├── self-reference-from-plugin.test.ts │ │ │ ├── self-reference.test.ts │ │ │ ├── session/ │ │ │ │ ├── session.contention.test.ts │ │ │ │ ├── session.file-changes.test.ts │ │ │ │ ├── session.re-exports.test.ts │ │ │ │ ├── session.test.ts │ │ │ │ └── util.ts │ │ │ ├── session-dependencies.test.ts │ │ │ ├── skip-exports-analysis.test.ts │ │ │ ├── subpath-import-from-plugin.test.ts │ │ │ ├── subpath-import.test.ts │ │ │ ├── subpath-imports-outdir.test.ts │ │ │ ├── subpath-patterns.test.ts │ │ │ ├── tagged-template-literal.test.ts │ │ │ ├── tags-cli.test.ts │ │ │ ├── tags-exclude.test.ts │ │ │ ├── tags-include.test.ts │ │ │ ├── ts-namespace.test.ts │ │ │ ├── tsc-files-mode.test.ts │ │ │ ├── tsconfig-extends.test.ts │ │ │ ├── tsconfig-include-dir.test.ts │ │ │ ├── tsconfig-nested-paths.test.ts │ │ │ ├── tsconfig-paths-extends.test.ts │ │ │ ├── tsconfig-preset-strict.test.ts │ │ │ ├── tsconfig-rootdirs.test.ts │ │ │ ├── tsconfig.json │ │ │ ├── type-in-type.test.ts │ │ │ ├── type-in-value-export.test.ts │ │ │ ├── types.test.ts │ │ │ ├── unresolved-rtl.test.ts │ │ │ ├── url-import-meta-url.test.ts │ │ │ ├── util/ │ │ │ │ ├── codeowners.test.ts │ │ │ │ ├── convert-gitignore-patterns.test.ts │ │ │ │ ├── find-and-parse-gitignores.test.ts │ │ │ │ ├── get-included-issue-types.test.ts │ │ │ │ ├── get-inputs-from-scripts.test.ts │ │ │ │ ├── graph-sequencer.test.ts │ │ │ │ ├── has-strictly-ns-references.test.ts │ │ │ │ ├── load.test.ts │ │ │ │ ├── modules.test.ts │ │ │ │ ├── remove-export.test.ts │ │ │ │ ├── serialize.test.ts │ │ │ │ ├── string.test.ts │ │ │ │ ├── table.test.ts │ │ │ │ ├── workspace-selectors.test.ts │ │ │ │ └── workspace.test.ts │ │ │ ├── workspace-selectors-errors.test.ts │ │ │ ├── workspace-selectors-root.test.ts │ │ │ ├── workspace-selectors.test.ts │ │ │ ├── workspaces-circular-symlinks.test.ts │ │ │ ├── workspaces-circular.test.ts │ │ │ ├── workspaces-cross-reference.test.ts │ │ │ ├── workspaces-dts.test.ts │ │ │ ├── workspaces-entry-files.test.ts │ │ │ ├── workspaces-ignored.test.ts │ │ │ ├── workspaces-include-entry-exports.test.ts │ │ │ ├── workspaces-module-resolution.test.ts │ │ │ ├── workspaces-nested.test.ts │ │ │ ├── workspaces-noconfig-plugin.test.ts │ │ │ ├── workspaces-paths-compilers.test.ts │ │ │ ├── workspaces-paths.test.ts │ │ │ ├── workspaces-plugin-circular.test.ts │ │ │ ├── workspaces-plugin-config.test.ts │ │ │ ├── workspaces-plugin-overlap.test.ts │ │ │ ├── workspaces-pnpm.test.ts │ │ │ ├── workspaces-self-reference.test.ts │ │ │ ├── workspaces-tooling.test.ts │ │ │ ├── workspaces.test.ts │ │ │ └── zero-config.test.ts │ │ └── tsconfig.json │ ├── language-server/ │ │ ├── README.md │ │ ├── license │ │ ├── package.json │ │ ├── src/ │ │ │ ├── cli.js │ │ │ ├── code-actions.js │ │ │ ├── constants.js │ │ │ ├── diagnostics.js │ │ │ ├── index.js │ │ │ ├── server.js │ │ │ └── types.d.ts │ │ └── tsconfig.json │ ├── mcp-server/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── license │ │ ├── package.json │ │ └── src/ │ │ ├── cli.js │ │ ├── curated-resources.js │ │ ├── server.js │ │ ├── texts.js │ │ └── tools.js │ └── vscode-knip/ │ ├── .gitignore │ ├── .release-it.json │ ├── README.md │ ├── license │ ├── package.json │ ├── scripts/ │ │ ├── publish.js │ │ └── sync-from-mcp.js │ ├── src/ │ │ ├── collect-dependency-hover-snippets.js │ │ ├── collect-export-hover-snippets.js │ │ ├── index.js │ │ ├── render-dependency-hover.js │ │ ├── render-export-hover.js │ │ ├── tools.js │ │ ├── tree-view-base.js │ │ ├── tree-view-exports.js │ │ └── tree-view-imports.js │ ├── test/ │ │ ├── extension.test.mjs │ │ ├── index.mjs │ │ └── run.mjs │ └── tsconfig.json ├── pnpm-workspace.yaml ├── release.sh └── templates/ ├── demo/ │ ├── monorepo/ │ │ ├── .gitignore │ │ ├── knip.ts │ │ ├── package.json │ │ ├── packages/ │ │ │ ├── client/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ └── tsconfig.json │ │ │ ├── server/ │ │ │ │ ├── package.json │ │ │ │ ├── src/ │ │ │ │ │ └── index.ts │ │ │ │ └── tsconfig.json │ │ │ └── shared/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── exports.ts │ │ │ │ ├── import-numbers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── numbers.ts │ │ │ │ └── used-fn.ts │ │ │ └── tsconfig.json │ │ └── tsconfig.json │ └── script/ │ └── demo.lua ├── issue-reproduction/ │ ├── basic/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.ts │ │ ├── knip.json │ │ ├── package.json │ │ └── tsconfig.json │ └── monorepo/ │ ├── .gitignore │ ├── README.md │ ├── knip.json │ ├── package.json │ ├── packages/ │ │ ├── client/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ └── lib/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── language-server-client/ │ ├── .gitignore │ ├── knip.json │ ├── package.json │ ├── packages/ │ │ ├── client/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── blend.js │ │ │ │ ├── index.ts │ │ │ │ ├── pick.js │ │ │ │ └── reap.js │ │ │ └── tsconfig.json │ │ ├── server/ │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── branch-definition.ts │ │ │ │ ├── branch-left.ts │ │ │ │ ├── branch-right.ts │ │ │ │ ├── branch.ts │ │ │ │ ├── circular-a.ts │ │ │ │ ├── circular-b.ts │ │ │ │ ├── circular-c.ts │ │ │ │ ├── conflict-1.ts │ │ │ │ ├── conflict-2.ts │ │ │ │ ├── conflict-3.ts │ │ │ │ ├── index.ts │ │ │ │ ├── overload-1.ts │ │ │ │ ├── overload-2.ts │ │ │ │ └── overload-3.ts │ │ │ └── tsconfig.json │ │ └── shared/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── constants.ts │ │ │ ├── fruits.ts │ │ │ ├── helpers.ts │ │ │ ├── index.ts │ │ │ └── unused.ts │ │ └── tsconfig.json │ └── tsconfig.json └── playground/ ├── basic/ │ ├── README.md │ ├── clutter.ts │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ └── util.ts └── monorepo/ ├── .gitignore ├── README.md ├── knip.ts ├── package.json ├── packages/ │ ├── client/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── server/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ └── shared/ │ ├── package.json │ ├── src/ │ │ ├── exports.ts │ │ ├── index.ts │ │ └── used-fn.ts │ └── tsconfig.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .agents/MODULE_GRAPH.md ================================================ # Module Graph Concise walk-through from CLI to reporter output. Core module graph and AST traversal. ## Implementation walk-through The sequence from [CLI][1]: 1. [Create options][2] 2. [Run][3] 1. Normalize user config 2. Get workspaces 3. [Build module graph][4] 1. [Run enabled plugins][5] in each workspace 2. Store entry points and referenced dependencies 3. [Create TS programs][6] 4. [Get imports and exports][7] using TS AST traversal/visitors 5. [Get dependencies/binaries from scripts][8] 4. [Analyze module graph][9] 1. Find [unused exports][10] (respecting [namespaces & members][11]) 2. Settle unused files 3. [Settle unused/unlisted dependencies][12] 4. Settle unused catalog entries 3. [Run default reporter][13] [1]: ./packages/knip/src/cli.ts [2]: ./packages/knip/src/util/create-options.ts [3]: ./packages/knip/src/run.ts [4]: ./packages/knip/src/graph/build.ts [5]: ./packages/knip/src/WorkspaceWorker.ts [6]: ./packages/knip/src/ProjectPrincipal.ts [7]: ./packages/knip/src/typescript/get-imports-and-exports.ts [8]: ./packages/knip/src/binaries/bash-parser.ts [9]: ./packages/knip/src/graph/analyze.ts [10]: ./packages/knip/src/graph-explorer/operations/is-referenced.ts [11]: ./packages/knip/src/graph-explorer/operations/has-strictly-ns-references.ts [12]: ./packages/knip/src/DependencyDeputy.ts [13]: ./packages/knip/src/reporters/symbols.ts ================================================ FILE: .agents/PLUGINS.md ================================================ # Plugins ## General Read [Writing A Plugin][1] first to understand: - Plugin responsibilities - Functions like `resolveConfig` and `Input` type definition - Consider `resolveFromAST` only for custom plugin-specific needs (core takes care of module resolution, imports, exports, external dependencies) ## Creating a new plugin To create a new plugin for a certain package/tool/framework: - Come up with a kebab-cased `name`. - Run `pnpm create-plugin --name [name]` from the `packages/knip` directory. - Update the plugin's `types.ts`: add only relevant types, remove if unused. - Consult similar plugins and the tool's website before implementation - Update and fill out the blanks in the generated files. - Remove unused variables and empty arrays from the template - Don't forget: [run tests][2] individually first. [1]: ../packages/docs/src/content/docs/writing-a-plugin/index.md [2]: ../AGENTS.md#test ================================================ FILE: .gitattributes ================================================ # Convert all files to use "\n" line endings. * text eol=lf # Specify the file type for some binary files to prevent Git from changing the line endings upon # cloning the repository. *.gif binary *.ico binary *.jpeg binary *.jpg binary *.png binary *.otf binary *.mov binary *.mp3 binary *.mp4 binary *.webm binary *.webp binary ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ # Code of Conduct - **Be kind & respectful**: Treat everyone with kindness, empathy, and respect. No personal attacks, offensive language, or discrimination. - **Collaborate**: Share your ideas, help others, and work together. We're all here to learn and grow! - **Communicate clearly**: Be open and honest, but also considerate. Keep your messages clear and concise. - **Stay on topic**: Keep discussions relevant to the project. Off-topic conversations can happen elsewhere. - **Be patient**: We all have different skill levels and backgrounds. Give people time to respond and learn. - **Report issues**: If you see any violations of this Code of Conduct, please report them to the [project maintainer][1]. This document is a summary of [the Contributor Covenant Code Of Conduct][2]. By participating in this project, you agree to follow this Code of Conduct. [1]: https://github.com/webpro [2]: https://www.contributor-covenant.org/version/2/1/code_of_conduct/ ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing Thank you for investing your time in contributing to Knip! Read our [Code of Conduct][1] to keep our community approachable and respectable. ## Types of contributions - Star the project to show your support - Share [Knip][2] in social media or blog posts - [Open an issue][3] - [Open a pull request][4] to: - Fix a bug - Add a new feature - Add a new plugin - Improve output or add a new reporter - Improve documentation - Improve performance or architecture The main goal of Knip is to keep projects clean & tidy. Everything that contributes to that goal is welcome! ## Open an issue Feel free to open an issue for things like this: - Knip throws an error. - Knip shows incorrect output, e.g. it reports false negatives. - Documentation is incorrect or something is missing. - Questions about configuration or how to run Knip. - Discuss whether to start a pull request. - Request a new feature. Before you open an issue: - Make sure you're using the **latest** version of Knip (see [https://github.com/webpro-nl/knip/releases][5]) - Use GitHub search to find related questions, known issues, etc. - If relevant, use the `--debug` flag which might reveal errors, potential issues with configuration, etc. ## Open a pull request Pull requests are welcome! Please consider this before opening a pull request: - Open an issue before starting the work if for any reason you're not 100% sure about it. We can optimize both your and our time if we discuss ideas and choose a direction upfront. - Pull requests may not align with the general philosophy, or may not be affordable to maintain, and therefore rejected. - Generated ("vibe-coded") pull requests may be rejected without explanation. - Read [development][6] instructions and guidelines. - If you think your PR is not ready for review yet, [set it as a draft][7]. - No need to worry about commit messages, they will probably be squashed into a single commit when merged. - After your first PR is merged, you are automatically added to the [list of contributors][8]. [1]: ./CODE_OF_CONDUCT.md [2]: https://knip.dev [3]: #open-an-issue [4]: #open-a-pull-request [5]: https://github.com/webpro-nl/knip/releases [6]: ./DEVELOPMENT.md [7]: https://docs.github.com/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request [8]: https://knip.dev/#created-by-awesome-contributors ================================================ FILE: .github/DEVELOPMENT.md ================================================ # Development Development in this repository is using: - pnpm - TypeScript - Biome This document describes commands and tasks that might help during development. Use what fits your workflow best, but make sure [QA][1] passes. > [!TIP] > > tl;dr The quickest way to get started: `git clone`, `pnpm install`, find a > relevant test file in `packages/knip/test`, and [hit F5 in VS Code or > WebStorm][2]. ## Contents - [Getting started][3] - [Agents][4] - [Contributing a plugin?][5] - [Running Knip][6] - [Tests][7] - [QA][1] - [GitHub Action][8] ## Getting started This guide assumes familiarity with concepts like [forking][9], [cloning a repo][10] and working with a package manager. - Fork the project using the [GitHub website][11] or the [`gh` CLI][12] - Clone the repository - Install dependencies Example terminal commands on your machine to get started: ```shell git clone git@github.com:[username]/knip.git # Or using gh CLI: gh repo fork webpro-nl/knip --clone cd knip pnpm install cd packages/knip pnpm build pnpm test ``` To skip slower tests related to CLI and `--fix`, while still covering all the essentials and plugins: ```shell pnpm test:smoke bun test:bun:smoke ``` ## Agents Using coding agents cq AI-powered tooling? Inform it about [AGENTS.md][13]. Take responsibility and make sure to not cause unnecessary review and "wall of text" overhead to maintainers. Also [consider this before opening a pull request][14]. ## Contributing a plugin? In addition to the generic guidelines in this document, there's a guide for [writing a plugin][15]. ## Running Knip Knip is written in TypeScript, and there are a few options to run it including your changes: - [Compile][16] ahead of time to JavaScript to run in Node.js - [Without compilation][17] - Transpile on the fly using e.g `tsx` to run in Node.js - Use a runtime that supports TypeScript (i.e. Bun) ### Compile Use `pnpm build` to compile using `tsc` once. To recompile on changes: ```shell pnpm watch ``` On source code changes, `tsc` will compile to JavaScript, and the `knip` executable is available globally to run from any directory. ### Without compilation Run Knip without compilation: ```shell node path/to/knip/packages/knip/src/cli.ts ``` #### Alias Expanding on this idea, set up an alias like so: ```shell alias k="node --inspect ~/p/knip/packages/knip/src/cli.ts" ``` Invoke `k` to run Knip including any local changes. And if it's in the built-in terminal, it will stop at breakpoints. For the rest of this document, `knip` or `node --inspect` can be replaced with `k`. ## Tests Most pull requests should probably include one or more tests. Assuming you've created `test/feature.test.ts` and `fixtures/feature` (the plugin create command does for you), here's a few ideas to run and debug Knip from a test. Creating a new plugin? The [plugin guide][18] has a command to set up a test with fixtures for you. ### Run single test file ```shell node --test test/my-feature.test.ts bun test test/plugins/my-plugin.test.ts ``` ### Run Knip in the directory ```shell knip --directory fixtures/feature ``` ### Attach debugger to Node.js To debug Knip in an IDE (e.g. [VS Code][19] or [WebStorm][20]), open the built-in terminal and allow the debugger to connect: ```shell cd fixtures/feature node --inspect ../../src/cli.ts ``` Make sure VS Code is set up to attach to the Node.js process ("Always" or "With flag"). ### Attach debugger from inside a test file Run configurations for VS Code and WebStorm² are set up in the repo. This a great way to debug almost anything in Knip. - Using Node.js - From any test file, run the "Debug test with tsx/Node.js" launch config - Using Bun - VS Code: ensure the [Bun extension][21] is enabled - WebStorm: ensure the [Bun plugin][22] is enabled - From any test file, run the "Debug test with Bun" launch config From now on, just set a breakpoint and hit `F5` (Code) or `ctrl-r` (WS) from any test file to run and debug. ² Requires at least WebStorm 2025.2 EAP ### Attach debugger to tests In case you're wondering if or why some code is ever hit, attach the debugger to each test. Set a breakpoint and run all tests in one of the following ways: - From built-in terminal: `tsx --inspect --test test/**/*.test.ts` - Use the "Debug all tests with Bun" launch config. ## QA Knip has a few tools set up to verify code quality and to format code and documentation: ```shell pnpm format pnpm lint pnpm knip pnpm knip --strict pnpm test ``` ## GitHub Action The [ci.yml][23] workflow runs the tests across Bun, recent Node.js versions, Ubuntu, macOS and Windows. QA in CI must be all green before a pull request can be merged. The [integration.yml][24] workflow runs Knip in multiple repositories using Knip, against the latest version of the code. ## Previews Thanks to [pkg.pr.new][25] pull requests can be previewed by installing it as a regular package. Every push is published to their registry. Look for the `pkg-pr-new` bot in your pull request. [1]: #qa [2]: #attach-debugger-to-bun-from-a-test [3]: #getting-started [4]: #agents [5]: #contributing-a-plugin [6]: #running-knip [7]: #tests [8]: #github-action [9]: https://docs.github.com/get-started/quickstart/fork-a-repo [10]: https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository [11]: https://github.com/webpro-nl/knip [12]: https://cli.github.com/ [13]: ../AGENTS.md [14]: ./CONTRIBUTING.md#open-a-pull-request [15]: https://knip.dev/guides/writing-a-plugin/ [16]: #compile [17]: #without-compilation [18]: https://knip.dev/guides/writing-a-plugin#create-a-new-plugin [19]: https://code.visualstudio.com/docs/nodejs/nodejs-debugging [20]: https://www.jetbrains.com/help/webstorm/running-and-debugging-node-js.html [21]: https://marketplace.visualstudio.com/items?itemName=oven.bun-vscode [22]: https://www.jetbrains.com/help/webstorm/bun.html#bun_before_you_start [23]: https://github.com/webpro-nl/knip/actions/workflows/ci.yml [24]: https://github.com/webpro-nl/knip/actions/workflows/integration.yml [25]: https://pkg.pr.new ================================================ FILE: .github/FUNDING.yml ================================================ github: webpro open_collective: knip ================================================ FILE: .github/ISSUE_TEMPLATE/01-bug_report.yaml ================================================ name: 🐛 Bug report description: Create a report to help us improve title: '🐛 ' labels: ['bug'] body: - type: markdown attributes: value: | Use common sense and provide the necessary information that helps us to help you. A minimal reproduction is mandatory: only the code and configuration required to demonstrate the issue. Issues that do not meet these requirements may be closed without further investigation. - type: checkboxes attributes: label: Prerequisites description: Please check existing information about your issue options: - label: I'm using the latest version required: true - label: I've read the relevant [documentation](https://knip.dev) required: true - label: I've searched for [existing issues](https://github.com/webpro-nl/knip/issues?q=is%3Aissue) required: true - label: I've checked the [list of known issues](https://knip.dev/reference/known-issues) required: true - label: I've read the [issue reproduction guide](https://knip.dev/guides/issue-reproduction) required: true - type: input id: reproduction attributes: label: Reproduction url description: Please link to the location of the issue reproduction validations: required: true - type: checkboxes attributes: label: Reproduction access description: For instance, a CodeSandbox seems private by default options: - label: I've made sure the reproduction is publicly accessible required: true - type: textarea id: description attributes: label: Description of the issue description: What happened, and what would you expect to happen? validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/02-regression.yaml ================================================ name: 🔄 Regression description: Something that worked a certain way before, but no longer does title: '🔄 ' labels: ['regression'] body: - type: markdown attributes: value: | Please make sure you have read the docs and are using the latest version of Knip. Use common sense and provide the necessary information that helps me or others to help you. A minimal reproduction is mandatory: only the code and configuration required to demonstrate the issue. Issues that do not meet these requirements may be closed without further investigation. - type: checkboxes attributes: label: Prerequisites description: Please check existing information about your issue options: - label: I've read the relevant [documentation](https://knip.dev) required: true - label: I've searched for [existing issues](https://github.com/webpro-nl/knip/issues?q=is%3Aissue) required: true - label: I've read the [issue reproduction guide](https://knip.dev/guides/issue-reproduction) required: true - type: input id: reproduction attributes: label: Reproduction url description: Please link to the location of the issue reproduction validations: required: true - type: checkboxes attributes: label: Reproduction access description: For instance, a CodeSandbox seems private by default options: - label: I've made sure the reproduction is publicly accessible required: true - type: input id: good-version attributes: label: Good version description: What's the latest version it worked as expected? validations: required: true - type: input id: bad-version attributes: label: Bad version description: What's the first version it no longer works as expected? validations: required: true - type: textarea id: description attributes: label: Description of the regression description: What happened before, what happens now? validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/03-feature_request.yaml ================================================ name: 💡 Feature Request (RFC) description: Suggest an idea for Knip title: '💡 ' labels: ['feature request'] body: - type: markdown attributes: value: Use common sense and provide the necessary information to explain why the feature is useful to you and to others. Thanks! - type: textarea id: description attributes: label: Suggest an idea for Knip validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/04-documentation.yaml ================================================ name: 📘 Documentation description: An idea for or issue with the documentation website (knip.dev) title: '📘 ' labels: ['documentation'] body: - type: markdown attributes: value: An idea for or issue with the documentation website - type: input id: link attributes: label: Link description: If possible or relevant, please link to the location - type: textarea id: description attributes: label: Description of the issue description: Please describe the issue validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/05-everything-else.yaml ================================================ name: 🧩 Everything Else description: Discuss anything related to Knip title: '🧩 ' labels: ['discussion'] body: - type: markdown attributes: value: Feel free to discuss something related to Knip that does not fit the other categories. - type: textarea id: description attributes: label: Discuss anything related to Knip validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ ================================================ FILE: .github/copilot-instructions.md ================================================ See [AGENTS.md][1]. [1]: ../AGENTS.md ================================================ FILE: .github/workflows/ci-bun.yml ================================================ name: Tests (Bun) on: workflow_dispatch: pull_request: push: branches: - '**' tags: - '!**' jobs: test: strategy: matrix: os: - macos-latest - ubuntu-latest - windows-latest runs-on: ${{ matrix.os }} name: ${{ matrix.os }} steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 with: bun-version: 1.2.22 - name: Install dependencies run: bun install --ignore-scripts - name: Run linter and formatter run: bun ci - name: Build knip run: bun run build working-directory: packages/knip - name: Run knip run: ./packages/knip/bin/knip-bun.js - name: Run knip (production/strict) run: ./packages/knip/bin/knip-bun.js --production --strict - name: Test knip run: bun run test:bun working-directory: packages/knip ================================================ FILE: .github/workflows/ci-ts-latest.yml ================================================ name: Tests (against typescript@latest in Node.js v22) on: workflow_dispatch: pull_request: push: branches: - '**' tags: - '!**' jobs: test: runs-on: ubuntu-latest name: Ubuntu/Node v22 steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: 22 - uses: pnpm/action-setup@v5 - name: Install dependencies run: pnpm install - name: Install latest peer dependencies run: pnpm add typescript@latest @types/node@22 working-directory: packages/knip - name: Build knip run: pnpm run build working-directory: packages/knip - name: Test knip run: pnpm run test:node working-directory: packages/knip - name: Run knip run: ./packages/knip/bin/knip.js - name: Run knip in strict mode run: ./packages/knip/bin/knip.js --production --strict ================================================ FILE: .github/workflows/ci-ts-next.yml ================================================ name: Tests (against typescript@next in Node.js v24) on: workflow_dispatch: pull_request: push: branches: - '**' tags: - '!**' jobs: test: runs-on: ubuntu-latest name: Ubuntu/Node v24 steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: 24 - uses: pnpm/action-setup@v5 - name: Install dependencies run: pnpm install - name: Install latest peer dependencies run: pnpm add typescript@next @types/node@24 working-directory: packages/knip - name: Build knip run: pnpm run build working-directory: packages/knip - name: Test knip run: pnpm run test:node working-directory: packages/knip - name: Run knip run: ./packages/knip/bin/knip.js - name: Run knip in strict mode run: ./packages/knip/bin/knip.js --production --strict ================================================ FILE: .github/workflows/ci.yml ================================================ name: Tests (against typescript@5.0.4 in Node.js v20) on: workflow_dispatch: pull_request: push: branches: - '**' tags: - '!**' jobs: test: strategy: matrix: os: - macos-latest - ubuntu-latest - windows-latest node: - 20 - 22 runs-on: ${{ matrix.os }} name: ${{ matrix.os }} (Node v${{ matrix.node }}) steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: ${{ matrix.node }} - uses: pnpm/action-setup@v5 - name: Install dependencies run: pnpm install - name: Build knip run: pnpm run build working-directory: packages/knip - name: Install earliest supported peer dependencies run: pnpm add typescript@5.0.4 @types/node@20 working-directory: packages/knip - name: Type-check against TS 5.0.4 run: | node -e "let f=require('fs'),p='tsconfig.json';f.writeFileSync(p,f.readFileSync(p,'utf8').replace(/.*(?:rewriteRelativeImportExtensions|erasableSyntaxOnly).*\n/g,''))" pnpm tsc --noEmit working-directory: packages/knip - name: Test knip run: pnpm run test:smoke working-directory: packages/knip - name: Run knip run: ./packages/knip/bin/knip.js --reporter github-actions - name: Run knip in strict mode run: ./packages/knip/bin/knip.js --production --strict ================================================ FILE: .github/workflows/integration.yml ================================================ name: Publish preview & run ecosystem tests on: workflow_dispatch: pull_request: push: branches: - '**' tags: - '!**' permissions: issues: write jobs: publish: name: Build and publish Knip runs-on: ubuntu-latest outputs: sha: ${{ steps.publish.outputs.sha }} steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@v5 - run: pnpm install --frozen-lockfile working-directory: packages/knip - run: pnpm run build working-directory: packages/knip - id: publish run: | pnpx pkg-pr-new publish --compact './packages/knip' './packages/language-server' './packages/mcp-server' - name: Comment on referenced issues if: github.event_name == 'push' uses: actions/github-script@v8 with: script: | const sha = '${{ steps.publish.outputs.sha }}'; const commits = context.payload.commits || []; const messages = commits.map(commit => commit.message).join('\n'); const issueRefs = messages.match(/#(\d+)/g) || []; const issues = new Set(issueRefs.map(ref => parseInt(ref.slice(1)))); const isClosingMatch = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi; const closingIssues = new Set([...messages.matchAll(isClosingMatch)].map(m => parseInt(m[1]))); for (const issue_number of issues) { try { const { owner, repo } = context.repo; const { data } = await github.rest.issues.get({ owner, repo, issue_number }); if (data.state === 'open' || closingIssues.has(issue_number)) { const body = `Preview release available:\n\`\`\`sh\nnpm i -D https://pkg.pr.new/knip@${sha}\n\`\`\``; await github.rest.issues.createComment({ owner, repo, issue_number, body }); } } catch(error) { console.log(`Could not comment on #${issue_number}: ${error.message}`);} } integration: name: Run Knip in ${{ matrix.project.name }} needs: publish runs-on: ubuntu-latest env: PKG_URL: https://pkg.pr.new/knip@${{ needs.publish.outputs.sha }} strategy: fail-fast: false matrix: project: - name: 10ten-ja-reader repo: birchill/10ten-ja-reader commands: | pnpm install pnpm dlx $PKG_URL - name: argos repo: argos-ci/argos commands: | pnpm install pnpm build pnpm add -D -w $PKG_URL pnpm run knip - name: astro repo: withastro/astro commands: | pnpm install pnpm build pnpm add -D -w $PKG_URL - name: create-typescript-app repo: JoshuaKGoldberg/create-typescript-app commands: | pnpm install pnpm add -D $PKG_URL pnpm lint:knip - name: DefinitelyTyped-tools repo: microsoft/DefinitelyTyped-tools commands: | pnpm install pnpm dlx $PKG_URL - name: eslint repo: eslint/eslint commands: | npm install npm install --prefix docs npm install -D $PKG_URL npm run lint:unused -- --cache npm run lint:unused -- --cache - name: mocha repo: mochajs/mocha commands: | npm ci npm install -D $PKG_URL npm run lint:knip - name: InvokeAI repo: invoke-ai/InvokeAI sparse-checkout: invokeai/frontend/web commands: | cd invokeai/frontend/web pnpm install pnpm add -D $PKG_URL bunx --bun knip --tags=-knipignore bunx --bun knip --tags=-knipignore --production --fix --allow-remove-files --format bunx --bun knip --tags=-knipignore --production - name: npmx.dev repo: npmx-dev/npmx.dev commands: | pnpm install pnpm add -D -w $PKG_URL pnpm knip pnpm knip --production --exclude dependencies - name: prettier repo: prettier/prettier commands: | yarn yarn --cwd scripts/release yarn --cwd scripts/tools/bundle-test yarn --cwd scripts/tools/eslint-plugin-prettier-internal-rules yarn --cwd website yarn add -D knip@$PKG_URL yarn knip - name: query repo: TanStack/query commands: | pnpm install pnpm add -D -w $PKG_URL pnpm test:knip --cache pnpm test:knip --cache - name: rolldown repo: rolldown/rolldown commands: | pnpm install pnpm add -D -w knip@$PKG_URL pnpm knip - name: sentry repo: getsentry/sentry commands: | pnpm install pnpm add -D $PKG_URL pnpm run knip pnpm run knip:prod - name: slonik repo: gajus/slonik commands: | pnpm install --no-frozen-lockfile pnpm dlx $PKG_URL - name: TypeScript repo: microsoft/TypeScript commands: | npm ci npm install -D $PKG_URL npm run knip steps: - uses: actions/checkout@v6 - name: Check out ${{ matrix.project.repo }} uses: actions/checkout@v6 with: repository: ${{ matrix.project.repo }} path: ${{ matrix.project.name }} sparse-checkout: ${{ matrix.project.sparse-checkout }} - name: Apply patch if exists working-directory: ${{ matrix.project.name }} run: | PATCH_FILE="${{ github.workspace }}/.github/workflows/patches/${{ matrix.project.name }}.patch" [ -f "$PATCH_FILE" ] && git apply --verbose "$PATCH_FILE" || true - uses: actions/setup-node@v6 with: node-version: 24 - uses: oven-sh/setup-bun@v2 - uses: pnpm/action-setup@v5 - name: Run Knip in ${{ matrix.project.repo }} working-directory: ${{ matrix.project.name }} run: | set -x ${{ matrix.project.commands }} ================================================ FILE: .github/workflows/markdown-link-check.json ================================================ { "aliveStatusCodes": [0, 200, 429], "ignorePatterns": [ { "generated": "packages/docs/src/content/docs/reference/plugins/*.md" } ] } ================================================ FILE: .github/workflows/markdown-link-check.yml ================================================ name: Check Markdown links on: push: branches: - '**' tags: - '!**' jobs: markdown-link-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@main - name: Check Markdown links uses: gaurav-nelson/github-action-markdown-link-check@v1 with: config-file: .github/workflows/markdown-link-check.json use-quiet-mode: 'yes' use-verbose-mode: 'yes' ================================================ FILE: .github/workflows/patches/.gitkeep ================================================ ================================================ FILE: .github/workflows/patches/TypeScript.patch ================================================ diff --git a/knip.jsonc b/knip.jsonc index f471ada9b2..83844be8aa 100644 --- a/knip.jsonc +++ b/knip.jsonc @@ -32,6 +32,7 @@ "ignoreExportsUsedInFile": { "enum": true, "interface": true, + "namespace": true, "type": true }, "mocha": false ================================================ FILE: .github/workflows/patches/argos.patch ================================================ diff --git a/knip.json b/knip.json --- a/knip.json +++ b/knip.json @@ -11,7 +11,8 @@ "src/graphql/definitions/*.ts", "scripts/*.ts" ], - "ignore": ["**/bin/**/*"] + "ignore": ["**/bin/**/*"], + "ignoreDependencies": ["@argos/knex-scripts", "moment"] }, "apps/frontend": { "ignore": ["vite.config.mts"], ================================================ FILE: .github/workflows/patches/create-typescript-app.patch ================================================ diff --git a/knip.json b/knip.json index 8bbe72d..23921d7 100644 --- a/knip.json +++ b/knip.json @@ -1,6 +1,6 @@ { "$schema": "https://unpkg.com/knip@5.71.0/schema.json", - "entry": ["src/**/*.test.*", "src/index.ts"], + "entry": ["src/**/*.test.*"], "ignoreDependencies": [ "all-contributors-cli", "cspell-populate-words", ================================================ FILE: .github/workflows/patches/npmx.dev.patch ================================================ diff --git a/knip.ts b/knip.ts index f885994f..27d68897 100644 --- a/knip.ts +++ b/knip.ts @@ -4,18 +4,6 @@ const config: KnipConfig = { workspaces: { '.': { entry: [ - 'app/router.options.ts!', - 'app/app.vue!', - 'app/error.vue!', - 'app/pages/**/*.vue!', - 'app/components/**/*.vue!', - 'app/components/**/*.d.vue.ts!', - 'app/composables/**/*.ts!', - 'app/middleware/**/*.ts!', - 'app/plugins/**/*.ts!', - 'app/utils/**/*.ts!', - 'server/**/*.ts!', - 'modules/**/*.ts!', 'config/**/*.ts!', 'lunaria/**/*.ts!', 'shared/**/*.ts!', @@ -24,11 +12,12 @@ const config: KnipConfig = { 'pwa-assets.config.ts', '.lighthouserc.cjs', 'lighthouse-setup.cjs', - 'uno-preset-rtl.ts!', + 'uno-preset-*.ts!', 'scripts/**/*.ts', ], project: [ - '**/*.{ts,vue,cjs,mjs}', + '**/*.{ts,vue,cjs,mjs}!', + '!test/**!', '!test/fixtures/**', '!test/test-utils/**', '!test/e2e/helpers/**', @@ -48,31 +37,39 @@ const config: KnipConfig = { /** Some components import types from here, but installing it directly could lead to a version mismatch */ 'vue-router', - /** Required by @nuxtjs/i18n at runtime but not directly imported in production code */ - '@intlify/shared', - /** Oxlint plugins don't get picked up yet */ '@e18e/eslint-plugin', 'eslint-plugin-regexp', /** Used in test/e2e/helpers/ which is excluded from knip project scope */ 'h3-next', + + /** Not referenced in production source code (either pending/inactive, or effectively devDependencies) */ + '@deno/doc!', + '@floating-ui/vue!', + '@intlify/shared!', + '@shikijs/langs!', + '@shikijs/themes!', + '@upstash/redis!', + '@vueuse/integrations!', + 'algoliasearch!', + 'focus-trap!', + 'ipaddr.js!', + 'marked!', + 'sanitize-html!', + 'semver!', + 'shiki!', + 'virtua!', + 'vue-data-ui!', ], - ignoreUnresolved: ['#components', '#oauth/config'], + ignoreUnresolved: ['#oauth/config'], }, 'cli': { project: ['src/**/*.ts!', '!src/mock-*.ts'], }, 'docs': { entry: ['app/**/*.{ts,vue,css}'], - ignoreDependencies: [ - 'docus', - 'better-sqlite3', - '@nuxtjs/mdc', - 'nuxt!', - '@nuxt/ui', - 'tailwindcss', - ], + ignoreDependencies: ['docus', 'better-sqlite3', '@nuxtjs/mdc', 'nuxt!'], }, }, } ================================================ FILE: .gitignore ================================================ node_modules /.idea/* !/.idea/runConfigurations .DS_Store .npmrc packages/*/dist ================================================ FILE: .idea/runConfigurations/Debug_Bun_test.xml ================================================ ================================================ FILE: .idea/runConfigurations/Debug_Node_test.xml ================================================ ================================================ FILE: .oxfmtrc.json ================================================ { "printWidth": 120, "singleQuote": true, "arrowParens": "avoid", "trailingComma": "es5", "overrides": [ { "files": ["**/*.json", "**/*.jsonc"], "options": { "printWidth": 80 } }, { "files": ["*.css"], "options": { "singleQuote": false } }, { "files": ["packages/knip/test/util/get-inputs-from-scripts.test.ts"], "options": { "printWidth": 200 } } ] } ================================================ FILE: .oxlintrc.json ================================================ { "$schema": "./node_modules/oxlint/configuration_schema.json", "plugins": ["typescript", "import"], "categories": { "correctness": "error" }, "rules": { "no-unused-vars": [ "error", { "argsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_", "destructuredArrayIgnorePattern": "^_" } ], "no-unused-expressions": [ "error", { "allowShortCircuit": true, "allowTernary": true } ], "no-console": "error", "@typescript-eslint/no-explicit-any": "off", "no-param-reassign": "off", "dot-notation": "off", "array-callback-return": "off" }, "ignorePatterns": [ "**/dist", "**/tmp", "**/vendor", "packages/docs/.astro", ".vscode", "templates" ], "overrides": [ { "files": ["**/*.astro"], "rules": { "no-unused-vars": "off" } }, { "files": ["packages/knip/**"], "rules": { "no-restricted-imports": [ "error", { "paths": [ { "name": "node:path", "message": "Please use src/util/path.js instead." }, { "name": "path", "message": "Please use src/util/path.js instead." }, { "name": "node:assert", "message": "Please use node:assert/strict instead." } ] } ], "import/extensions": ["error", "always", { "ignorePackages": true }] } }, { "files": ["packages/docs/**", "packages/create-config/**"], "rules": { "no-restricted-imports": "off", "no-console": "off" } }, { "files": ["packages/language-server/**"], "rules": { "no-console": "off" } }, { "files": [ "packages/knip/src/reporters/**", "packages/knip/scripts/**", "packages/vscode-knip/scripts/**", "packages/vscode-knip/test/**" ], "rules": { "no-console": "off" } }, { "files": ["packages/knip/fixtures/**"], "rules": { "no-unused-expressions": "off", "no-unused-vars": "off", "no-console": "off", "no-duplicate-enum-values": "off", "no-restricted-imports": "off", "triple-slash-reference": "off", "import/namespace": "off", "import/extensions": "off" } } ] } ================================================ FILE: .prettierignore ================================================ **/dist **/tmp **/fixtures **/*.md **/*.mdx templates/language-server-client packages/docs/.astro ================================================ FILE: .release-it.json ================================================ { "$schema": "https://unpkg.com/release-it@19/schema/release-it.json", "git": { "commitMessage": "Release ${npm.name}@${version}", "tagName": "${npm.name}@${version}" }, "npm": { "publishPackageManager": "pnpm", "publishArgs": ["--no-git-checks"] } } ================================================ FILE: .vscode/extensions.json ================================================ { "recommendations": [ "oxc.oxc-vscode", "remcohaszing.vscode-mdxlint", "unifiedjs.vscode-remark" ] } ================================================ FILE: .vscode/launch.json ================================================ { "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug test with Node.js", "runtimeArgs": ["--test"], "args": ["${file}"], "cwd": "${workspaceFolder}/packages/knip", "console": "integratedTerminal" }, { "type": "bun", "request": "launch", "name": "Debug test with Bun", "program": "${file}", "cwd": "${workspaceFolder}/packages/knip", "runtime": "bun", "runtimeArgs": ["test", "--timeout", "999999999"], "internalConsoleOptions": "openOnSessionStart" }, { "type": "bun", "request": "launch", "name": "Debug all tests with Bun", "program": ".", "cwd": "${workspaceFolder}/packages/knip", "runtime": "bun", "runtimeArgs": ["test", "--timeout", "999999999"], "internalConsoleOptions": "openOnSessionStart" }, { "name": "Run Extension on Playground Monorepo (w/ MCP Server)", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceFolder}/packages/vscode-knip", "${workspaceFolder}/templates/language-server-client" // Point at any repo ], "outFiles": [ "${workspaceFolder}/packages/vscode-knip/**/*.js", "${workspaceFolder}/packages/language-server/**/*.js", "${workspaceFolder}/packages/mcp-server/**/*.js" ] }, { "name": "Attach to Knip Server", "type": "node", "request": "attach", "port": 6009, "restart": true, "outFiles": [ "${workspaceFolder}/packages/language-server/**/*.js", "${workspaceFolder}/packages/knip/dist/**/*.js", "${workspaceFolder}/packages/knip/src/**/*.ts" ], "sourceMaps": true, "resolveSourceMapLocations": [ "${workspaceFolder}/**", "!**/node_modules/**" ] } ], "compounds": [ { "name": "Run + Attach Knip LSP", "configurations": [ "Run Extension on Playground Monorepo (w/ MCP Server)", "Attach to Knip Server" ] } ], "inputs": [ { "id": "projectPath", "type": "promptString", "description": "Enter absolute path to y${lineNumber}our project dir", "default": "${workspaceFolder}/templates/language-server-client" } ] } ================================================ FILE: .vscode/settings.json ================================================ { "[javascript]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "[json]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "[jsonc]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "[markdown]": { "editor.defaultFormatter": "unifiedjs.vscode-remark" }, "[mdx]": { "editor.defaultFormatter": "remcohaszing.vscode-mdxlint" }, "[typescript]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "[typescriptreact]": { "editor.defaultFormatter": "oxc.oxc-vscode" }, "oxc.fmt.configPath": ".oxfmtrc.json", "cSpell.enabled": true, "cSpell.words": [ "astro", "codebase", "codegen", "codeowners", "commitlint", "devkit", "execa", "jiti", "knip", "lefthook", "preprocess", "preprocessor", "stylelint", "timerify", "tsup", "unimported", "webp" ], "editor.formatOnSave": true } ================================================ FILE: AGENTS.md ================================================ # Knip Knip is a tool to find and fix unused dependencies, exports and files in JavaScript and TypeScript projects. ## Context: project overview - Monorepo - Main package is core in `packages/knip` (TypeScript) - Language Server in `packages/language-server` (JS + JSDoc for types) - VS Code Extension in `packages/vscode-knip` (JS + JSDoc for types) - [Documentation][1] content in `packages/docs` (Astro + MD/MDX) ## Principles - Ask yourself: "Would a staff engineer approve this?" — maintain high standards - If something goes sideways, stop and re-plan immediately - don't keep pushing - For non-trivial changes: pause and ask "is there a more elegant way?" - If a fix feels hacky: "Knowing everything I know now, implement the elegant solution" — but skip this for simple, obvious fixes (i.e. don't over-engineer) - Challenge your own work before presenting it - Your training data is stale — verify packages, APIs, and syntax against current docs - If you say "I will do X", actually do X — don't just announce intentions - Don't blindly follow instructions: question the user if the request would not result in something better or faster ## Communication - Zero context switching required from the user - When reporting information to the user, be extremely concise and sacrifice grammar for the sake of concision - Don't add comments to code, unless explicitly asked for. ## Planning 1. Plan: write plan to `.agents/tasks/todo-(name).md` with checkable items 2. Get alignment: check in with user before starting implementation, question any doubts or noise 3. Track progress: mark items complete as you go 4. Explain changes: high-level summary at each step 5. Document results: add review section to `.agents/tasks/todo-(name).md` 6. Capture lessons: update `.agents/lessons.md` after corrections - Use subagents liberally to keep main context window clean - Offload research, exploration, and parallel analysis to subagents ## Workflow - Read broadly before editing — understand surrounding code, not just the target - Commit chunks of verified work — don't let unrelated changes accumulate - Make small, testable, incremental changes — not big-bang edits - Avoid manual edits and regex-based refactors, prefer AST-based tools and codemods (jscodeshift) — except for tiny edits - Reflect on outcomes between steps — don't blindly chain actions - Diff behavior between main and your changes when relevant ## Code style - Performance is key, both high level (design) and low level (impl). - Avoid redundant code and abstractions. - Avoid unnecessary complexity and nesting. - Concise one-liners are fine, but prioritize clarity over cleverness. - JavaScript - Prefer plain `for..in/of` loops over iterator methods like `map`/`reduce`. - TypeScript - Avoid `any` and type casting (`as`) - Avoid runtime overhead just to get the types right ## Verification - Insufficient testing is the #1 failure mode — test rigorously, not hopefully - State verification method _before_ implementing (test, CLI output, linter, screenshot) - Prefer TDD for new features — write or update tests before implementing - For UI or integration changes: screenshots or CLI output as evidence - Tailor to the domain: run a bash command, check a web page, use a linter — whatever is most direct - Every completed task must answer: "How was this verified?" - Document verification steps in `.agents/tasks/todo-(name).md` - Maintain "known pitfalls" in `.agents/lessons.md` — check it before starting, update it after corrections ## Issues and Pull Requests - When given a bug report, first confirm the behavior is actually wrong. Reproduce, then check if the reported behavior is correct-by-design before writing any fix - Find repositories/CodeSandbox/StackBlitz source files and local fixtures to actually reproduce the issue at hand - To fetch stackblitz.com reproduction url: `pnpx stackblitz-zip https://stackblitz.com/edit/{name} {filename}.zip` ## Domain Knowledge - Unused file → unused exports/dependencies is a chain, not a bug - Use `--performance` or `--performance-fn [name]` to profile (→ [timerify][2]) - If creating or modifying a plugin, read [PLUGINS.md][3] first. - If modifying core module graph, AST traversal, or CLI sequence, read [MODULE_GRAPH.md][4] first. ## Environment - Before using `sed`, `awk`, etc. — verify GNU or POSIX-compatible tools are installed (gnu-sed, coreutils) - Always look at root lockfile and package.json to choose between npm/npx, pnpm/pnpx, etc. ## Run & Debug Important: debug, don't guess. Run the CLI directly using `node` or `bun`. The rest of this document shows `knip` in commands for consistency. Replace it with `node (path/to/)src/cli.ts` or `bun (path/to/)src/cli.ts` and keep using what works. - Run `knip` directly in a fixture or temp directory (over creating test scripts that import the `main` function). - Knip requires `package.json` in root dir. - Enable [debug & helpers][5] with `--debug` (not `DEBUG=`). Warning: noisy. - Use [trace][6] to debug - exported identifiers (`knip --trace-export [name] --trace-file [file]`) - external dependencies (`knip --trace-dependency [name] --workspace [dir]`) ## Test Prefer `bun` over `node` for speed. Don't run all tests at once (slow & noisy). Start out with running the relevant test(s) first: ```sh cd packages/knip bun test test/util/get-inputs-from-scripts.test.ts node --test test/commonjs.test.ts ``` To run all relevant tests without having to build `knip`: ```sh cd packages/knip pnpm run test:bun:smoke ``` Use `node` if Bun is not available: ```sh cd packages/knip node --test test/commonjs.test.ts pnpm test:smoke ``` Build core package and run all tests only if there are changes in auto-fix, formatting and reporter related functionality: ```sh cd packages/knip pnpm build pnpm test ``` ## Fixtures There are plenty of directories with fixtures in `packages/knip/fixtures`. - In general, tests have their own fixture directory. - Plugin fixture directories at `packages/knip/fixtures/plugins/[plugin-name]*`. - For trivial changes or fixes, extend an existing fixture. - Don't use "foo" or vague names. One fixture should consist of descriptive file and variable names like `module.ts` and `barrel.ts`, or build upon a "theme" such as fruits or animals to indicate relation/hierarchy. - Use empty files if sufficient (e.g. to verify import specifier or entry file). - For debugging, it might be useful to run Knip from the fixture directory and see output in terminal. Example: ```sh cd packages/knip/fixtures/commonjs knip ``` ## Build To type-check `knip` with `tsc`: ```sh cd packages/knip pnpm build ``` [1]: https://knip.dev [2]: ./packages/knip/src/util/Performance.ts [3]: ./.agents/PLUGINS.md [4]: ./.agents/MODULE_GRAPH.md [5]: ./packages/knip/src/util/debug.ts [6]: ./packages/docs/src/content/docs/guides/troubleshooting.md#trace ================================================ FILE: knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "workspaces": { ".": { "project": ["!templates/**"] }, "packages/knip": { "project": [ "src/**/*.ts!", "test/**/*.ts", "!src/util/empty.ts", "!**/_template/**" ], "ignoreDependencies": ["prettier"] }, "packages/docs": { "entry": ["{remark,scripts}/*.ts"] }, "packages/vscode-knip": { "entry": ["src/index.js!", "scripts/*.js", "test/*.mjs"], "ignoreDependencies": ["vscode!"] } } } ================================================ FILE: license ================================================ ISC License (ISC) Copyright 2022-2025 Lars Kappert Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ================================================ FILE: package.json ================================================ { "name": "@knip/root", "version": "0.0.0", "private": true, "description": "Find unused dependencies, exports and files in your TypeScript and JavaScript projects", "homepage": "https://knip.dev", "bugs": "https://github.com/webpro-nl/knip/issues", "license": "ISC", "author": { "name": "Lars Kappert", "email": "lars@webpro.nl" }, "repository": { "type": "git", "url": "https://github.com/webpro-nl/knip" }, "workspaces": [ "packages/*" ], "type": "module", "scripts": { "watch": "pnpm run --dir packages/knip watch", "docs": "pnpm run --dir packages/docs dev", "test": "pnpm run --dir packages/knip test", "format": "oxfmt", "lint": "oxlint", "ci": "oxlint && oxfmt --check && installed-check --ignore-dev", "release": "./release.sh" }, "devDependencies": { "@release-it/bumper": "^7.0.5", "installed-check": "^9.3.0", "mdxlint": "^1.0.0", "mdxlint-preset-webpro": "^1.1.1", "oxfmt": "^0.35.0", "oxlint": "^1.50.0", "release-it": "^19.2.4", "remark-cli": "12.0.1", "remark-preset-webpro": "^2.1.1" }, "prettier": { "arrowParens": "avoid", "singleQuote": true, "trailingComma": "es5" }, "remarkConfig": { "plugins": [ "preset-webpro" ] }, "engines": { "node": ">=22.0.0" }, "packageManager": "pnpm@10.24.0", "mdxlint": { "plugins": [ "mdxlint-preset-webpro" ] } } ================================================ FILE: packages/create-config/README.md ================================================ # @knip/create-config Add Knip to a repository. ```shell npm init @knip/config ``` This adds Knip and its peer dependencies to `devDependencies`. Example result: ```json { "name": "my-package", "scripts": { "knip": "knip" }, "devDependencies": { "@types/node": "^20.14.8", "knip": "^5.30.1", "typescript": "^5.5.4" } } ``` ================================================ FILE: packages/create-config/index.js ================================================ #!/usr/bin/env node import { execSync } from 'node:child_process'; import fs from 'node:fs'; import { EOL } from 'node:os'; import path from 'node:path'; const fileExists = filePath => { const stat = fs.statSync(filePath, { throwIfNoEntry: false }); return stat?.isFile(); }; const hasAccess = filePath => { try { fs.accessSync(filePath, fs.constants.R_OK); return true; } catch { return false; } }; const readFirstBytes = (filePath, length = 128) => { const fd = fs.openSync(filePath, 'r'); const buffer = Buffer.alloc(length); const bytesRead = fs.readSync(fd, buffer, 0, length, 0); fs.closeSync(fd); return buffer.subarray(0, bytesRead).toString('utf-8'); }; const getPackageManager = () => { // get the root of the repository let repositoryRoot = ''; try { repositoryRoot = execSync('git rev-parse --show-toplevel', { stdio: [null, null, 'ignore'] }) .toString() .trim(); } catch {} if (fileExists(path.join(repositoryRoot, 'bun.lock'))) return 'bun'; if (fileExists(path.join(repositoryRoot, 'bun.lockb'))) return 'bun'; if (hasAccess(path.join(repositoryRoot, 'yarn.lock'))) { const yarnLock = readFirstBytes(path.join(repositoryRoot, 'yarn.lock'), 128); return yarnLock.includes('yarn lockfile v1') ? 'yarn' : 'yarn-berry'; } if (fileExists(path.join(repositoryRoot, 'pnpm-lock.yaml'))) return 'pnpm'; return 'npm'; }; const getBinX = pm => { if (pm === 'npm') return 'npx'; return pm; }; const hasWorkspaces = manifest => { if (manifest.workspaces) { if (Array.isArray(manifest.workspaces) && manifest.workspaces.length > 0) return true; if (typeof manifest.workspaces === 'object' && manifest.workspaces.packages?.length > 0) return true; } if (hasAccess('pnpm-workspace.yaml')) { try { const content = fs.readFileSync('pnpm-workspace.yaml', 'utf-8'); return /(^|\n)packages:\n/.test(content); } catch { return false; } } return false; }; const findPackageJsonFiles = (dir, depth = 0) => { if (depth > 3) return []; const dirs = []; const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue; const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { dirs.push(...findPackageJsonFiles(fullPath, depth + 1)); } else if (entry.name === 'package.json' && dir !== process.cwd()) { dirs.push(path.relative(process.cwd(), dir)); } } return dirs; }; const getWorkspaceFlag = (manifest, pm) => { if (pm === 'pnpm') return hasWorkspaces(manifest) ? '-w' : undefined; if (pm === 'yarn') return hasWorkspaces(manifest) ? '-W' : undefined; }; const getPackageManagerFromPackageJson = manifest => { if (!manifest.packageManager) return undefined; let [pmName, pmVersion] = manifest.packageManager.split('@'); if (pmName === 'yarn' && pmVersion?.[0] > 1) { pmName = 'yarn-berry'; } const validPackageManagers = ['bun', 'yarn', 'yarn-berry', 'pnpm', 'npm']; if (!validPackageManagers.includes(pmName)) return undefined; return pmName; }; const main = () => { if (!fileExists('package.json')) { console.error('Please run this command from the root of a repository with a package.json.'); return; } const packageJsonPath = path.join(process.cwd(), 'package.json'); const manifest = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); // Differentiate yarn v1 and v2+ but call them both with `yarn` const pm = getPackageManagerFromPackageJson(manifest) ?? getPackageManager(); const bin = pm === 'yarn-berry' ? 'yarn' : pm; const cmd = [bin, 'add', getWorkspaceFlag(manifest, pm), '-D', 'knip', 'typescript', '@types/node'] .filter(Boolean) .join(' '); execSync(cmd, { stdio: 'inherit' }); console.info(''); console.info('✓ Install Knip'); const knipConfig = { $schema: 'https://unpkg.com/knip@6/schema.json', tags: ['-lintignore'], }; const hasExplicitWorkspaces = hasWorkspaces(manifest); if (hasExplicitWorkspaces) knipConfig.workspaces = { '.': {} }; try { if (!fileExists('knip.json')) { fs.writeFileSync('knip.json', `${JSON.stringify(knipConfig, null, 2)}${EOL}`); console.info('✓ Create knip.json'); } else { console.info('✓ Detected knip.json'); } } catch (error) { console.warn('× Failed to create knip.json:', error.message); } try { execSync('npm pkg set scripts.knip=knip', { stdio: ['inherit', 'inherit', 'ignore'] }); console.info('✓ Add knip to package.json#scripts'); } catch { console.warn('× Failed to add knip to package.json#scripts'); } if (!hasExplicitWorkspaces) { const packages = findPackageJsonFiles(process.cwd()); if (packages.length > 0) { console.info(''); console.info('⚠ Found package.json files in subdirectories:'); for (const pkg of packages.slice(0, 5)) console.info(`- ${pkg}`); if (packages.length > 5) console.info(`- ...and ${packages.length - 5} more`); console.info('Consider adding workspaces to knip.json:'); console.info('More details: https://knip.dev/features/monorepos-and-workspaces#additional-workspaces'); } } console.info(''); console.info(`→ Run \`${getBinX(bin)} knip --max-show-issues 5\` to run Knip for the first time`); console.info(`→ Continue with https://knip.dev/overview/configuration`); }; main(); ================================================ FILE: packages/create-config/package.json ================================================ { "name": "@knip/create-config", "version": "1.2.1", "homepage": "https://knip.dev", "bugs": "https://github.com/webpro-nl/knip/issues", "license": "ISC", "author": { "name": "Lars Kappert", "email": "lars@webpro.nl" }, "repository": { "type": "git", "url": "https://github.com/webpro-nl/knip", "directory": "packages/create-config" }, "funding": [ { "type": "github", "url": "https://github.com/sponsors/webpro" }, { "type": "opencollective", "url": "https://opencollective.com/knip" } ], "bin": "index.js", "type": "module", "publishConfig": { "access": "public" }, "scripts": { "release": "release-it -c ../../.release-it.json" } } ================================================ FILE: packages/docs/.gitignore ================================================ .astro/ .DS_Store .env dist/ node_modules/ src/content/docs/reference/plugins/ ================================================ FILE: packages/docs/README.md ================================================ # knip.dev The source of [knip.dev][1]. [1]: https://knip.dev ================================================ FILE: packages/docs/astro.config.ts ================================================ import starlight from '@astrojs/starlight'; import type { ExpressiveCodeTheme } from '@astrojs/starlight/expressive-code'; import { defineConfig } from 'astro/config'; import remarkDirective from 'remark-directive'; import { fixInternalLinks } from './remark/fixInternalLinks.ts'; import { transformDirectives } from './remark/transformDirectives.ts'; const setForeground = (theme: ExpressiveCodeTheme, scope: string, value: string) => { const settings = theme.settings.find(setting => setting.scope?.includes(scope)); if (settings) settings.settings.foreground = value; }; export default defineConfig({ site: 'https://knip.dev', base: '/', // @ts-expect-error sitemap: false, trailingSlash: 'never', redirects: { '/guides/commonjs': '/guides/working-with-commonjs', '/guides/writing-a-plugin': '/writing-a-plugin', }, markdown: { remarkPlugins: [fixInternalLinks, transformDirectives, remarkDirective], }, integrations: [ starlight({ title: 'Knip', logo: { light: './src/assets/title-light.svg', dark: './src/assets/title-dark.svg', replacesTitle: true, }, social: [ { icon: 'github', label: 'GitHub', href: 'https://github.com/webpro-nl/knip' }, { icon: 'blueSky', label: 'Bluesky', href: 'https://bsky.app/profile/webpro.nl' }, { icon: 'npm', label: 'npm', href: 'https://www.npmjs.com/package/knip' }, ], components: { Head: './src/components/Head.astro', Footer: './src/components/Footer.astro', }, customCss: ['./src/styles/custom.css', './src/fonts/font-face.css'], editLink: { baseUrl: 'https://github.com/webpro-nl/knip/edit/main/packages/docs/', }, sidebar: [ { label: 'Overview', autogenerate: { directory: 'overview' }, }, { label: 'Understanding Knip', autogenerate: { directory: 'explanations' }, }, { label: 'Features', autogenerate: { directory: 'features' }, }, { label: 'Guides', autogenerate: { directory: 'guides' }, }, { label: 'Writing a Plugin', autogenerate: { directory: 'writing-a-plugin' }, }, { label: 'Reference', autogenerate: { directory: 'reference' }, }, { label: 'Blog', autogenerate: { directory: 'blog' }, }, { label: 'Read more', collapsed: true, autogenerate: { directory: 'typescript' }, }, ], expressiveCode: { emitExternalStylesheet: true, styleOverrides: { // @ts-expect-error deal with it 'frm-tooltipSuccessBg': 'var(--sl-color-orange)', 'frm-tooltipSuccessFg': 'var(--sl-color-white)', 'frm-edBg': 'var(--sl-color-black)', 'frm-edActTabBg': 'var(--sl-color-black)', 'frm-edActTabBrdCol': 'var(--sl-color-black)', 'frm-edTabBarBg': 'none', 'frm-edTabBarBrdBtmCol': 'none', 'frm-frameBoxShdCssVal': 'none', }, frames: { showCopyToClipboardButton: true, }, themes: ['min-dark'], customizeTheme: theme => { setForeground(theme, 'entity.name.tag', '#f68a22'); setForeground(theme, 'entity.name.type', '#ededed'); setForeground(theme, 'string', '#ededed'); return theme; }, }, }), ], }); ================================================ FILE: packages/docs/mock/contributors.json ================================================ [ { "login": "webpro", "id": 456426, "node_id": "MDQ6VXNlcjQ1NjQyNg==", "avatar_url": "https://avatars.githubusercontent.com/u/456426?v=4", "gravatar_id": "", "url": "https://api.github.com/users/webpro", "html_url": "https://github.com/webpro", "followers_url": "https://api.github.com/users/webpro/followers", "following_url": "https://api.github.com/users/webpro/following{/other_user}", "gists_url": "https://api.github.com/users/webpro/gists{/gist_id}", "starred_url": "https://api.github.com/users/webpro/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/webpro/subscriptions", "organizations_url": "https://api.github.com/users/webpro/orgs", "repos_url": "https://api.github.com/users/webpro/repos", "events_url": "https://api.github.com/users/webpro/events{/privacy}", "received_events_url": "https://api.github.com/users/webpro/received_events", "type": "User", "site_admin": false, "contributions": 1282 } ] ================================================ FILE: packages/docs/package.json ================================================ { "name": "@knip/docs", "version": "0.0.0", "private": true, "description": "Documentation for Knip, hosted at knip.dev", "homepage": "https://knip.dev", "repository": { "type": "git", "url": "github:webpro-nl/knip", "directory": "packages/docs" }, "type": "module", "scripts": { "prebuild": "node ./scripts/generate-plugin-docs.ts", "build": "astro check && astro build", "postbuild": "[ \"$CF_PAGES\" = \"1\" ] && find dist -mindepth 2 -type f -name 'index.html' -exec bash -c 'f=\"$1\"; d=$(dirname \"$f\"); bn=$(basename \"$d\"); mv -v \"$f\" \"$d/../$bn.html\"' _ {} \\; && find dist -mindepth 1 -type d -empty -print -delete || true", "dev": "astro dev", "remark": "remark README.md 'src/content/docs/**/*.md' --verbose -o && mdxlint 'src/content/docs/**/*.mdx' --verbose -o" }, "dependencies": { "@astro-community/astro-embed-youtube": "0.5.10", "@astrojs/starlight": "0.38.1", "sharp": "0.34.5" }, "devDependencies": { "@astrojs/check": "0.9.8", "@octokit/graphql": "^9.0.3", "@types/mdast": "4.0.4", "@types/unist": "3.0.3", "astro": "6.0.5", "hastscript": "9.0.1", "picocolors": "^1.1.1", "remark-directive": "4.0.0", "remark-frontmatter": "5.0.0", "remark-gfm": "4.0.1", "remark-parse": "11.0.0", "remark-stringify": "11.0.0", "unified": "11.0.5", "unist-builder": "4.0.0", "unist-util-visit": "5.1.0" }, "engines": { "node": ">=22.0.0" } } ================================================ FILE: packages/docs/public/fonts/fonts.conf ================================================ /vercel/path0/docs/public/fonts/ /vercel/path0/docs/.astro/ ================================================ FILE: packages/docs/public/manifest.json ================================================ { "name": "Knip", "short_name": "Knip", "icons": [ { "src": "/favicon.svg", "type": "image/svg+xml", "sizes": "512x512" }, { "src": "/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#fbfbfb", "background_color": "#f56e0f", "display": "standalone", "scope": "/", "start_url": "/overview/getting-started/" } ================================================ FILE: packages/docs/public/robots.txt ================================================ User-agent: * Allow: / Sitemap: https://knip.dev/sitemap.txt ================================================ FILE: packages/docs/remark/fixInternalLinks.ts ================================================ import pc from 'picocolors'; import type { Node, Parent } from 'unist'; import { type Visitor, visit } from 'unist-util-visit'; interface LinkNode extends Node { url: string; } const isLinkNode = (node: Node): node is LinkNode => (node.type === 'link' || node.type === 'definition') && typeof (node as LinkNode).url === 'string'; const dateTimeFormat = new Intl.DateTimeFormat([], { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }); export const fixInternalLinks = () => (tree: Parent) => { const visitor: Visitor = node => { if (isLinkNode(node) && node.url.startsWith('.')) { const url = node.url; node.url = url.replace(/(?:\/index)?\.mdx?(#.+)?$/, '$1'); console.log(`${pc.dim(dateTimeFormat.format(new Date()))} ${pc.cyan('[fix-link]')} Modify ${url} → ${node.url}`); } }; visit(tree, visitor); }; ================================================ FILE: packages/docs/remark/transformDirectives.ts ================================================ import { h } from 'hastscript'; import type { Node, Parent } from 'unist'; import { type Visitor, visit } from 'unist-util-visit'; interface DirectiveNode extends Node { type: 'textDirective' | 'leafDirective' | 'containerDirective'; name: string; attributes: Record; data: Record; } const isDirectiveNode = (node: Node): node is DirectiveNode => node.type === 'textDirective' || node.type === 'leafDirective' || node.type === 'containerDirective'; export const transformDirectives = () => (tree: Parent) => { const visitor: Visitor = node => { if (isDirectiveNode(node)) { const hast = h(node.name, node.attributes); // oxlint-disable-next-line no-cond-assign const data = node.data || (node.data = {}); data.hName = hast.tagName; data.hProperties = hast.properties; } }; visit(tree, visitor); }; ================================================ FILE: packages/docs/scripts/generate-plugin-docs.ts ================================================ import fs from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import type { Root } from 'mdast'; import remarkDirective from 'remark-directive'; import remarkFrontmatter from 'remark-frontmatter'; import remarkParse from 'remark-parse'; import remarkStringify from 'remark-stringify'; import { unified } from 'unified'; import type { Node } from 'unist'; import { u } from 'unist-builder'; import type { Plugin } from '../../knip/src/types/config.ts'; const rootDir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..'); const referenceDocsDir = path.join(rootDir, 'src/content/docs/reference'); const knipDir = path.join(rootDir, '../../packages/knip'); const pluginsDir = path.join(knipDir, 'src/plugins'); const directories = await fs.opendir(pluginsDir); const plugins = []; const srcBaseUrl = new URL('webpro-nl/knip/blob/main/packages/knip/src/plugins', 'https://github.com'); const parseFragment = (text: string) => { const tree = unified().use(remarkParse).parse(text); return tree.children; }; const writeTree = async (tree: Node, filePath: string) => { try { const file = await unified().run(tree); const markdown = unified() .use(remarkFrontmatter, ['yaml']) .use(remarkDirective) .use(remarkStringify, { bullet: '-', }) .stringify(file as Root); await fs.writeFile(filePath, markdown); } catch (err) { console.error(err); } }; for await (const dir of directories) { if (dir.isDirectory() && dir.name !== '_template') { const pluginName = dir.name; const pluginDir = path.join(pluginsDir, pluginName); const mod = await import(path.join(pluginDir, 'index.ts')); const plugin: Plugin = mod.default; const docs: undefined | { note: string; entry?: string[]; production?: string[] } = mod.docs; const { title, enablers, args, config, entry, production, project } = plugin; plugins.push([title, pluginName]); const frontmatter = u('yaml', `title: ${title}\nsidebar:\n hidden: true`); const defaults: Record = {}; const configFiles = typeof config === 'function' ? config({ cwd: pluginDir }) : config; if (configFiles && configFiles.length > 0) defaults.config = configFiles; if (entry && entry.length > 0) defaults.entry = entry; if (docs?.entry && docs.entry.length > 0) defaults.entry = [...(defaults.entry ?? []), ...docs.entry]; if (production && production.length > 0) defaults.entry = [...(defaults.entry ?? []), ...production]; if (docs?.production && docs.production.length > 0) defaults.entry = [...(defaults.entry ?? []), ...docs.production]; if (project && project.length > 0) defaults.project = project; const hasDefaultConfig = Object.values(defaults).some(v => v.length > 0); const enabledText = Array.isArray(enablers) && enablers.length > 0 ? enablers.length === 1 && typeof enablers[0] === 'string' ? parseFragment( `This plugin is enabled if \`"${enablers[0]}"\` is listed in \`"dependencies"\` or \`"devDependencies"\` in \`package.json\`.` ) : [ ...parseFragment( `This plugin is enabled if there's a match in \`"dependencies"\` or \`"devDependencies"\` in \`package.json\`:` ), u( 'list', enablers.map((enabler: string | RegExp) => u('listItem', [u('inlineCode', typeof enabler === 'string' ? enabler : enabler.source)]) ) ), ] : typeof enablers === 'string' ? parseFragment(enablers) : [u('paragraph', [u('text', 'This plugin is always enabled.')])]; const defaultConfig = hasDefaultConfig ? [ u('heading', { depth: 2 }, [u('text', 'Default configuration')]), ...parseFragment('If this plugin is enabled, the following configuration is added automatically:'), u('code', { lang: 'json', // TODO How to set attributes/properties/props properly? value: JSON.stringify({ [pluginName]: defaults }, null, 2), }), ...parseFragment('Depending on local configuration, plugins may modify the defaults as shown.'), ...parseFragment('Custom `config` or `entry` options override default values, they are not merged.'), ...parseFragment( 'See [Plugins](../../explanations/plugins.md) for more details about plugins and their `entry` and `config` options.' ), ] : []; const notes = docs?.note ? [u('heading', { depth: 2 }, [u('text', 'Note')]), ...parseFragment(docs.note)] : []; const printCode = (value: unknown): string => Array.isArray(value) ? `[${value.map(printCode).join(', ')}]` : typeof value === 'function' ? value.toString() : JSON.stringify(value).replace(/([,:])/g, '$1 '); const argsText = args ? [ ...parseFragment( `## Shell commands\n\nThis plugin adds argument parsing for the ${args.binaries ? args.binaries.join(' and ') : pluginName} ${args.binaries && args.binaries.length > 1 ? 'binaries' : 'binary'}. Configuration:` ), ...parseFragment( `\`\`\`\n${Object.entries(args) .filter(([key]) => key !== 'binaries') .map(([key, value]) => `${key}: ${printCode(value)}`) .join('\n')}\n\`\`\`` ), ...parseFragment( 'The configuration was generated from source code. Also see [Script Parser](../../features/script-parser.md).' ), ] : []; const generated = parseFragment( `## Generated from source\n\nThis page was generated from the [${pluginName} plugin source code](${srcBaseUrl}/${dir.name}/index.ts).` ); const tree = u('root', [ frontmatter, u('heading', { depth: 2 }, [u('text', 'Enabled')]), ...enabledText, ...defaultConfig, ...notes, ...argsText, ...generated, ]); console.log(`Writing ${pluginName} docs to plugins/${pluginName}.md`); await writeTree(tree, path.join(referenceDocsDir, `plugins/${pluginName}.md`)); } } plugins.sort((a, b) => (a[1] < b[1] ? -1 : 1)); const frontmatter = u('yaml', `title: Plugins (${plugins.length})\ntableOfContents: false`); const tree = u('root', [ frontmatter, u('containerDirective', { name: 'section{.columns.min200}' }, [ u( 'list', { spread: false, ordered: false }, plugins.map(plugin => u('listItem', [u('link', { title: plugin[0], url: `/reference/plugins/${plugin[1]}` }, [u('text', plugin[0])])]) ) ), u('paragraph'), ]), ]); console.log('Writing plugin list to plugins.md'); await writeTree(tree, path.join(referenceDocsDir, 'plugins.md')); ================================================ FILE: packages/docs/scripts/get-monthly-sponsorships-github.ts ================================================ import { graphql } from '@octokit/graphql'; const token = process.env.GITHUB_TOKEN_SPONSORSHIPS; type Options = { token?: string; startDate: Date; endDate?: Date; recurringOnly: boolean; }; interface SponsorActivity { action: 'NEW_SPONSORSHIP' | 'CANCELLED_SPONSORSHIP'; timestamp: string; sponsorsTier: { monthlyPriceInDollars: number; isOneTime: boolean; }; sponsor: { login: string; }; } interface GraphQLResponse { viewer: { sponsorsActivities: { nodes: SponsorActivity[]; }; }; } const getMonthlyTotals = async (options: Options) => { const { token, startDate, recurringOnly } = options; const { viewer } = await graphql({ query: ` query { viewer { sponsorsActivities(first: 100, period: ALL) { nodes { action timestamp sponsorsTier { monthlyPriceInDollars isOneTime } sponsor { ... on User { login } ... on Organization { login } } } } } } `, headers: { authorization: `token ${token}`, }, }); const activities = [...viewer.sponsorsActivities.nodes].sort( (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime() ); const activeRecurring = new Map(); const monthlyTotals = new Map(); const now = new Date(); for (let d = new Date(startDate); d <= now; d = new Date(d.getFullYear(), d.getMonth() + 1, 1)) { monthlyTotals.set(d.toISOString().substring(0, 7), 0); } for (const activity of activities) { const { action, sponsor, sponsorsTier, timestamp } = activity; if (recurringOnly && sponsorsTier?.isOneTime) continue; const amount = sponsorsTier?.monthlyPriceInDollars || 0; const monthYear = new Date(timestamp).toISOString().substring(0, 7); if (sponsorsTier?.isOneTime) { if (!recurringOnly && action === 'NEW_SPONSORSHIP') { monthlyTotals.set(monthYear, (monthlyTotals.get(monthYear) || 0) + amount); } } else { if (action === 'NEW_SPONSORSHIP') activeRecurring.set(sponsor.login, amount); if (action === 'CANCELLED_SPONSORSHIP') activeRecurring.delete(sponsor.login); const total = Array.from(activeRecurring.values()).reduce((sum, a) => sum + a, 0); for (const month of monthlyTotals.keys()) { if (month >= monthYear) monthlyTotals.set(month, total); } } } return monthlyTotals; }; export const getGitHubTotals = async (options: Options) => { if (!token) throw new Error('GITHUB_TOKEN_SPONSORSHIPS is not set'); const monthlyData = await getMonthlyTotals({ ...options, token }); const startMonth = options.startDate.toISOString().substring(0, 7); const endMonth = options.endDate?.toISOString().substring(0, 7); for (const month of monthlyData.keys()) { if (month < startMonth || (endMonth && month > endMonth)) monthlyData.delete(month); } return monthlyData; }; ================================================ FILE: packages/docs/scripts/get-monthly-sponsorships-opencollective.ts ================================================ import { graphql } from '@octokit/graphql'; const token = process.env.OPENCOLLECTIVE_TOKEN; const RATE_EUR_TO_USD = 1.08; type Options = { token?: string; startDate: Date; endDate?: Date; recurringOnly: boolean; }; interface Transaction { id: string; type: string; kind: string; amount: { value: number; currency: string; }; createdAt: string; fromAccount: { name: string; }; } interface Expense { id: string; amount: number; currency: string; createdAt: string; type: string; status: string; } interface GraphQLResponse { account: { transactions: { nodes: Transaction[]; }; }; expenses: { nodes: Expense[]; }; } const getMonthlyTotals = async (options: Options): Promise> => { const { token, startDate, recurringOnly } = options; const { account, expenses } = await graphql({ query: ` query { account(slug: "knip") { transactions(type: CREDIT) { nodes { id type kind amount { value currency } createdAt fromAccount { name } } } } expenses(fromAccount: { slug: "webpro" }) { nodes { id amount currency createdAt type status } } } `, url: 'https://api.opencollective.com/graphql/v2', headers: { 'Api-Key': token, Accept: 'application/json', }, }); const monthlyTotals = new Map(); const now = new Date(); for (let d = new Date(startDate); d <= now; d = new Date(d.getFullYear(), d.getMonth() + 1, 1)) { monthlyTotals.set(d.toISOString().substring(0, 7), 0); } for (const transaction of account.transactions.nodes) { if (recurringOnly && transaction.kind !== 'CONTRIBUTION') continue; const month = new Date(transaction.createdAt).toISOString().substring(0, 7); const amount = Math.round(transaction.amount.value); monthlyTotals.set(month, (monthlyTotals.get(month) || 0) + amount); } if (!recurringOnly) { for (const expense of expenses.nodes) { const month = new Date(expense.createdAt).toISOString().substring(0, 7); const amount = expense.currency === 'EUR' ? Math.round((expense.amount / 100) * RATE_EUR_TO_USD) : Math.round(expense.amount / 100); monthlyTotals.set(month, (monthlyTotals.get(month) || 0) + amount); } } return monthlyTotals; }; export const getOpenCollectiveTotals = async (options: Options) => { if (!token) throw new Error('OPENCOLLECTIVE_TOKEN is not set'); const monthlyData = await getMonthlyTotals({ ...options, token }); const startMonth = options.startDate.toISOString().substring(0, 7); const endMonth = options.endDate?.toISOString().substring(0, 7); for (const month of monthlyData.keys()) { if (month < startMonth || (endMonth && month > endMonth)) monthlyData.delete(month); } return monthlyData; }; ================================================ FILE: packages/docs/scripts/get-monthly-sponsorships.ts ================================================ import { Table } from '../../knip/src/util/table.ts'; import { getGitHubTotals } from './get-monthly-sponsorships-github.ts'; import { getOpenCollectiveTotals } from './get-monthly-sponsorships-opencollective.ts'; const START_DATE = new Date('2023-11-01'); const END_DATE = new Date(); END_DATE.setDate(1); END_DATE.setHours(-1); const main = async () => { const [monthlyGHS, monthlyGHSRO, monthlyOC, monthlyOCRO] = await Promise.all([ getGitHubTotals({ startDate: START_DATE, endDate: END_DATE, recurringOnly: false }), getGitHubTotals({ startDate: START_DATE, endDate: END_DATE, recurringOnly: true }), getOpenCollectiveTotals({ startDate: START_DATE, endDate: END_DATE, recurringOnly: false }), getOpenCollectiveTotals({ startDate: START_DATE, endDate: END_DATE, recurringOnly: true }), ]); const monthly = new Map(); for (const [month, amount] of monthlyGHS) monthly.set(month, [...(monthly.get(month) || []), amount]); for (const [month, amount] of monthlyOC) monthly.set(month, [...(monthly.get(month) || []), amount]); const monthlyRO = new Map(); for (const [month, amount] of monthlyGHSRO) monthlyRO.set(month, [...(monthlyRO.get(month) || []), amount]); for (const [month, amount] of monthlyOCRO) monthlyRO.set(month, [...(monthlyRO.get(month) || []), amount]); const table = new Table(); const digits = (n: number) => (v: any) => (typeof v === 'number' ? v.toFixed(n) : v); const sum = Array.from(monthly.values()).reduce((a, c) => a + c.reduce((a, b) => a + b, 0), 0); const sumGHS = Array.from(monthlyGHS.values()).reduce((a, c) => a + c, 0); const sumOC = Array.from(monthlyOC.values()).reduce((a, c) => a + c, 0); const sumRO = Array.from(monthlyRO.values()).reduce((a, c) => a + c.reduce((a, b) => a + b, 0), 0); for (const [key, value] of [ ['months', monthly.size], ['github', sumGHS], ['OC', sumOC], ['sum', sum], ['avg', sum / monthly.size], ['recurring sum', sumRO], ['recurring avg', sumRO / monthlyRO.size], ]) { table.row(); table.cell('key', key); table.cell('value', value, digits(0)); } console.log(table.toString()); const url = new URL('/', 'https://try.venz.dev'); url.searchParams.set('type', 'pivot'); url.searchParams.set('lp', 'tr'); url.searchParams.set('br', '0'); url.searchParams.set('labelX', 'month'); url.searchParams.set('labelY', 'amount ($)'); url.searchParams.append('l', 'GitHub Sponsors'); url.searchParams.append('color', '#fbfbfb'); url.searchParams.append('l', 'Open Collective'); url.searchParams.append('color', '#2487ff'); for (const [month, amount] of monthly) { url.searchParams.append('label', month); url.searchParams.append('data', amount.join(',')); } console.log('\nVenz link'); const text = `${url.origin}?${decodeURIComponent(url.searchParams.toString()).replaceAll('#', '%23')}`; console.log(text); }; main().catch(console.error); ================================================ FILE: packages/docs/src/assets/testimonials.json ================================================ { "data": [ { "entities": { "urls": [ { "url": "cdn.bsky.app/img/dummy-02", "display_url": "cdn.bsky.app/img/julien.deniau.me", "media_key": "4" } ] }, "id": "3mdrubg3y5c2z", "author_id": "11", "created_at": "2026-02-01T07:57:00.000Z", "attachments": {}, "text": "Done on a mono-repo in two times.\nWhat's impressive is that there were no false positive!\ncdn.bsky.app/img/dummy-02" }, { "entities": { "urls": [ { "url": "https://t.co/EwIeRiHaXf", "display_url": "pic.x.com/EwIeRiHaXf", "media_key": "6" } ] }, "id": "2017122504914161979", "author_id": "16", "created_at": "2026-01-30T06:27:00.000Z", "text": "Good morning 🌄\nA tool I discovered lately.\nIf you care about clean codebases, this one's a gem 💎" }, { "entities": { "urls": [] }, "id": "3mcky5ps3r22p", "author_id": "12", "created_at": "2026-01-16T20:53:09.000Z", "text": "Knip is a cracking-looking open source tool for trimming unused JavaScript." }, { "entities": { "urls": [ { "url": "cdn.bsky.app/img/dummy-03", "display_url": "cdn.bsky.app/img/patak.dev", "media_key": "5" } ] }, "id": "3mcjtmv35wc2y", "author_id": "15", "created_at": "2026-01-16T09:59:29.000Z", "attachments": {}, "text": "From the report, we could improve the situation if we stop sending unused JavaScript. @webpro.nl is doing an incredible job growing the usage of knip.dev, and that should hopefully make a dent in the future.\ncdn.bsky.app/img/dummy-03" }, { "entities": { "urls": [ { "url": "https://knip.dev/blog/for-editors-and-agents", "expanded_url": "https://knip.dev/blog/for-editors-and-agents", "display_url": "knip.dev/blog/for-edi..." } ] }, "id": "3mby3zkzhfs2t", "author_id": "13", "created_at": "2026-01-09T08:41:49.000Z", "text": "The VSCode/Cursor extension is ace!\nAnd you can use the Knip MCP to create the config file.\nIt works for Svelte as well.\nKnip is really really good 🙏" }, { "entities": { "urls": [ { "url": "https://t.co/6rcslWBqIV", "display_url": "pic.x.com/6rcslWBqIV", "media_key": "6" } ] }, "id": "2007481125610914217", "author_id": "17", "created_at": "2026-01-03T15:56:00.000Z", "attachments": { "media_keys": ["6"] }, "text": "This is both embarrassing and satisfying after running @Knip https://t.co/6rcslWBqIV" }, { "entities": { "urls": [ { "url": "https://t.co/hneEWMqdnm", "expanded_url": "https://knip.dev", "display_url": "Knip.dev" } ] }, "id": "2007221517562904675", "author_id": "18", "created_at": "2026-01-02T23:44:00.000Z", "text": "You can't spell Opus without https://t.co/hneEWMqdnm" }, { "entities": { "urls": [] }, "id": "3mbggqrihuk2r", "author_id": "14", "created_at": "2026-01-02T08:05:50.000Z", "text": "Knip is amazing and you should be using it." }, { "entities": { "urls": [] }, "id": "1932778410691949034", "author_id": "10", "created_at": "2025-06-11T14:34:00.000Z", "text": "\"Thanks Knip!\"\neveryday,\nevery team member,\nliterally..\nknip.dev 🏅" }, { "entities": { "urls": [] }, "url": "https://github.com/webpro-nl/knip/issues/1120#issuecomment-2943978262", "author_id": "9", "created_at": "2025-06-05T14:00:00.000Z", "text": "Thank you so much for this incredible piece of software! Knip is one of the most impressive tools I've seen in my career." }, { "entities": { "urls": [ { "url": "https://github.com/webpro-nl/knip/pull/1022", "expanded_url": "https://github.com/webpro-nl/knip/pull/1022", "display_url": "https://github.com/webpro-nl/knip/pull/1022", "title": "feat: add create-typescript-app plugin", "description": "feat: add create-typescript-app plugin", "unwound_url": "https://github.com/webpro-nl/knip/pull/1022" } ] }, "id": "3lmhgsj2n622o", "author_id": "7", "created_at": "2025-04-10T13:50:00.000Z", "attachments": {}, "text": "Got my first plugin merged into Knip by @webpro.nl today! ☺️\n\nThe contribution experience was fantastic: the docs were super clear, the code was straightforward to navigate, and the helper script to generate a new plugin got me 90% of the way there. Awesome. Thanks Lars!\n\nhttps://github.com/webpro-nl/knip/pull/1022" }, { "entities": { "urls": [] }, "id": "1904580358307250634", "author_id": "6", "created_at": "2025-03-25T18:05:00.000Z", "attachments": {}, "text": "All of the TanStack monorepos make use of knip.dev\n\nIt's like eslint for detecting unused dependencies or even your own files/modules." }, { "entities": { "urls": [ { "url": "cdn.bsky.app/img/dummy-01", "display_url": "cdn.bsky.app/img/opw3iapscc55nlgrx6q2yjah", "media_key": "2" } ] }, "id": "3ll5ioywml223", "author_id": "8", "created_at": "2025-03-24T20:32:00.000Z", "attachments": {}, "text": "The joy of adding knip.dev (by @webpro.nl) on a codebase! Right in time for spring cleaning 🧹🍃\ncdn.bsky.app/img/dummy-01" }, { "entities": { "urls": [] }, "id": "1874692207472726401", "author_id": "5", "created_at": "2025-01-02T06:40:00.000Z", "attachments": {}, "text": "Knip helped us delete ~300k lines of unused code at Vercel." }, { "entities": { "urls": [ { "url": "https://t.co/kA81p5gkmP", "expanded_url": "https://www.npmjs.com/package/knip", "display_url": "npmjs.com/package/knip", "title": "Knip", "description": "Find unused dependencies, exports and files in your TypeScript and JavaScript projects.", "unwound_url": "https://www.npmjs.com/package/knip" } ] }, "id": "1850975288362221628", "author_id": "5", "created_at": "2024-10-28T19:57:00.000Z", "attachments": {}, "text": "Knip may be the greatest tool ever conceived.\nhttps://t.co/kA81p5gkmP" }, { "entities": { "urls": [] }, "id": "3k3obqi65oy2p", "author_id": "4", "created_at": "2023-07-29T17:33:00.000Z", "attachments": {}, "text": "`knip` is the best code maintenance tool I've used in my 20 years of development, just an absolute work of art" }, { "entities": { "urls": [] }, "id": "1808672067900092505", "author_id": "3", "created_at": "2024-07-04T03:19:00.000Z", "attachments": {}, "text": "knip is great.\n\nA great example of stuff just working. It detects your environment so well and its defaults are almost too good because I didn’t realise it was doing everything automatically." }, { "entities": { "urls": [] }, "id": "1808808208229707835", "author_id": "3", "created_at": "2024-07-04T12:20:00.000Z", "attachments": {}, "text": "Then was like “this is how tooling should be, this has taken me an hour not a day and it’s faster and more accurate and more future proof”\n\nFive stars ⭐️⭐️⭐️⭐️⭐️" }, { "entities": { "urls": [] }, "id": "1803013555907698921", "author_id": "2", "created_at": "2024-06-18T12:35:00.000Z", "attachments": {}, "text": "Crazy useful tool. Thought it would be a nightmare to setup in my Next.js+Workers repo but it has crazy good automatic detection for code dependencies. In short, Knip creates a graph of code use and highlights dead code for you to snip (knip)." }, { "entities": { "urls": [] }, "id": "1793913676896031033", "author_id": "44217212", "created_at": "2024-05-24T09:55:00.000Z", "attachments": {}, "text": "Lars is singlehandedly building the best tool to keep your code clean and your dependencies minimal. And he's so engaging and helpful. Can't imagine going back to not using knip 👏" }, { "entities": { "urls": [ { "url": "https://t.co/dummy-01", "display_url": "pic.twitter.com/uOuO1ch5ij", "media_key": "1" } ] }, "id": "1745972825490604506", "author_id": "1", "created_at": "2024-01-13T01:55:00.000Z", "attachments": { "media_keys": ["1"] }, "text": "warning: do not use a tool like knip.dev + code search to delete a ton of unused code. It works too well.\n\nI just did this in https://github.com/sourcegraph/cody/pull/2705, and my boss said if I end the week with net negative lines of code committed, I'm in deep trouble. https://t.co/dummy-01" }, { "entities": { "mentions": [ { "username": "argos_ci", "id": "1554000987022663681" }, { "username": "webprolific", "id": "218833730" } ], "annotations": [ { "probability": 0.6699, "type": "Other", "normalized_text": "Prettier" }, { "probability": 0.7586, "type": "Other", "normalized_text": "ESLint" } ], "urls": [ { "url": "https://t.co/uOuO1ch5ij", "expanded_url": "https://twitter.com/gregberge_/status/1730180003453927560/photo/1", "display_url": "pic.twitter.com/uOuO1ch5ij", "media_key": "3_1730179997682552832" } ] }, "author_id": "22918124", "text": "Ran knip.dev in @argos_ci, and boom 💥! Dead code detected instantly. With a good config, it can run on CI to keep projects clean. Installing this tool should be a no-brainer, like Prettier or ESLint.\n\nKudos, @webprolific! 👏 https://t.co/uOuO1ch5ij", "id": "1730180003453927560", "created_at": "2023-11-30T11:00:32.000Z", "edit_history_tweet_ids": ["1730180003453927560"], "attachments": { "media_keys": ["3_1730179997682552832"] } }, { "note_tweet": { "text": "Problem: \n🚫 Your project has unused files.\n🚫 It has unused npm dependencies.\n🚫 It has unused TypeScript exports.\n\nBut you haven't noticed, because these things are hard to spot.\n\nSolution: knip\n\nI just used knip to find and resolve dozens of issues.\n\nhttps://t.co/QmN3sNlmbm", "entities": { "urls": [ { "url": "https://t.co/QmN3sNlmbm", "expanded_url": "https://github.com/webpro-nl/knip", "display_url": "github.com/webpro-nl/knip" } ] } }, "entities": { "annotations": [ { "probability": 0.8569, "type": "Other", "normalized_text": "TypeScript" } ], "urls": [ { "url": "https://t.co/grbeTqMtt6", "expanded_url": "https://github.com/webpro-nl/knip", "display_url": "github.com/webpro-nl/knip", "images": [ { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig", "width": 1280, "height": 640 }, { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150", "width": 150, "height": 150 } ], "title": "GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!", "description": "✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...", "unwound_url": "https://github.com/webpro-nl/knip" }, { "url": "https://t.co/qaOXBlD3eo", "expanded_url": "https://twitter.com/i/web/status/1691460974518353920", "display_url": "twitter.com/i/web/status/1…" } ] }, "author_id": "19268321", "text": "Problem: \n🚫 Your project has unused files.\n🚫 It has unused npm dependencies.\n🚫 It has unused TypeScript exports.\n\nBut you haven't noticed, because these things are hard to spot.\n\nSolution: knip\n\nI just used knip to find and resolve dozens of issues.\n\nhttps://t.co/grbeTqMtt6 https://t.co/qaOXBlD3eo", "id": "1691460974518353920", "created_at": "2023-08-15T14:44:56.000Z", "edit_history_tweet_ids": ["1691460974518353920"] }, { "entities": { "mentions": [ { "username": "webprolific", "id": "218833730" } ], "annotations": [ { "probability": 0.6322, "type": "Other", "normalized_text": "Knip" } ] }, "author_id": "3126044440", "text": "@webprolific Knip helped me get rid of over 41k lines of code in legacy codebase 🥺🥺💕", "id": "1729181106715632088", "created_at": "2023-11-27T16:51:17.000Z", "edit_history_tweet_ids": ["1729181106715632088"] }, { "entities": { "mentions": [ { "username": "contra", "id": "973313523790082053" } ], "annotations": [ { "probability": 0.8474, "type": "Other", "normalized_text": "Knip" } ], "urls": [ { "url": "https://t.co/UgCunYQWzu", "expanded_url": "https://twitter.com/webprolific/status/1729105865683435542", "display_url": "twitter.com/webprolific/st…" } ] }, "author_id": "95668959", "text": "Big fans of Knip at @Contra. Such an extremely well developed and maintained project https://t.co/UgCunYQWzu", "id": "1729157761215369264", "created_at": "2023-11-27T15:18:31.000Z", "edit_history_tweet_ids": ["1729157761215369264"] }, { "entities": { "mentions": [ { "username": "webprolific", "id": "218833730" } ], "urls": [ { "url": "https://t.co/ZUYYdvkBJc", "expanded_url": "https://github.com/getsentry/sentry/", "display_url": "github.com/getsentry/sent…", "title": "GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring", "description": "Developer-first error tracking and performance monitoring - GitHub - getsentry/sentry: Developer-first error tracking and performance monitoring", "unwound_url": "https://github.com/getsentry/sentry/" } ] }, "author_id": "1632752318994153472", "text": "@webprolific Just tried this on https://t.co/ZUYYdvkBJc - got some super useful results! Nice work.", "id": "1727040036334424406", "created_at": "2023-11-21T19:03:26.000Z", "edit_history_tweet_ids": ["1727040036334424406"] }, { "entities": { "mentions": [ { "username": "TkDodo", "id": "44217212" }, { "username": "webprolific", "id": "218833730" }, { "username": "webprolific", "id": "218833730" } ] }, "author_id": "1513218780167655427", "text": "@TkDodo @webprolific I've manage to delete 6k LOC in the last 30 minutes 🫣\n\nGreat job here @webprolific 👍🏽", "id": "1726807293583609935", "created_at": "2023-11-21T03:38:35.000Z", "edit_history_tweet_ids": ["1726807293583609935"] }, { "entities": { "mentions": [ { "username": "webprolific", "id": "218833730" } ], "urls": [ { "url": "https://t.co/Tg5E6C7gqa", "expanded_url": "https://twitter.com/housecor/status/1713975785273303286", "display_url": "twitter.com/housecor/statu…" } ] }, "author_id": "44217212", "text": "knip is an amazing tool. Shoutout to @webprolific for building it 🙌.\n\nNot cleaning up correctly has a real maintenance cost. I've deleted lots of dead code - functions that were only used in tests and components that were only used in stories - all thanks to knip 🚀. https://t.co/Tg5E6C7gqa", "id": "1714023231689031941", "created_at": "2023-10-16T20:59:18.000Z", "edit_history_tweet_ids": ["1714023231689031941"] }, { "entities": { "annotations": [ { "probability": 0.9562, "type": "Other", "normalized_text": "JavaScript" }, { "probability": 0.8666, "type": "Other", "normalized_text": "TypeScript" } ], "urls": [ { "url": "https://t.co/f3fzC5UPtR", "expanded_url": "https://github.com/webpro-nl/knip", "display_url": "github.com/webpro-nl/knip", "images": [ { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig", "width": 1280, "height": 640 }, { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150", "width": 150, "height": 150 } ], "title": "GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!", "description": "✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...", "unwound_url": "https://github.com/webpro-nl/knip" } ] }, "author_id": "481186762", "text": "🛠️ Knip\n\n👉🏻 Knip finds unused dependencies, exports and files in your JavaScript and TypeScript projects.\n👉🏻 Less code and dependencies lead to improved performance, less maintenance and easier refactorings. \n\nhttps://t.co/f3fzC5UPtR", "id": "1696221274039595363", "created_at": "2023-08-28T18:00:40.000Z", "edit_history_tweet_ids": ["1696221274039595363"] }, { "entities": { "annotations": [ { "probability": 0.9354, "type": "Other", "normalized_text": "JavaScript" }, { "probability": 0.7027, "type": "Other", "normalized_text": "TypeScript" }, { "probability": 0.7208, "type": "Other", "normalized_text": "Josh" } ], "urls": [ { "url": "https://t.co/nKtvr2wEg6", "expanded_url": "https://twitter.com/JoshuaKGoldberg/status/1693713311836115286", "display_url": "twitter.com/JoshuaKGoldberg" } ] }, "author_id": "416394303", "text": "Knip is wonderful at finding out unused code/dependencies in a legacy JavaScript/TypeScript application\n\nRecommend 💯\n\nHere's how Josh used it to remove code bloat in Centered: https://t.co/nKtvr2wEg6", "id": "1693944495472046382", "created_at": "2023-08-22T11:13:34.000Z", "edit_history_tweet_ids": ["1693944495472046382"] }, { "entities": { "annotations": [ { "probability": 0.5513, "type": "Other", "normalized_text": "Knip" } ], "urls": [ { "url": "https://t.co/L8w9V11PRL", "expanded_url": "https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/", "display_url": "smashingmagazine.com/2023/08/knip-a…", "images": [ { "url": "https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=orig", "width": 1200, "height": 675 }, { "url": "https://pbs.twimg.com/news_img/1727384011872366592/W-M5klkJ?format=jpg&name=150x150", "width": 150, "height": 150 } ], "title": "Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies — Smashing Magazine", "description": "Most of the projects have at least a few unused files, exports, and dependencies lying around, often because it’s difficult knowing when one thing relies on another and scary removing something you’re not sure is in use. Lars Kappert shares a tool he’s been working on that offers a solution.", "unwound_url": "https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/" } ] }, "author_id": "15736190", "text": "Unused files, exports, and dependencies often clutter projects, as it’s difficult knowing when one thing relies on another and scary to remove something you’re not sure is in use. 👀\n\n↬ Meet Knip, which scours projects for these unused artifacts: https://t.co/L8w9V11PRL", "id": "1691120132901240832", "created_at": "2023-08-14T16:10:33.000Z", "edit_history_tweet_ids": ["1691120132901240832"] }, { "entities": { "mentions": [ { "username": "typescript", "id": "809233214" } ], "urls": [ { "url": "https://t.co/1mRMwvjIpw", "expanded_url": "https://effectivetypescript.com/2023/07/29/knip/", "display_url": "effectivetypescript.com/2023/07/29/kni…", "images": [ { "url": "https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=orig", "width": 560, "height": 735 }, { "url": "https://pbs.twimg.com/news_img/1696204795353219085/ZjmFlTVW?format=jpg&name=150x150", "width": 150, "height": 150 } ], "title": "Effective TypeScript › Recommendation Update: ✂️ Use knip to detect dead code and types", "description": "TL;DR: Use ts-prune is in maintenance mode. Use knip to find dead code instead. It's great!", "unwound_url": "https://effectivetypescript.com/2023/07/29/knip/" } ] }, "author_id": "21046936", "text": "Recommendation update: use knip to find dead code, types and dependencies in your @typescript ✂️https://t.co/1mRMwvjIpw", "id": "1685298103094554625", "created_at": "2023-07-29T14:35:53.000Z", "edit_history_tweet_ids": ["1685298103094554625"] }, { "entities": { "annotations": [ { "probability": 0.9661, "type": "Other", "normalized_text": "GitHub" } ], "urls": [ { "url": "https://t.co/vnxNbiJs1I", "expanded_url": "https://github.com/webpro-nl/knip", "display_url": "github.com/webpro-nl/knip", "images": [ { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=orig", "width": 1280, "height": 640 }, { "url": "https://pbs.twimg.com/news_img/1729485824314548224/0xZughNs?format=png&name=150x150", "width": 150, "height": 150 } ], "title": "GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it!", "description": "✂️ Find unused dependencies, exports and files in your JavaScript and TypeScript projects. Knip it before you ship it! - GitHub - webpro-nl/knip: ✂️ Find unused dependencies, exports and files in yo...", "unwound_url": "https://github.com/webpro-nl/knip" } ] }, "author_id": "380616577", "text": "This is worth checking out on GitHub. 👍 https://t.co/vnxNbiJs1I", "id": "1581910299846012928", "created_at": "2022-10-17T07:29:40.000Z", "edit_history_tweet_ids": ["1581910299846012928"] }, { "note_tweet": { "text": "Streamlining React projects with Knip:\n\nRecently, I employed Knip for a project, and it worked wonders! \n\nIt efficiently resolved issues with removing\n✅ Unused files, \n✅ Unused npm dependencies, \n✅ Unneeded TypeScript exports.\n\n A real time-saver for maintaining a clean and efficient codebase. 🛠️ #ReactDevelopment \n\nhttps://t.co/IbJH2fIzsE", "entities": { "urls": [ { "url": "https://t.co/IbJH2fIzsE", "expanded_url": "https://github.com/webpro-nl/knip", "display_url": "github.com/webpro-nl/knip" } ], "hashtags": [{ "tag": "ReactDevelopment" }] } }, "entities": { "annotations": [ { "probability": 0.743, "type": "Other", "normalized_text": "Knip" }, { "probability": 0.7667, "type": "Other", "normalized_text": "Knip" } ], "urls": [ { "url": "https://t.co/P39xg0qCrT", "expanded_url": "https://twitter.com/i/web/status/1693502146128281657", "display_url": "twitter.com/i/web/status/1…" } ] }, "author_id": "827145937030148097", "text": "Streamlining React projects with Knip:\n\nRecently, I employed Knip for a project, and it worked wonders! \n\nIt efficiently resolved issues with removing\n✅ Unused files, \n✅ Unused npm dependencies, \n✅ Unneeded TypeScript exports.\n\n A real time-saver for maintaining a clean and… https://t.co/P39xg0qCrT", "id": "1693502146128281657", "created_at": "2023-08-21T05:55:50.000Z", "edit_history_tweet_ids": ["1693502146128281657"] }, { "entities": { "annotations": [ { "probability": 0.9331, "type": "Other", "normalized_text": "JavaScript" }, { "probability": 0.5907, "type": "Other", "normalized_text": "Knip" } ] }, "author_id": "18191376", "text": "Found a bunch of unused code, -dependencies, and unnecessary exports. Had just one false positive but overall pretty good. 10/10 would recommend.\n\nIf you’ve got a JavaScript package/project use Knip and remove unnecessary code. ✂️", "id": "1692942539614028086", "created_at": "2023-08-19T16:52:09.000Z", "edit_history_tweet_ids": ["1692942539614028086"] } ], "includes": { "media": [ { "media_key": "1", "url": "https://pbs.twimg.com/media/GDrwdB3aYAAu4am?format=png&name=orig", "type": "photo" }, { "media_key": "2", "url": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreihzszb56agbe6dtuf6xfutl65mjg5ethnrvw264d5bljbm377jora@jpeg", "type": "photo" }, { "media_key": "3_1730179997682552832", "url": "https://pbs.twimg.com/media/GALVin9a0AAsn0-.jpg", "type": "photo" }, { "media_key": "4", "url": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreid63o3hwvwpk6emgzj64vywusztofhz2yihuvwkywuuajn4eekvom@jpeg", "type": "photo" }, { "media_key": "5", "url": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreiahk2jbsb2stw276lkrkxrkvialqs25zrpgo2n3cigzfb7qvgfsmq@jpeg", "type": "photo" }, { "media_key": "6", "url": "https://pbs.twimg.com/media/G9wBaMFWoAAkgv5.png", "type": "photo" } ], "users": [ { "id": "11", "username": "julien.deniau.me", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:4dsclu5hjmht3shxutxtge6h/bafkreiht3iqxcmelwe7oysawrdpynzevf4dt2ndzeln4f5c2izf62zm57q@jpeg", "name": "Julien Deniau" }, { "id": "12", "username": "alexharfordseo.bsky.social", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:y3arowkhgiexpyvmmxvquavg/bafkreiazlcx5fdxylsqtsdng3beq3ayuoc7nzyqcddeequhi7uploqcjny@jpeg", "name": "AlexHarford-TechSEO" }, { "id": "13", "username": "fubits.dev", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:6aglx53tojyuwxwueap5og3h/bafkreiclnob3mnfvo74an6ugrnbdikrkxcskndjojrdtkwf5vwjuu77z5u@jpeg", "name": "Ilja" }, { "id": "14", "username": "alexanderkaran.bsky.social", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:3n4fccuhdomkkebojjdurnco/bafkreiggltcvdoh4igf5yxvrxggysmasv5efn6hffyav2o6swxslbc3lp4@jpeg", "name": "Alexander Karan" }, { "id": "15", "username": "patak.dev", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreifgzl4e5jqlakd77ajvnilsb5tufsv24h2sxfwmitkzxrh3sk6mhq@jpeg", "name": "patak" }, { "id": "16", "username": "psparwez", "profile_image_url": "https://unavatar.io/x/psparwez", "name": "PS" }, { "id": "17", "username": "k_shehadeh", "profile_image_url": "https://unavatar.io/x/k_shehadeh", "name": "Karim Shehadeh" }, { "id": "18", "username": "cramforce", "profile_image_url": "https://unavatar.io/x/cramforce", "name": "Malte Ubl" }, { "id": "1", "username": "sqs", "profile_image_url": "https://pbs.twimg.com/profile_images/1519180377604034560/NxI03WYE_400x400.jpg", "name": "Quinn Slack" }, { "id": "2", "username": "jokull", "profile_image_url": "https://pbs.twimg.com/profile_images/1943338796122083328/NsFCJwMd_400x400.jpg", "name": "Jökull Solberg" }, { "id": "3", "username": "Hicksyfern", "profile_image_url": "https://pbs.twimg.com/profile_images/1559181703352094720/NFL2PBbK_400x400.jpg", "name": "Tom Hicks" }, { "id": "4", "username": "daviduzumeri.bsky.social", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:6ykajndqngy2kxozo37mpsgc/bafkreif2xu6bini3tpv2hfauw53ng43zbefgqol36yt4baehcbdfxahihu@jpeg", "name": "Old Man Uzi" }, { "id": "5", "username": "gary__tyr", "profile_image_url": "https://pbs.twimg.com/profile_images/1947080916045631488/m42HwWiy_400x400.jpg", "name": "Gary Tyr" }, { "id": "6", "username": "KevinVanCott", "profile_image_url": "https://pbs.twimg.com/profile_images/1419785698887012357/V533Pwsr_400x400.jpg", "name": "Kevin Thomas Van Cott" }, { "id": "7", "username": "joshuakgoldberg.com", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:hwtki3j7oghodc7h6gqnrtro/bafkreicvkrpjmc7yoviwf5vhkecgcgyn23x24ix4aqdwiikcl226c64k2q@jpeg", "name": "Josh Goldberg 💖" }, { "id": "8", "username": "beaussan.io", "profile_image_url": "https://cdn.bsky.app/img/avatar/plain/did:plc:opw3iapscc55nlgrx6q2yjah/bafkreiaj72657msogojjdk4wr76fe3umimydon3pzzrquuj7opcftntrqa@jpeg", "name": "Nicolas Beaussart" }, { "id": "9", "username": "MidnightDesign", "name": "Rudolph Gottesheim", "profile_image_url": "https://avatars.githubusercontent.com/u/743172?v=4" }, { "id": "10", "username": "stephaneledorze", "name": "stephane le dorze", "profile_image_url": "https://pbs.twimg.com/profile_images/1587561006317899777/y8cgxyI7_400x400.jpg" }, { "id": "22918124", "username": "gregberge_", "profile_image_url": "https://pbs.twimg.com/profile_images/1722358890807861248/75S7CB3G_normal.jpg", "name": "Greg Bergé" }, { "id": "19268321", "username": "housecor", "profile_image_url": "https://pbs.twimg.com/profile_images/1963593369306750976/7gPWqEa8_400x400.jpg", "name": "Cory House" }, { "id": "3126044440", "username": "pkgacek", "profile_image_url": "https://pbs.twimg.com/profile_images/585047168899244033/kpQ-Reb7_normal.jpg", "name": "Piotr Gacek 🐟" }, { "id": "95668959", "username": "kuizinas", "profile_image_url": "https://pbs.twimg.com/profile_images/1978959812172894209/yQXTNMuJ_400x400.jpg", "name": "Gajus" }, { "id": "1632752318994153472", "username": "imabhiprasad", "profile_image_url": "https://pbs.twimg.com/profile_images/1917768224612962304/7RHnN131_400x400.jpg", "name": "Abhijeet Prasad" }, { "id": "1513218780167655427", "username": "fernandoeeu_dev", "profile_image_url": "https://pbs.twimg.com/profile_images/1513219705317822473/9CR0LjqB_normal.jpg", "name": "Fernando" }, { "id": "44217212", "username": "TkDodo", "profile_image_url": "https://pbs.twimg.com/profile_images/1803004614372937728/OSIQ4AGx_400x400.jpg", "name": "Dominik 🔮" }, { "id": "481186762", "username": "Mokkapps", "profile_image_url": "https://pbs.twimg.com/profile_images/1825498937911889920/FtBqvqgK_400x400.jpg", "name": "Michael Hoffmann" }, { "id": "416394303", "username": "nicoespeon", "profile_image_url": "https://pbs.twimg.com/profile_images/1649018862527041536/9s6Nlwyj_normal.jpg", "name": "Nicolas Carlo" }, { "id": "15736190", "username": "smashingmag", "profile_image_url": "https://pbs.twimg.com/profile_images/1669591955653685248/mTxJyTGY_normal.jpg", "name": "Smashing Magazine 🇺🇦 🏳️‍🌈" }, { "id": "21046936", "username": "danvdk", "profile_image_url": "https://pbs.twimg.com/profile_images/485135064557035520/zATSd81r_normal.jpeg", "name": "Dan Vanderkam" }, { "id": "380616577", "username": "stefanjudis", "profile_image_url": "https://pbs.twimg.com/profile_images/1465780299380502537/pptBYF44_normal.jpg", "name": "Stefan Judis" }, { "id": "827145937030148097", "username": "BKailaash", "profile_image_url": "https://pbs.twimg.com/profile_images/839048279442718720/SiC-Q2Nc_normal.jpg", "name": "Kailaash" }, { "id": "18191376", "username": "waldekm", "profile_image_url": "https://pbs.twimg.com/profile_images/1670040743006617602/N5VnH4YU_normal.jpg", "name": "Waldek Mastykarz" } ] } } ================================================ FILE: packages/docs/src/components/Contributors.astro ================================================ --- import { readFile } from 'node:fs/promises'; const ENVIRONMENT = import.meta.env.ENVIRONMENT; const GITHUB_TOKEN = import.meta.env.GITHUB_TOKEN; const isFetch = ENVIRONMENT !== 'development' && Boolean(GITHUB_TOKEN); interface Contributor { html_url: string; avatar_url: string; login: string; } const url = new URL('/repos/webpro-nl/knip/contributors', 'https://api.github.com'); url.searchParams.set('per_page', '100'); const getAllContributors = async (url: URL) => { const allContributors: Contributor[] = []; let nextUrl: string = url.href; console.log('\n'); while (nextUrl) { console.log(`Fetching contributors from ${nextUrl}`); const response = await fetch(nextUrl, { headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${GITHUB_TOKEN}`, 'X-GitHub-Api-Version': '2022-11-28', }, }); if (!response.ok) { console.error('GitHub API request failed:'); console.log(await response.text()); return []; } const contributors = await response.json(); allContributors.push(...contributors); const linkHeader = response.headers.get('Link'); nextUrl = linkHeader?.match(/<([^>]+)>;\s*rel="next"/)?.[1] || ''; } return allContributors; }; const contributors: Contributor[] = isFetch ? await getAllContributors(url) : JSON.parse(await readFile('mock/contributors.json', 'utf-8')); if (!Array.isArray(contributors)) console.log(contributors); ---
{ (Array.isArray(contributors) ? contributors : []).map(contributor => ( {contributor.login} )) }
================================================ FILE: packages/docs/src/components/EmojiBlastButton.astro ================================================
================================================ FILE: packages/docs/src/components/Footer.astro ================================================ --- import Default from '@astrojs/starlight/components/Footer.astro'; ---

ISC License © 2024 Lars Kappert

================================================ FILE: packages/docs/src/components/Head.astro ================================================ --- import Default from '@astrojs/starlight/components/Head.astro'; const slug = Astro.locals.starlightRoute.slug; const url = new URL(Astro.url); url.pathname = `/og/docs${slug ? `/${slug}` : ''}.webp`; --- ================================================ FILE: packages/docs/src/components/Post.astro ================================================ --- import { formatTimestamp, type PostWithUser, replaceShortenedUrls } from '../util/post.js'; const post: PostWithUser = replaceShortenedUrls(Astro.props.data); --- { post && ( <>
{post.user.name} @{post.user.username}

')} />

17 ? `https://twitter.com/${post.user.username}/status/${post.id}` : `https://bsky.app/profile/${post.user.username}/post/${post.id}`}`}> {formatTimestamp(post.created_at)}

) } ================================================ FILE: packages/docs/src/components/Posts.astro ================================================ --- import { readFile } from 'node:fs/promises'; import { Card, CardGrid } from '@astrojs/starlight/components'; import type { PostResponse } from '../util/post.js'; import Post from './Post.astro'; const testimonials: PostResponse = JSON.parse(await readFile('src/assets/testimonials.json', 'utf-8')); ---
{ testimonials.data.map(testimonial => { return ( user.id === testimonial.author_id ), media: testimonials.includes.media?.filter(media => testimonial.entities.urls ?.map(url => url.media_key) .includes(media.media_key) ), }} /> ); }) }
================================================ FILE: packages/docs/src/components/Projects.astro ================================================ --- import Adobe from '../assets/projects/adobe.svg'; import AGGrid from '../assets/projects/ag-grid.svg'; import AGGrid2 from '../assets/projects/ag-grid2.svg'; import Anthropic from '../assets/projects/anthropic.svg'; import ArkType from '../assets/projects/arktype.svg'; import AstroLogo from '../assets/projects/astro.svg'; import AWS from '../assets/projects/aws.svg'; import Backstage from '../assets/projects/backstage.svg'; import Cloudflare from '../assets/projects/cloudflare.svg'; import CreateTypeScriptApp from '../assets/projects/create-typescript-app.png'; import Datadog from '../assets/projects/datadog.svg'; import ESLint from '../assets/projects/eslint.svg'; import FreeCodeCamp from '../assets/projects/freecodecamp.svg'; import Google from '../assets/projects/google.svg'; import Grafana from '../assets/projects/grafana.svg'; import Guardian from '../assets/projects/guardian.svg'; import Microsoft from '../assets/projects/microsoft.svg'; import Mocha from '../assets/projects/mocha.svg'; import Nuxt from '../assets/projects/nuxt.svg'; import Prettier from '../assets/projects/prettier.svg'; import Sanity from '../assets/projects/sanity.svg'; import SAP from '../assets/projects/sap.svg'; import Sentry from '../assets/projects/sentry.svg'; import Shopify from '../assets/projects/shopify.svg'; import SourceGraph from '../assets/projects/sourcegraph.svg'; import Stately from '../assets/projects/stately.svg'; import Storybook from '../assets/projects/storybook.svg'; import Svelte from '../assets/projects/svelte.svg'; import TanStack from '../assets/projects/tanstack.png'; import TypeScriptESLint from '../assets/projects/typescript-eslint.svg'; import Vercel from '../assets/projects/vercel.svg'; ---
================================================ FILE: packages/docs/src/components/Sponsors.astro ================================================ --- const { showAll = true } = Astro.props; --- ================================================ FILE: packages/docs/src/components/SponsorsChart.astro ================================================ --- import Chart from '../assets/venz-chart.svg'; --- ================================================ FILE: packages/docs/src/content/docs/blog/brief-history.md ================================================ --- title: A Brief History Of Knip date: 2023-10-15 sidebar: order: 8 --- _Published: 2023-10-15_ If you are fond of short lists and brief histories, then this page was written just for you! - 2022-10-04: The [initial commit][1]. Still so tiny at that point, but the seed was planted. Starting out with finding unused files and exports, the name was Exportman! 🦸 - 2022-10-09: Big plans and a rename 5 days later, the first published version of Knip was [v0.1.2][2]. - 2022-11-22: Unused dependencies and support for workspaces and plugins in the [first alpha of v1][3]. - 2023-01-10: Lots of testing and fixes led to [Knip v1][4]. - 2023-03-22: [Knip v2][5] saw a full rewrite of the TypeScript backend. - 2023-10-15: [Introduction of Knip v3][6]. [1]: https://github.com/webpro-nl/knip/commit/9589dfe22608da7d89f2613383da6db5826226d2 [2]: https://github.com/webpro-nl/knip/tree/0.1.2 [3]: https://github.com/webpro-nl/knip/releases/tag/1.0.0-alpha.0 [4]: https://github.com/webpro-nl/knip/tree/1.0.0 [5]: https://github.com/webpro-nl/knip/issues/73 [6]: ./knip-v3.mdx ================================================ FILE: packages/docs/src/content/docs/blog/for-editors-and-agents.md ================================================ --- title: Knip for Editors & Agents date: 2025-12-17 sidebar: order: 2 --- _Published: 2025-12-17_ Three years in, Knip has found its place in [over 10.000 projects][1] and is downloaded [over 18M times/month][2]. A long period of steady growth in usage and stability allows Knip to become more accessible to more people. That's why I'm excited and proud to introduce the brand new [Editor Extension][3] **and** MCP Server. For humans and coding agents alike, Knip will help keep your codebases tidy. Don't forget... Knip it before you ship it! ## Editor Extension This one is for you. [The usual suspects][4] like red squiggles for unused exports are there. What really moves the needle for DX with Knip's module graph is **navigation**. A completely unique way to view & fly through codebases. Connect the dots during development and refactors, while keeping things in check. We're starting out with [3 key features][5]: 1. **Hover over Export** for import & usage locations 2. **Imports Tree View** for direct links to implementations 3. **Exports Tree View** for direct links to import & usage locations The extension has a [built-in MCP Server][6] with a command and resources to configure Knip for you, _completely automated_. Find [Knip on the VS Code Marketplace][7] and find [Knip in the Open VSX Registry][8]. ## MCP Server Configuring Knip has always been a major headache to many. No more. Tell your coding agent to "configure knip" and it will RTFM so you don't have to. Using a newer model like Opus 4.5 or GPT 5.2 results in an optimized `knip.json` file and an uncluttered codebase. The [MCP Server is available][9] separately and built into the VS Code Extension. ## Language Server The VS Code Extension and the MCP Server are powered by the new Language Server. It's a custom server that builds the full module graph of your project, and provides a session with a graph explorer to request all sorts of interesting information. Queries like "where is an export imported" or "is this import part of a circular dependency" are just scratching the surface here. Extensions for other IDEs can be built on top. See [language-server/README.md][10] ## Screenshots - [Lint Findings][4] - [Imports & Exports][5] - [Contention][11] - [Circular Dependencies][12] - [Conflicts][13] - [Branching][14] - [VS Code Extension Settings][15] ### Lint Findings ![Lint Findings][16] ### Imports & Exports ![hover][17] ### Contention The IDE extension shows extra issues in the tree views like circular dependencies. We're starting out with some extra novelties like conflicting and branched/diamond-shaped import chains. #### Circular Dependencies If an import is part of a circular dependency, Knip will display: ![Circular Dependencies][18] #### Conflicts TypeScript shows direct conflicts when importing or re-exporting the same named export from different files. Except when the problem is more subtle and the chain spans more than one file. Knip warns: ![Conflicts][19] #### Branching Branched or diamond-shaped imports chains indicate unnecessary re-exports and complexity. They help to untangle large codebases and shrink or get rid of barrel files. Knip warns: ![Branching][20] ### VS Code Extension Settings ![VS Code Extension Settings][21] [1]: https://github.com/webpro-nl/knip/network/dependents [2]: https://www.npmjs.com/package/knip [3]: #editor-extension [4]: #lint-findings [5]: #imports--exports [6]: #mcp-server [7]: https://marketplace.visualstudio.com/items?itemName=webpro.vscode-knip [8]: https://open-vsx.org/extension/webpro/vscode-knip [9]: https://www.npmjs.com/package/@knip/mcp [10]: https://github.com/webpro-nl/knip/blob/main/packages/language-server/README.md [11]: #contention [12]: #circular-dependencies [13]: #conflicts [14]: #branching [15]: #vs-code-extension-settings [16]: /screenshots/editors-and-agents/diagnostics.webp [17]: /screenshots/editors-and-agents/imports-exports.webp [18]: /screenshots/editors-and-agents/circular-dependency.webp [19]: /screenshots/editors-and-agents/conflict.webp [20]: /screenshots/editors-and-agents/branch.webp [21]: /screenshots/editors-and-agents/vscode-extension-settings.webp ================================================ FILE: packages/docs/src/content/docs/blog/knip-v3.mdx ================================================ --- title: Announcing Knip v3 date: 2023-10-15 sidebar: order: 9 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; _Published: 2023-10-15_ Lots of new users got introduced to Knip, coming with clear bug reports, helpful insights, superb reproductions and great suggestions this year. You're all a friendly and helpful bunch! Recently I've opened a Discord channel where more communication, collaboration, ideas and updates are happening: feel free to join [The Knip Barn][1]! Today, Knip has [over 140k weekly downloads on npm][2], [almost 4000 stars on GitHub][3], and [over 500 repositories][4] using it. While numbers are just numbers, they do add to the positive feedback I'm receiving daily. Everything combined makes me think I'm on the right track which is very motivating to keep working on Knip. ## So... What's Been Cooking Lately? - Migration to a monorepo setup - This very website built with Starlight 🌟 - Extended documentation for just about everything - Improved JSON reporter for external integrations (e.g. [GitHub Action][5]) - Some breaking changes, but you probably don't need to make any changes ## Breaking Changes A major bump comes with breaking changes, but most likely no changes necessary on your end: - Removed support for Node.js v16, Knip v3 requires at least Node.js v18.6 - Simplified [exit codes][6] - [Production mode][7] now includes types by default (add `--exclude types` for previous behavior) - Removed `--ignore-internal` flag; [`@internal`][8] exports ignored in production mode now - The `--debug-file-filter` flag is removed - The `jsonExt` reporter is now the default [JSON reporter][9] (the previous one is gone) - Moved `typescript` to `peerDependencies` (requires `>=5.0.4`) ## Installation Try out the latest Knip v3 release today! ```shell npm install -D knip ``` ```shell pnpm add -D knip ``` ```shell bun add -D knip ``` ```shell yarn add -D knip ``` Remember, Knip it before you ship it! Have a great day ☀️ [1]: https://discord.gg/r5uXTtbTpc [2]: https://www.npmjs.com/package/knip [3]: https://github.com/webpro-nl/knip/stargazers [4]: https://github.com/webpro-nl/knip/network/dependents [5]: https://github.com/marketplace/actions/knip-reporter [6]: ../reference/cli.md#--no-exit-code [7]: ../features/production-mode.md [8]: ../reference/jsdoc-tsdoc-tags.md#internal [9]: ../features/reporters.md#json ================================================ FILE: packages/docs/src/content/docs/blog/knip-v4.mdx ================================================ --- title: Announcing Knip v4 date: 2024-01-16 sidebar: order: 6 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; _Published: 2024-01-16_ I'm happy to announce that Knip v4 is available! The work took over a month and the process of [slimming down to speed up][1] ended up really well: significant faster runs and reduced memory usage. In the meantime, v3 continued to receive more contributions, plugins and bug fixes. ## Highlights Compared to v3, here are the highlights: - Performance: significant speed bump (up to 80%!) - Performance: globbing in combo with `.gitignore` is a lot more efficient - Configuration: [built-in compilers][2] (for Astro, MDX, Svelte & Vue) - The `ignore` option has been improved - Internal refactoring to serialize data for future improvements like caching. The actual performance win in your projects depends on various factors like size and complexity. ## Major Changes The changes have been tested against various repositories, but it's possible that you will encounter false positives caused by the major refactoring that has been done. If you do, [please report][3]! ### Unused Class Members Finding unused class members is no longer enabled by default. Here's why it's now opt-in: - When using Knip for the first time on a large repository it can crash after a while with an out of memory error. This is a terrible experience. - Plenty of codebases don't use classes at all, keeping TS programs in memory is a waste of resources. - Many configurations already exclude `classMembers` from the output. Enable unused class members by using the CLI argument or the configuration option: ```shell knip --include classMembers ``` ```json { "include": ["classMembers"] } ``` Now that unused class members is opt-in and better organized within Knip, it might be interesting to start looking at opt-ins for other unused members, such as those of types and interfaces. By the way, enum members are "cheap" with the v4 refactor, so those are still included by default. ### Compilers You can remove the `compilers` option from your configuration. Since you can override them, your custom compilers can stay where they are. This also means that you can go back from `knip.ts` to `knip.json` if you prefer. ### Ignore Files The `ignore` option accepted patterns like `examples/`, but if you want to ignore the files inside this folder you should update to globs like `examples/**`. ## What's Next? The refactoring for this release opens the door to more optimizations, such as caching. I'm also very excited to see how deeper integrations such as in GitHub Actions or IDEs like VS Code or WebStorm may further develop. Remember, if you are you using Knip at work your company can [sponsor me][4]! ## One More Thing... An idea I've been toying with is "tagged exports". The idea is that you can tag exports in a JSDoc comment. The tag does not need to be part of the JSDoc or TSDoc spec. For example: ```ts /** @custom */ export const myExport = 1; ``` Then, include or exclude such tagged exports from the report like so: ```shell knip --experimental-tags=+custom knip --experimental-tags=-custom,-internal ``` This way, you can either focus on or ignore specific tagged exports with tags you define yourself. This also works for individual class or enum members. Once this feature is intuitive and stable, the `experimental` flag will be removed and option(s) added to the Knip configuration file. The docs are in the [CLI reference][5]. ## Let's Go! What are you waiting for? Start using Knip v4 today! ```shell npm install -D knip ``` ```shell pnpm add -D knip ``` ```shell bun add -D knip ``` ```shell yarn add -D knip ``` Remember, Knip it before you ship it! Have a great day ☀️ [1]: ./slim-down-to-speed-up.md [2]: ../features/compilers.md [3]: ../guides/issue-reproduction.md [4]: https://github.com/sponsors/webpro [5]: ../reference/cli.md#--tags ================================================ FILE: packages/docs/src/content/docs/blog/knip-v5.mdx ================================================ --- title: Announcing Knip v5 date: 2024-02-10 sidebar: order: 5 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; _Published: 2024-02-10_ Today brings the smallest major release so far. Tiny yet mighty! Below are two cases to demonstrate the change in how unused exports are reported. ## Case 1 The first case shows two exports with a namespaced import that references one of those exports explicitly: ```ts title="knip.js" export const version = 'v5'; export const getRocket = () => '🚀'; ``` ```ts title="index.js" import * as NS from './knip.js'; console.log(NS.version); ``` In this case we see that `getRocket` is an unused export. Previously it would go into the "Unused exports in namespaces" category (`nsExports`). This issue has been moved to the "Unused exports" category (`exports`). ## Case 2 The second case is similar, but only the imported namespace itself is referenced. None of the individual exports is referenced: ```ts title="index.js" import * as NS from './knip.js'; import send from 'stats'; send(NS); ``` Are the `version` and `getRocket` exports used? We can't know. The same is true for the spread object pattern: ```ts title="index.js" import * as NS from './knip.js'; const Spread = { ...NS }; ``` Previously those exports would go into the "Unused exports in namespaces" category. This is still the case, but this category is no longer enabled by default. ## Include unused exports in namespaces To enable this type of issues in Knip v5, add this argument to the command: ```shell knip --include nsExports ``` Or in your configuration file: ```json title="knip.json" { "include": ["nsExports", "nsTypes"] } ``` Now `version` and `getRocket` will be reported as "Unused exports in namespaces". Note that `nsExports` and `nsTypes` are split for more granular control. ## Handling exports in namespaced imports You have a few options to handle namespaced imports when it comes to unused exports. ### 1. Use named imports Regardless of whether `nsExports` is enabled or not, it's often good practice to replace the namespaced imports with named imports: ```ts title="index.js" import { version, getRocket } from './knip.js'; send({ version, getRocket }); ``` Whenever possible, explicit over implicit is often the better choice. ### 2. Standardized JSDoc tags Using one of the available JSDoc tags like `@public` or `@internal`: ```ts title="knip.js" export const version = 'v5'; /** @public */ export const getRocket = () => '🚀'; ``` Assuming only imported using a namespace (like in the example cases above), this will exclude the `getRocket` export from the report, even though it isn't explicitly referenced. ### 3. Arbitrary JSDoc tags Another solution is to tag individual exports arbitrarily: ```ts title="knip.js" export const version = 'v5'; /** @launch */ export const getRocket = () => '🚀'; ``` And then exclude the tag like so: ```shell $ knip --experimental-tags=-launch Exports in used namespace (1) version NS unknown knip.js:1:1 ``` Assuming only imported using a namespace (like in the example cases above), this will exclude the `getRocket` export from the report, even though it isn't explicitly referenced. ## A better default I believe this behavior in v5 is the better default: have all exports you want to know about in a single category, and those you probably want to ignore in another that's disabled by default. Before the [v4 refactoring][1], this would be a lot harder to implement. That refactoring turns out to be a better investment than expected. Combined with a better understanding of how people write code and use Knip, this change is a natural iteration. Why the major bump? It's not breaking for the large majority of users, but for some it may be breaking. For instance when relying on the [JSON reporter][2], other reporter output, or custom [preprocessing][3]. It's not a bug fix, it's not a new feature, but since semver is all about setting expectations I feel the change is large enough to warrant a major bump. ## Let's Go! What are you waiting for? Start using Knip v5 today! ```shell npm install -D knip ``` ```shell pnpm add -D knip ``` ```shell bun add -D knip ``` ```shell yarn add -D knip ``` Remember, Knip it before you ship it! Have a great day ☀️ [1]: ../blog/slim-down-to-speed-up.md [2]: ../features/reporters.md#json [3]: ../features/reporters.md#preprocessors ================================================ FILE: packages/docs/src/content/docs/blog/knip-v6.md ================================================ --- title: Announcing Knip v6 date: 2026-03-20 sidebar: order: 1 --- _Published: 2026-03-20_ ## Knip v6 is out! This release is all about replacing the TypeScript backend entirely with `oxc-parser` and `oxc-resolver`, and making Knip a whole lot faster! ## From TypeScript to oxc Two years ago, the ["slim down to speed up"][1] and [Knip v4][2] work removed a lot of overhead around TypeScript programs, made serialization and caching practical, and improved memory efficiency a lot. But there was still a ceiling: parsing and module resolution still depended on TypeScript APIs designed for IDEs and language servers — not for the kind of single-pass static analysis Knip does. Starting today, Knip v6 parses your source files with [oxc-parser][3]. This is more than just a parser swap for the sake of using the latest 'n greatest. Knip has always been designed to parse each file only once, but the TypeScript backend carried the overhead of wiring up an entire program along with the typechecker. That's useful for IDEs keeping symbols connected, but much less so when you only need to traverse an AST once to collect imports and exports. The TypeScript backend made the setup as a whole harder and slower than it needed to be, especially to keep large monorepos in check. Now with TypeScript itself Go-ing places, replacing that backend was only a matter of time. Unsurprisingly, the search didn't take long: `oxc-parser` offers everything we need and its (experimental) raw transfer is crazy fast. Massive props to [overlookmotel][4], [Boshen][5] and all contributors for all the work on [the oxc suite][6]! ## Performance tuning Next to this major refactor, I've been having a ball tuning Knip's performance further. One thing to highlight here is that a few more plugins have been refactored to statically analyze configuration files directly, as opposed to actually importing them (including transitive dependencies...). This includes the ESLint ("flat config"), tsdown and tsup plugins. ## The numbers Comparing v5 and v6 in some projects using Knip, all boosts are in the **2-4x** range: [![venz-chart][8]][7] Trust me, I could look at this chart all day long! The same numbers in a table: | Project | v5.88.0 | v6.0.0 | | ---------------- | ------: | -----: | | [astro][9] | 4.0s | 2.0s | | [query][10] | 3.8s | 1.7s | | [rolldown][11] | 3.7s | 1.7s | | [sentry][12] | 11.0s | 4.0s | | [TypeScript][13] | 3.7s | 0.9s | ## What's new - Did I already mention Knip got 2-4x faster? - Support for TS namespaces (and modules), new issue type `namespaceMembers`: ```ts export namespace MyNamespace { export const myName = 'knip'; // we were ignored in v5, export type MyType = string; // yet in v6 we are included } ``` ## Breaking changes Granted, most of you won't even notice. Here's the list: - Dropped support for Node.js v18 → Knip v6 requires Node.js v20.19.0 or newer - Dropped issue type `classMembers` - Dropped `--include-libs` → this is now the default and only behavior - Dropped `--isolate-workspaces` → this is now the default and only behavior - Dropped `--experimental-tags` → use [`--tags`][14] - In [reporter functions][15], `issues.files` is consistent with other issue shapes. Removed `issues._files`. - In the [JSON reporter][16], issues are consistently arrays for any issue type. Removed root `files`. ## Editor Extensions [Editor extensions][17] benefit from the core upgrades, for being faster and more memory-efficient. Regardless of new extension releases, the local version of Knip will be detected and used. Upgrade `knip` in your dependencies when you're ready. ## What about classMembers? I feel you. Even Knip itself was using it. Until today. The problem is that the implementation relies on the JS-based `ts.LanguageService` API that exposes the `findReferences` method. TypeScript v6 is the last JS-based release, and TypeScript v7 is a full rewrite in Go. I am left wondering if it ever will be feasible and practical to build such features using primitives (i.e. not via LSP) in a JS-based CLI (references: [microsoft/typescript-go#455][18], [@typescript/api][19]). Knip was already pretty unique for even trying this in a CLI tool. Not that many projects seem to be using it either: [github.com search for "classMembers path\:knip.json"][20]. If your project relies on it, feel free to open an issue on GitHub or contact me and maybe we can work something out. Maybe a separate dedicated tool could work, or extended support for Knip v5. ## Upgrade today ```sh npm install -D knip@latest ``` ## Deep closing thoughts... Remember, Knip it before you ship it! Have a great day ☀️ [1]: ./slim-down-to-speed-up.md [2]: ./knip-v4.mdx [3]: https://oxc.rs/docs/guide/usage/parser [4]: https://github.com/overlookmotel [5]: https://github.com/Boshen [6]: https://oxc.rs [7]: https://try.venz.dev/?type=bar&labelX=Knip&labelY=duration+(s)&label=astro&label=query&label=rolldown&label=sentry&label=typescript&l=v5.88.0&l=v6.0.0&data=4*2&data=3.8*1.7&data=3.7*1.7&data=11*4&data=3.7*0.9 [8]: https://cdn.venz.dev/i/chart.svg?pad=0&type=bar&labelX=Knip&labelY=duration+(s)&label=astro&label=query&label=rolldown&label=sentry&label=typescript&l=v5.88.0&l=v6.0.0&data=4*2&data=3.8*1.7&data=3.7*1.7&data=11*4&data=3.7*0.9&theme=dark [9]: https://github.com/withastro/astro [10]: https://github.com/TanStack/query [11]: https://github.com/rolldown/rolldown [12]: https://github.com/getsentry/sentry [13]: https://github.com/microsoft/TypeScript [14]: ../reference/configuration.md#tags [15]: ../features/reporters.md#custom-reporters [16]: ../features/reporters.md#json [17]: ../reference/integrations.md [18]: https://github.com/microsoft/typescript-go/discussions/455 [19]: https://github.com/microsoft/typescript-go/tree/main/_packages/api [20]: https://github.com/search?q=classMembers%20path%3Aknip.json&type=code ================================================ FILE: packages/docs/src/content/docs/blog/migration-to-v1.md ================================================ --- title: Migration to v1 --- _2023-01-04_ When coming from version v0.13.3 or before, there are some breaking changes: - The `entryFiles` and `projectFiles` options have been renamed to `entry` and `project`. - The `--dev` argument and `dev: true` option are gone, this is now the default mode (see [production mode][1]). - Workspaces have been moved from the root of the config to the `workspaces` key (see [workspaces][2]). - The `--dir` argument has been renamed to `--workspace`. ## Example A configuration like this in v0.13.3 or before... ```json { "entryFiles": ["src/index.ts"], "projectFiles": ["src/**/*.ts", "!**/*.spec.ts"], "dev": { "entryFiles": ["src/index.ts", "src/**/*.spec.ts", "src/**/*.e2e.ts"], "projectFiles": ["src/**/*.ts"] } } ``` ...should become this for v1... ```json { "entry": ["src/index.ts!"], "project": ["src/**/*.ts!"] } ``` Much cleaner, right? For some more details: - The `dev` property for the `--dev` flag is now the default mode. - Use `--production` to analyze only the `entry` and `project` files suffixed with `!`. - The glob patterns for both types of test files (`*.spec.ts` and `*.e2e.ts`) are no longer needed: - Regular test files like `*.test.js` and `*.spec.ts` etc. are automatically handled by Knip. - The `*.e2e.ts` files is configured with the Cypress or other plugin. Note that Cypress uses `*.cy.ts` for spec files, but this could be overridden like so: ```json { "entry": "src/index.ts!", "project": "src/**/*.ts!", "cypress": { "entry": "src/**/*.e2e.ts" } } ``` [1]: ../features/production-mode.md [2]: ../features/monorepos-and-workspaces.md ================================================ FILE: packages/docs/src/content/docs/blog/release-notes-v2.md ================================================ --- title: Release Notes v2 sidebar: order: 10 --- _2023-03-22_ ## Breaking changes When coming from v1, there are no breaking changes in terms of configuration. ## Changes There are some changes regarding CLI arguments and output: - Knip now runs on every \[workspace]\[1] automatically (except for the ones in `ignoreWorkspaces: []`). - The "Unlisted or unresolved dependencies" is split in "Unlisted dependencies" and "Unresolved imports". - Bug fixes and increased correctness impact output (potentially causing CI to now succeed or fail). ## New features Rewriting a major part of Knip's core from scratch allows for some new exciting features: - **Performance**. Files are read only once, and their ASTs are traversed only once. Projects of any size will notice the difference. Total running time for some projects decreases with 90%. - **Compilers**. You can now include other file types such as `.mdx`, `.vue` and `.svelte` in the analysis. Internally, the `ts-morph` dependency is replaced by `typescript` itself. ## Other improvements - Improved support for workspaces. - Improved module resolutions, self-referencing imports, and other things you don't want to worry about. - Configure `ignoreDependencies` and `ignoreBinaries` at the workspace level. - Simplified plugins model: plugin dependency finder may now return any type of dependency in a single array: npm packages, local workspace packages, local files, etc. (module and path resolution are handled outside the plugin). - Many bugfixes. ================================================ FILE: packages/docs/src/content/docs/blog/slim-down-to-speed-up.md ================================================ --- title: Slim down to speed up date: 2023-12-14 sidebar: order: 7 --- _Published: 2023-12-14_ **tl;dr;** Memory usage is up to 50% lower, runs are up to 60% faster and you can start using v4 canary today. No "unused class members" for the time being, but this feature is planned to be restored. ## Introduction Honestly, performance has always been a challenge for Knip. A longstanding bottleneck has finally been eliminated and Knip is going to be a lot faster. Skip straight to the bottom to install v4 canary and try it out! Or grab yourself a nice drink and read on if you're interested in where we are coming from, and where we are heading. ## Projects & Workspaces From the start, Knip has relied on TypeScript for its robust parser for JavaScript and TypeScript files. And on lots of machinery important to Knip, like module resolution and accurately finding references to exported values. Parts of it can be customized, such as the (virtual) file system and the module resolver. In TypeScript terms, a "project" is like a workspace in a monorepo. Same as each workspace has a `package.json`, each project has a `tsconfig.json`. The `ts.createProgram()` method is used to create a program based on a `tsconfig.json` and the machinery starts to read and parse source code files, resolve modules, and so on. Up until v2, when Knip wanted to find unused things in a monorepo, all programs for all workspaces were loaded into memory. Workspaces often depend on each other, so Knip couldn't load one project, analyze it and dispose it. This way, connections across workspaces would be lost. ## Shared Workspaces Knip v2 said goodbye to this approach and implemented its own TypeScript backend (after using `ts-morph` for this). Based on the compatibility of `compilerOptions`, workspaces were merged into shared programs whenever possible. Having less programs in memory led to significant performance improvements. Yet ultimately it was still a stopgap, since everything was still kept in memory for the duration of the process. "Why does everything need to stay in memory?", you may wonder. The answer is that Knip uses `findReferences` at the end of the process. Knip relied on this TypeScript Language Server method for everything that's not easy to find. More about that later in [the story of findReferences][1] ## Serialization Fortunately, everything that's imported and exported from source files (including things like members of namespaces and enums) can be found relatively easily during AST traversal. This way, references to exports don't have to be "traced back" later on. It's mostly class members that are harder to find due to their dynamic nature. Without these, all information can be serialized for storage and retrieval (in memory or on disk). Slimming down by taking class members out of the equation simplifies things a lot and paves the way for all sorts of improvements. ## We Have To Slim Down The relevant part in the linting process can be summarized in 5 steps: 1. Collect entry files and feed them to TypeScript 2. Read files, resolve modules, and create ASTs 3. Traverse ASTs and collect imports & exports 4. Match exports against imports to determine what's unused 5. Find references to hard-to-find exported values and members If we would hold on to reporting unused class members, then especially steps 2 and 5 are hard to decouple. The program and the language service containing the source files used to eventually trace back references can't really be decoupled. So class members had to go. Sometimes you have to slim down to keep moving. One step back, two steps forward. If you rely on this feature, fear not. I plan to bring it back before the final v4, but possibly behind a flag. ## What's In Store? So with this out of the way, everything becomes a lot clearer and we can finally really start thinking about significant memory and performance improvements. So what's in store here? A lot! - We no longer need to keep everything in memory, so workspaces are read and disposed in isolation, one at a time. Memory usage will be spread out more even. This does not make it faster, but reducing "out of memory" issues is definitely a Good Thing™️ in my book. - Knip could recover from unexpected exits and continue from the last completed workspace. - The imports and exports are in a format that can be serialized for storage and retrieval. This opens up interesting opportunities, such as local caching on disk, skipping work in subsequent runs, remote caching, and so on. - Handling workspaces in isolation and serialization result in parallelization becoming a possibility. This becomes essential, as module resolution and AST creation and traversal are now the slowest parts of the process and are not easy to optimize significantly (unless perhaps switching to e.g Rust). - No longer relying on `findReferences` speeds up the export/import matching part part significantly. So far I've seen **improvements of up to 60% on total runtime**, and my guess is that some larger codebases may profit even more. - The serialization format is still being explored and there is no caching yet, but having the steps more decoupled is another Good Thing™️ that future me should be happy about. ## Back It Up, Please I heard you. Here's some example data. You can get it directly from Knip using the `--performance` flag when running it on any codebase. Below we have some data after linting the [Remix monorepo][2]. ### Knip v3 ```sh $ knip --performance Name size min max median sum ----------------------------- ---- ------ ------- ------- ------- findReferences 223 0.55 2252.35 8.46 5826.95 createProgram 2 50.78 1959.92 1005.35 2010.70 getTypeChecker 2 5.04 667.45 336.24 672.48 getImportsAndExports 396 0.00 7.19 0.11 104.46 Total running time: 9.7s (mem: 1487.39MB) ``` ### Knip v4 ```sh $ knip --performance ... Name size min max median sum ----------------------------- ---- ------ ------- ------- ------- createProgram 2 54.36 2138.45 1096.40 2192.81 getTypeChecker 2 7.40 664.83 336.12 672.23 getImportsAndExports 396 0.00 36.36 0.16 224.37 getSymbolAtLocation 2915 0.00 29.71 0.00 65.63 Total running time: 4.3s (mem: 729.67MB) ``` ### Takeaways The main takeaways here: - In v3,`findReferences` is where Knip potentially spends most of its time - In v4, total running time is down over 50% - In v4, memory usage is down 50% (calculated using `process.memoryUsage().heapUsage`) - In v4, `getImportsAndExports` is more comprehensive to compensate for the absence of `findReferences` - more on that below Remember, unused class members are no longer reported by default in v4. ## The story of `findReferences` Did I mention Knip uses `findReferences`...? Knip relied on it for everything that's not easy to find. Here's an example of an export/import match that **is** easy to find: ```ts title="import.ts" import { MyThing } from './thing.ts'; ``` ```ts title="export.ts" export const MyThing = 'cool'; ``` In v2 and v3, Knip collects many of such easy patterns. Other patterns are harder to find with static analysis. This is especially true for class members. Let's take a look at the next example: ```ts title="MyClass.ts" class MyClass { constructor() { this.method(); } method() {} do() {} } export const OtherName = MyClass; ``` ```ts title="instance.ts" import * as MyNamespace from './MyClass.ts'; const { OtherName } = MyNamespace; const instance = new OtherName(); instance.do(); ``` Without a call or `new` expression to instantiate `OtherName`, its `method` member would not be used (since the constructor would not be executed). To figure this out using static analysis goes a long way. Through export declarations, import declarations, aliases, initializers, call expressions... the list goes on and on. Yet all this magic is exactly what happens when you use "Find all references" or "Go to definition" in VS Code. Knip used `findReferences` extensively, but it's what makes a part of Knip rather slow. TypeScript needs to wire things up (through `ts.createLanguageService` and `program.getTypeChecker`) before it can use this, and then it tries hard to find all references to anything you throw at it. It does this very well, but the more class members, enum members and namespaced imports your codebase has, the longer it inevitably takes to complete the process. Besides letting go of class members, a slightly more comprehensive AST traversal is required to compensate for the absence of `findReferences` (it's the `getImportsAndExports` function in the metrics above). I'd like to give you an idea of what "more comprehensive" means here. In the following example, `referencedExport` was stored as export from `namespace.ts`, but it was not imported directly as such: ```ts title="namespace.ts" export const referencedExport = () => {}; ``` ```ts title="index.ts" import * as NS from './namespace.ts'; NS.referencedExport(); ``` Previously, Knip used `findReferences()` to "trace back" the usage of the exported `referencedExport`. The gist of the optimization is to pre-determine all imports and exports. During AST traversal of `index.ts` , Knip sees that `referencedExport` is attached to the imported `NS` namespace, and stores that as an imported identifier of `namespace.ts`. When matching exports against imports, this lookup comes at no extra cost. Additionally, this can be stored as strings, so it can be serialized too. And that means it can be cached. Knip already did this for trivial cases as shown in the first example of this article. This has now been extended to cover more patterns. This is also what needs to be tested more extensively before v4 can be released. Its own test suite and the projects in the integration tests are already covered so we're well on our way. For the record, `findReferences` is an absolute gem of functionality provided by TypeScript. Knip is still backed by TypeScript, and tries to speed things up by shaking things off. In the end it's all about trade-offs. ## Let's Go! You can start using Knip v4 today, feel free to try it out! You might find a false positive that wasn't there in v3, please [report this][3]. ```sh npm install -D knip@canary ``` Remember, Knip it before you ship it! Have a great day ☀️ [1]: #the-story-of-findreferences [2]: https://github.com/remix-run/remix [3]: https://github.com/webpro-nl/knip/issues ================================================ FILE: packages/docs/src/content/docs/blog/state-of-knip.md ================================================ --- title: The State of Knip date: 2025-02-28 sidebar: order: 3 --- _Published: 2025-02-28_ Honestly, Knip was a bit of a "cursed" project from the get-go. Getting anywhere near a level of being broadly-ish valuable requires a good amount of ~~foolishness~~ determination, and it has always been clear it would stay far from perfect. It's telling that most of [similar projects][1] have been abandoned. And even though Knip is in its infancy, this update is meant as a sign we feel we're still on to something. External indicators include increased usage looking at numbers such as dependent repositories on GitHub and weekly downloads on npm, and bug reports about increasingly less rudimentary issues. ## Two Cases For those interested, let's take a look at two cases that hopefully give an impression of how Knip works under the hood and the level of issues we're currently dealing with. It's assumed you already have a basic understanding of Knip (otherwise please consider to read at least [entry files][2] and [plugins][3] first). ### Case 1: Next.js Let's say this default configuration represents, greatly simplified, [the default `entry` patterns][4] for projects using Next.js: ```json { "next": { "entry": ["next.config.ts", "src/pages/**/*.tsx"] } } ``` Those files will be searched for and then statically analyzed to collect `import` statements and find other local files and external dependencies. This is the generic way Knip handles all source files. However, the game changes if the project uses the following Next.js configuration: ```ts title="next.config.ts" const nextConfig = { pageExtensions: ['page.tsx'], }; export default nextConfig; ``` Next.js will now look for files matching `src/pages/**/*.page.tsx` instead (note the subtle change of the glob pattern). Knip should respect this to find used and unused files properly. Moving the burden to users for them to either not notice at all and get incorrect results, or having to override the `next.entry` patterns and include `src/pages/**/*.page.tsx` isn't good DX. Knip should take care of it. To get the configuration object and the value of `pageExtensions`, Knip has to actually load and execute `next.config.ts` ¹... and trouble is right around the corner: ```ts title="next.config.ts" const nextConfig = { pageExtensions: ['page.tsx'], env: { BASE_URL: process.env.BASE_URL.toLowerCase(), }, }; export default nextConfig; ``` ```shell $ knip 💥 LoaderError: Error loading next.config.ts 💥 Reason: Cannot read properties of undefined (reading 'toLowerCase') ``` Obviously a contrived example, but the gist is that lots of tooling configuration expects environment variables to be defined. But when running Knip there might not be a mechanism to set those. Clearly a breaking change when Knip starts doing this, only for Next.js projects with a configuration file that doesn't read environment variables safely (or has other contextual dependencies). By the way, [the ESLint v9 plugin][5] has a similar issue. ¹ Another approach could be to statically analyze the `next.config.ts` configuration file. That would require some additional efforts and get us only so far, but is definitely useful in some cases and on the radar. **EDIT:** This has been solved in the Next.js plugin in v5.48.0. ### Case 2: Knip does that?! To further bring down user configuration and the number of false positives, the system required more components. New components have been introduced to keep improving and nail it for an increasing number of projects. This case is an illustration of some of those components. Let's just dive into this example and find out what's happening: ```json title="package.json" { "scripts": { "test": "yarn --cwd packages/frontend vitest -c vitest.components.config.ts" } } ``` Orchestration is necessary between various components within Knip, such as: - Plugins, the Vitest plugin parses `vitest.components.config.ts` - Custom CLI argument parsing for executables, e.g. `yarn --cwd [dir]` and `vitest --config [file]` - The workspace graph, to see `packages/frontend` is a descendant workspace of the root workspace Patterns like in the script above do not occur only in `package.json` files, but could be anywhere. Here's a similar example in a GitHub Actions workflow: ```yaml title=".github/workflows/test.yml" jobs: integration: runs-on: ubuntu-latest steps: - run: playwright test -c playwright.e2e.config.ts working-directory: e2e ``` The pattern is very similar, because Knip needs to assign a configuration file to a specific workspace (assuming there's one in `./e2e`) and apply the Vitest configuration to that particular workspace with its own set of directory and entry file patterns. An essential part of Knip is to build up the module graph for source files. With the configuration files still in mind, this is the pattern Knip follows towards this goal: - Find configuration files at default and custom locations - Assign them to the right workspace - Run plugins in their own workspace to take entry file patterns from the configuration objects - Load and parse configuration files to get referenced dependencies The referenced dependencies are stored in the `DependencyDeputy` class to eventually determine what dependencies are unused or missing in `package.json` in each workspace. Both the configuration and entry files are then used to start building up the module graph. ## Comprehensive Discussing the two cases briefly covers only part of the whole process. This might give a sense of the reason why Knip is pretty comprehensive. After all, building the module graph for internal source files to find unused files and exports requires the list of external dependencies including internal workspaces. And on the other hand, a complete module graph is required to find unused or missing external dependencies. The comprehensiveness also requires a range of components in the system, such as the aforementioned ones, [compilers for popular frameworks][6] and a [script parser][7], and other affordances such as [auto-fix][8]. That said, code organization could be improved to make it more accessible for contributions and, for instance, expose programmatic APIs to use the generated module graph outside of Knip. Additionally, existing plugins can better take advantage of existing components in the system, and new plugins can be developed to further reduce user configuration and false positives. ## The End That's all for today, thanks for reading! Have a great one, and don't forget: Knip it before you ship it! ✂️ [1]: ../explanations/comparison-and-migration.md [2]: ../explanations/entry-files.md [3]: ../explanations/plugins.md [4]: ../reference/plugins/next.md#default-configuration [5]: ../reference/plugins/eslint.md#eslint-v9 [6]: ../features/compilers.md [7]: ../features/script-parser.md [8]: ../features/auto-fix.mdx ================================================ FILE: packages/docs/src/content/docs/blog/two-years.mdx ================================================ --- title: Two Years date: 2024-10-04 sidebar: order: 4 --- _Published: 2024-10-04_ import EmojiBlastButton from '../../../components/EmojiBlastButton.astro'; import Projects from '../../../components/Projects.astro'; import Sponsors from '../../../components/Sponsors.astro'; Exactly two years ago the first commit was pushed to GitHub and the first version of Knip was published to the npm registry. The name was initially [Exportman][1]! We've come a loooong way... The JavaScript ecosystem is highly dynamic and I've been crazy enough to even start, try and keep up with it! But here we are. October 4th is World Animal Day, so there was really no choice but bring in the crazy mascot that early adopters may remember: ![Crazy cow with orange scissors in Van Gogh style][2] Today we celebrate an unknown but CRAZY amount of clutter removed from so many codebases with Knip's help. Every single day I see many of those little red blocks for thousands of lines of deleted code and dependencies. Call me crazy, but to me this is pure joy and never gets old!    🟩 🟥 🟥 🟥 🟥 ## Smiling faces The actual amount of code and dependencies removed and the number of smiling faces this brings is what matters most, but also remain a good mystery. Clearly more and more projects add Knip to their projects and CI workflows to keep ever-growing codebases tidy. It's wonderful to see if Knip plays its part in today's ecosystem to help with that. Thanks for bearing with me, here's to a lot more little red blocks in your PRs!    🟩 🟥 🟥 🟥 🟥 ## Updates Why not throw in some freshly cooked updates in [v5.31.0][3] for you while we're at it: - [The auto-fix feature][4] has been completely revamped, it's much better and a lot more comprehensive! You have to see it to believe it. - Knip has upgraded to [Jiti v2][5], resolving a bunch of known issues when loading configuration files authored in TypeScript and ESM, such as: ``` Cannot use 'import.meta' outside a module await is only valid in async functions and the top level bodies of modules Unexpected identifier 'Promise' Reflect.metadata is not a function ``` And that pesky "CJS build of Vite's Node API is deprecated" warning is finally gone! Thanks to everyone involved in making this happen, it's truly much appreciated. ## Stable If you haven't tried Knip recently, it's worth taking another look! Version 5 was released 8 months ago, and even though there were no breaking changes, it includes many enhancements. In fact, Knip has been largely stable since version 3, which came out a year ago. Many releases have a compound effect, as Knip has kept the pace for two years now. ## Projects using Knip This list of projects using Knip to keep their codebases tidy is something I couldn't be more proud of: :::section{.columns.min200} ::: And so many more on and off the radar. Very, very cool! ## Sponsors Last but not least, eternal gratitude for all the sponsors that have been supporting me along the way. THANK YOU, THANK YOU, THANK YOU! And eh.. gotta take my chances: how about [joining this awesome club][6]? :::section{.columns.min300.mt} ::: ## Acknowledgements Thanks to Joshua Goldberg for [emoji-blast][7]! 🎉 [1]: https://www.npmjs.com/package/exportman/v/0.0.1 [2]: /cow-with-orange-scissors-van-gogh-style.webp [3]: https://github.com/webpro-nl/knip/releases/tag/5.31.0 [4]: ../features/auto-fix.mdx [5]: https://github.com/unjs/jiti [6]: /sponsors [7]: https://www.emojiblast.dev ================================================ FILE: packages/docs/src/content/docs/explanations/comparison-and-migration.md ================================================ --- title: Comparison & Migration --- First of all, Knip owes a lot to the projects on this page and they've all been inspirational in their own way. For best results, Knip has [a vision embracing comprehensiveness][1] which is larger in scope than any of the alternatives. So if any of those tools has the right scope for your requirements, then by all means, use what suits you best. Note that most projects are no longer maintained. All tools have in common that they have less features and don't support the concept of [monorepos/workspaces][2]. Feel free to send in projects that Knip does not handle better, Knip loves to be challenged! ## Migration A migration consists of deleting the dependency and its configuration file and [getting started with Knip][3]. You should end up with less configuration. ## Comparison ### depcheck > [Depcheck][4] is a tool for analyzing the dependencies in a project to see: > how each dependency is used, which dependencies are useless, and which > dependencies are missing from package.json. The project has plugins (specials), yet not as many as Knip has and they're not as advanced. It also supports compilers (parsers) for non-standard files. The following commands are similar: ```sh depcheck knip --dependencies ``` **Project status**: The project is archived and recommends Knip. ### unimported > Find and fix dangling files and unused dependencies in your JavaScript > projects. [unimported][5] is fast and works well. It works in what Knip calls "production mode" exclusively. If you're fine with a little bit of configuration and don't want or need to deal with non-production items (such as `devDependencies` and test files), then this might work well for you. The following commands are similar: ```sh unimported knip --production --dependencies --files ``` **Project status**: The project is archived and recommends Knip. ### ts-prune > Find unused exports in a typescript project. 🛀 [ts-prune][6] aims to find potentially unused exports in your TypeScript project with zero configuration. The following commands are similar: ```sh ts-prune knip --include exports,types,nsExports,nsTypes ``` Use `knip --exports` to also include enum and namespace members. **Project status**: The project is archived and recommends Knip. ### ts-unused-exports > [ts-unused-exports][7] finds unused exported symbols in your Typescript > project The following commands are similar: ```sh ts-unused-exports knip --include exports,types,nsExports,nsTypes ``` Use `knip --exports` to also include enum and namespace members. ### tsr > Remove unused code from your TypeScript Project [tsr][8] (previously `ts-remove-unused`) removes unused exports, and works based on a single `tsconfig.json` file (`includes` and `excludes`) and requires no configuration. It removes the `export` keyword or the whole export declaration. **Project status**: The project is archived and recommends Knip. ## Related projects Additional alternative and related projects include: - [deadfile][9] - [DepClean][10] - [dependency-check][11] - [find-unused-exports][12] - [next-unused][13] - [npm-check][14] - [renoma][15] In general, the [e18e.dev][16] website and in particular the [Cleanup][17] section is a great resource when dealing with technical debt. [1]: ./why-use-knip.md#comprehensive [2]: ../features/monorepos-and-workspaces.md [3]: ../overview/getting-started.mdx [4]: https://github.com/depcheck/depcheck [5]: https://github.com/smeijer/unimported [6]: https://github.com/nadeesha/ts-prune [7]: https://github.com/pzavolinsky/ts-unused-exports [8]: https://github.com/line/tsr [9]: https://github.com/M-Izadmehr/deadfile [10]: https://github.com/mysteryven/depclean [11]: https://github.com/dependency-check-team/dependency-check [12]: https://github.com/jaydenseric/find-unused-exports [13]: https://github.com/pacocoursey/next-unused [14]: https://github.com/dylang/npm-check [15]: https://github.com/bluwy/renoma [16]: https://e18e.dev [17]: https://e18e.dev/guide/cleanup.html ================================================ FILE: packages/docs/src/content/docs/explanations/entry-files.md ================================================ --- title: Entry Files sidebar: order: 1 --- Entry files are the starting point for Knip to determine what files are used in the codebase. More entry files lead to increased coverage of the codebase. This also leads to more dependencies to be discovered. This page explains how Knip and its plugins try to find entry files so you don't need to configure them yourself. ## Default entry file patterns For brevity, the [default configuration][1] on the previous page mentions only `index.js` and `index.ts`, but the default set of file names and extensions is actually a bit larger: - `index`, `main` and `cli` - `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx` This means files like `main.cjs` and `src/cli.ts` are automatically added as entry files. Here's the default configuration in full: ```json { "entry": [ "{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}", "src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}" ], "project": ["**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!"] } ``` Next to the default locations, Knip looks for `entry` files in other places. In a monorepo, this is done for each workspace separately. The values you set override the default values, they are not merged. Also see [FAQ: Where does Knip look for entry files?][2] ## Plugins Plugins often add entry files. For instance, if the Remix, Storybook and Vitest plugins are enabled in your project, they'll add additional entry files. See [the next page about plugins][3] for more details about this. ## Scripts in package.json The `package.json` is scanned for entry files. The `main`, `bin`, and `exports` fields may contain entry files. The `scripts` are also parsed to find entry files and dependencies. See [Script Parser][4] for more details. ## Ignored files Knip respects `.gitignore` files. By default, ignored files are not added as entry files. This behavior can be disabled by using the [`--no-gitignore`][5] flag on the CLI. ## Configuring project files See [configuring project files][6] for guidance on tuning `entry` and `project` and when to use `ignore`. [1]: ../overview/configuration.md#defaults [2]: ../reference/faq.md#where-does-knip-look-for-entry-files [3]: ./plugins.md [4]: ../features/script-parser.md [5]: ../reference/cli.md#--no-gitignore [6]: ../guides/configuring-project-files.md ================================================ FILE: packages/docs/src/content/docs/explanations/plugins.md ================================================ --- title: Plugins sidebar: order: 2 --- This page describes why Knip uses plugins and the difference between `config` and `entry` files. Knip has an extensive and growing [list of built-in plugins][1]. Feel free to [write a plugin][2] so others can benefit too! ## What does a plugin do? Plugins are enabled if the related package is listed in the list of dependencies in `package.json`. For instance, if `astro` is listed in `dependencies` or `devDependencies`, then the Astro plugin is enabled. And this means that this plugin will: - Handle [configuration files][3] like `astro.config.mjs` - Add [entry files][4] such as `src/pages/**/*.astro` - Define [command-line arguments][5] ## Configuration files Knip uses [entry files][6] as starting points to scan your source code and resolve other internal files and external dependencies. The module graph can be statically resolved through the `require` and `import` statements in those source files. However, configuration files reference external dependencies in various ways. Knip uses a plugin for each tool to parse configuration files and find those dependencies. ### Example: ESLint In the first example we look at [the ESLint plugin][7]. The default `config` file patterns include `.eslintrc.json`. Here's a minimal example: ```json title=".eslintrc.json" { "extends": ["airbnb", "prettier"], "plugins": ["@typescript-eslint"] } ``` Configuration files like this don't `import` or `require` anything, but they do require the referenced dependencies to be installed. In this case, the plugin will return three dependencies: - `eslint-config-airbnb` - `eslint-config-prettier` - `@typescript-eslint/eslint-plugin` Knip will then look for missing dependencies in `package.json` and report those as unlisted. And vice versa, if there are any ESLint plugins listed in `package.json`, but unused, those will be reported as well. ### Example: Vitest The second example uses [the Vitest plugin][8]. Here's a minimal example of a Vitest configuration file: ```ts title="vitest.config.ts" import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { coverage: { provider: 'istanbul', }, environment: 'happy-dom', }, }); ``` The Vitest plugin reads this configuration and returns two dependencies: - `@vitest/coverage-istanbul` - `vitest-environment-happy-dom` Knip will look for missing and unused dependencies in `package.json` and report accordingly. Some tools allow configuration to be stored in `package.json`, that's why some plugins contain `package.json` in the list of `config` files. :::tip[Summary] Plugins load configuration files to find referenced dependencies, and determine unused and unlisted dependencies. ::: ## Entry files Many plugins have default `entry` files configured. When the plugin is enabled, Knip will add entry files as configured by the plugin to resolve used files and dependencies. For example, if `next` is listed as a dependency in `package.json`, the Next.js plugin will automatically add multiple patterns as entry files, such as `pages/**/*.{js,jsx,ts,tsx}`. If `vitest` is listed, the Vitest plugin adds `**/*.{test,test-d,spec,spec-d}.ts` as entry file patterns. Most plugins have entry files configured, so you don't have to. It's mostly plugins for meta frameworks and test runners that have `entry` files configured. :::tip[Plugins result in less configuration] Plugins uses entry file patterns as defined in your configuration file of these tools. So you don't need to repeat this in your Knip configuration. ::: For example, let's say your Playwright configuration contains the following: ```ts title="playwright.config.ts" import type { PlaywrightTestConfig } from '@playwright/test'; const config: PlaywrightTestConfig = { testDir: 'integration', testMatch: ['**/*-test.ts'], }; export default config; ``` The Playwright plugin will read this configuration file and return those entry patterns (`integration/**/*-test.ts`). Knip will then not use the default entry patterns. You can still override this behavior in your Knip configuration: ```json title="knip.json" { "playwright": { "entry": "src/**/*.integration.ts" } } ``` This should not be necessary though. Please consider opening a pull request or a bug report if any plugin is not behaving as expected. :::tip[Summary] Plugins try hard to automatically add the correct entry files. ::: ## Entry files from config files Entry files are part of plugin configuration (as described in the previous section). Yet plugins can also return additional entry files after parsing configuration files. Below are some examples of configuration files parsed by plugins to return additional entry files. The goal of these examples is to give you an idea about the various ways Knip and its plugins try to find entry files so you don't need to configure them yourself. ### Angular The Angular plugin parses the Angular configuration file. Here's a fragment: ```json title="angular.json" { "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "projects": { "knip-angular-example": { "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/knip-angular-example", "main": "src/main.ts", "tsConfig": "tsconfig.app.json" } } } } } } ``` This will result in `src/main.ts` being added as an entry file (and `@angular-devkit/build-angular` as a referenced dependency). Additionally, the Angular plugin returns `tsconfig.app.json` as a configuration file for the TypeScript plugin. ### GitHub Actions This plugin parses workflow YAML files. This fragment contains three `run` scripts: ```yml title=".github/workflows/deploy.yml" jobs: integration: runs-on: ubuntu-latest steps: - run: npm install - run: node scripts/build.js - run: node --loader tsx scripts/deploy.ts - run: playwright test -c playwright.web.config.ts working-dir: e2e ``` From these scripts, the `scripts/build.js` and `scripts/deploy.ts` files will be added as entry files by the GitHub Actions plugin. Additionally, the file `e2e/playwright.web.config.ts` is detected and will be handed over as a Playwright configuration file. Read more about this in [command-line arguments][5]. ### webpack Let's take a look at this example webpack configuration file: ```js title="webpack.config.js" module.exports = env => { return { entry: { main: './src/app.ts', vendor: './src/vendor.ts', }, module: { rules: [ { test: /\.(woff|ttf|ico|woff2|jpg|jpeg|png|webp)$/i, use: 'base64-inline-loader', }, ], }, }; }; ``` The webpack plugin will parse this and add `./src/app.ts` and `./src/vendor.ts` as entry files. It will also add `base64-inline-loader` as a referenced dependency. :::tip[Summary] In your config files, plugins can find additional entry files and also other config files recursively. ::: ## Bringing it all together Sometimes a configuration file is a JavaScript or TypeScript file that imports dependencies, but also contains configuration that needs to be parsed by a plugin to find additional dependencies. Let's take a look at this example Vite configuration file: ```ts title="vite.config.ts" import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig(async ({ mode, command }) => { return { plugins: [react()], test: { setupFiles: ['./setup-tests.ts'], environment: 'happy-dom', coverage: { provider: 'c8', }, }, }; }); ``` This file imports `vite` and `@vitejs/plugin-react` directly, but also indirectly references the `happy-dom` and `@vitest/coverage-c8` packages. The Vite plugin of Knip will **dynamically** load this configuration file and parse the exported configuration. But it's not aware of the `vite` and `@vitejs/plugin-react` imports. This is why such `config` files are also automatically added as `entry` files for Knip to **statically** resolve the `import` and `require` statements. Additionally, `./setup-tests.ts` will be added as an `entry` file. :::note When plugins dynamically load configuration files, conditional dependencies may not be detected if the condition evaluates differently during analysis. See [conditional or dynamic dependencies][9] for details and workarounds. ::: ## Command-Line Arguments Plugins may define the arguments where Knip should look for entry files, configuration files and dependencies. We've already seen some examples above: ```sh node --loader tsx scripts/deploy.ts playwright test -c playwright.web.config.ts ``` Please see [script parser][10] for more details. ## Config File Location If configuration files aren't in their default location and they are not referenced through some script like `vite -c ./dir/vite.config.ts`, then make sure to tell Knip about it. Two examples: ```json title="knip.jsonc" { "playwright": { "config": ["e2e/playwright.config.ts"] }, "vite": "packages/*/vite.config.ts" // shorthand without `config` and array notation } ``` This is common in projects where a directory like `packages/lib` is not an actual workspace with a `package.json` file. Also see [integrated monorepos][11] for similar cases. ## Summary :::tip[Summary] Plugins are configured with two distinct types of files: - `config` files are dynamically loaded and parsed by the plugin - `entry` files are added to the module graph - Both can recursively lead to additional entry files, config files and dependencies ::: [1]: ../reference/plugins.md [2]: ../writing-a-plugin/index.md [3]: #configuration-files [4]: #entry-files [5]: #command-line-arguments [6]: ./entry-files.md [7]: ../reference/plugins/eslint.md [8]: ../reference/plugins/vitest.md [9]: ../guides/handling-issues.mdx#conditional-or-dynamic-dependencies [10]: ../features/script-parser.md [11]: ../features/integrated-monorepos.md ================================================ FILE: packages/docs/src/content/docs/explanations/why-use-knip.md ================================================ --- title: Why use Knip? sidebar: order: 3 --- The value of removing clutter is clear, but finding it manually is tedious. This is where Knip comes in: comprehensive and accurate results at any scale. :::tip[TL;DR] Knip finds and fixes unused dependencies, exports and files. Deep analysis from [fine-grained entry points][1] based on the actual frameworks and tooling in [(mono)repos][2] for accurate and actionable results. Advanced features for maximum coverage: - [Custom module resolution][3] - [Configuration file parsers][4] - [Advanced shell script parser][5] - [Built-in and custom compilers][6] - [Auto-fix most issues][7] ::: ## Less is more There are plenty of reasons to delete unused files, dependencies and "dead code": - Easier maintenance: things are easier to manage when there's less of it. - Improved performance: startup time, build time and/or bundle size can be negatively impacted when unused code, files and/or dependencies are included. Relying on tree-shaking when bundling code helps, but it's not a silver bullet. - Easier onboarding: there should be no doubts about whether files, dependencies and exports are actually in use or not. Especially for people new to the project and/or taking over responsibilities this is harder to grasp. - Prevent regressions: tools like TypeScript, ESLint and Prettier do all sorts of checks and linting to report violations and prevent regressions. Knip does the same for dependencies, exports and files that are obsolete. - Keeping dead code around has a negative value on readability, as it can be misleading and distracting. Even if it serves no purpose it will need to be maintained (source: [Safe dead code removal → YAGNI][8]). - Also see [Why are unused dependencies a problem?][9] and [Why are unused exports a problem?][10]. ## Automation Code and dependency management is usually not the most exciting task for most of us. Knip's mission is to automate finding clutter. This is such a tedious job if you were to do it manually, and where would you even start? Knip applies many techniques and heuristics to report what you need and save a lot of time. :::tip Knip not only finds clutter, it can also [remove clutter][7]! Use Knip next to a linter like ESLint or Biome: after removing unused variables inside files, Knip might find even more unused code. Rinse and repeat! ::: ## Comprehensive You can use alternative tools that do the same. However, the advantage of a strategy that addresses all of dependencies, exports and files is in their synergy: - Utilizing plugins to find their dependencies includes the capacity to find additional entry and configuration files. This results in more resolved and used files. Better coverage gives better insights into unused files and exports. - Analyzing more files reveals more unused exports and dependency usage, refining the list of both unused and unlisted dependencies. - This approach is amplified in a monorepo setting. In fact, files and internal dependencies can recursively reference each other (across workspaces). ## Greenfield or Legacy Installing Knip in greenfield projects ensures the project stays neat and tidy from the start. Add it to your CI workflow and prevent any regressions from entering the codebase. :::tip Use Knip in a CI environment to prevent future regressions. ::: In large and/or legacy projects, Knip may report false positives and require some configuration. It aims to be a great assistant when cleaning up parts of the project or doing large refactors. Even a list of results with a few false positives is many times better and faster than if you were to do it manually. ## Unobtrusive Knip does not introduce new syntax for you to learn. This may sound obvious, but consider comments like the following: ```js // eslint-disable-next-line // prettier-ignore // @ts-expect-error ``` Maybe you wonder why Knip does not have similar comments like `// knip-ignore` so you can get rid of false positives? A variety of reasons: 1. A false positive may be a bug in Knip, and should be reported, not dismissed. 2. Instead of proprietary comments, use [standardized annotations][11] that also serve as documentation. 3. In the event you want to remove Knip, just uninstall `knip` without having to remove useless comments scattered throughout the codebase. Tip: use `@lintignore` in JSDoc comments, so other linters can use the same. [1]: ./entry-files.md [2]: ../features/monorepos-and-workspaces.md [3]: ../reference/faq.md#why-doesnt-knip-use-an-existing-module-resolver [4]: ./plugins.md#configuration-files [5]: ../features/script-parser.md [6]: ../features/compilers.md [7]: ../features/auto-fix.mdx [8]: https://jfmengels.net/safe-dead-code-removal/#yagni-you-arent-gonna-need-it [9]: ../typescript/unused-dependencies.md#why-are-unused-dependencies-a-problem [10]: ../typescript/unused-exports.md#why-are-unused-exports-a-problem [11]: ../reference/jsdoc-tsdoc-tags.md ================================================ FILE: packages/docs/src/content/docs/features/auto-fix.mdx ================================================ --- title: Auto-fix --- import { Tabs, TabItem } from '@astrojs/starlight/components'; import { Badge } from '@astrojs/starlight/components'; Run Knip as you normally would, and if the report looks good then run it again with the `--fix` flag to let Knip automatically apply fixes. It fixes the following [issue types][1]: - Remove `export` keyword for unused exports, re-exports, and exported types - Remove `export default` keywords for unused default exports - Remove unused enum and namespace members - Remove unused `dependencies` and `devDependencies` from `package.json` - Remove unused files - Remove unused catalog entries :::caution Use a VCS (version control system) like Git to review and undo changes as necessary. ::: ## Flags ### Fix Add the `--fix` flag to remove unused exports and dependencies: ```sh knip --fix ``` Add `--allow-remove-files` to allow Knip to remove unused files: ```sh knip --fix --allow-remove-files ``` Use `--fix-type` to fix only specific issue types: - `dependencies` - `exports` - `types` - `files` - `catalog` Example: ```sh knip --fix-type exports,types knip --fix-type exports --fix-type types # same as above ``` ### Format Add `--format` to format the modified files using the formatter and configuration in your project. Supports Biome, deno fmt, dprint and Prettier (using [Formatly][2]): ```sh knip --fix --format ``` ## Demo ## Post-fix After Knip has fixed issues, there are four things to consider: ### 1. Use a formatter Use a tool like Prettier or Biome if the code needs formatting. Knip removes the minimum amount of code while leaving it in a working state. :::tip Add the `--format` flag to format the modified files using the formatter and configuration in your project. ::: ### 2. Unused variables Use a tool like ESLint or Biome to find and remove unused imports and variables inside files. Even better, try [remove-unused-vars][3] to remove unused variables within files. This may result in more deleted code, and Knip may then find more unused code. Rinse and repeat! ### 3. Unused dependencies Verify changes in `package.json` and update dependencies using your package manager. ```shell npm install ``` ```shell pnpm install ``` ```shell bun install ``` ```shell yarn ``` ### 4. Install unlisted dependencies If Knip reports unlisted dependencies or binaries, they should be installed using the package manager in the project, for example: ```shell npm install unlisted-package ``` ```shell pnpm add unlisted-package ``` ```shell bun add unlisted-package ``` ```shell yarn add unlisted-package ``` ## Example results ### Exports The `export` keyword for unused exports is removed: ```diff title="module.ts" -export const unused = 1; -export default class MyClass {} +const unused = 1; +class MyClass {} ``` The `default` keyword was also removed here. Knip removes the whole or part of export declarations: ```diff title="module.ts" type Snake = 'python' | 'anaconda'; const Owl = 'Hedwig'; const Hawk = 'Tony'; -export type { Snake }; -export { Owl, Hawk }; +; +; ``` ### Re-exports Knip removes the whole or part of re-exports: ```diff title="file.js" -export { Cat, Dog } from './pets'; -export { Lion, Elephant } from './jungle'; +export { Elephant } from './jungle' ``` Also across any chain of re-exports: ```diff export const Hawk = 'Tony'; -export const Owl = 'Hedwig'; +const Owl = 'Hedwig'; ``` ```diff export * from './module.js'; ``` ```diff -export { Hawk, Owl } from './barrel.js'; +export { Hawk } from './barrel.js' ``` ### Export assignments Knip removes individual exported items in "export assignments", but does not remove the entire export declaration if it's empty: ```diff title="file.js" -export const { a, b } = fn(); +export const { } = fn(); -export const [c, d] = [c, d]; +export const [, ] = [c, d]; ``` Reason: the right-hand side of the assignment might have side-effects. It's not safe to always remove the whole declaration. This could be improved in the future (feel free to open an issue/RFC). ### Enum members Unused members of enums are removed: ```diff title="file.ts" export enum Directions { North = 1, East = 2, - South = 3, West = 4, } ``` ### CommonJS Knip supports CommonJS and removes unused exports: ```diff title="common.js" -module.exports = { identifier, unused }; +module.exports = { identifier, }; -module.exports.UNUSED = 1; -module.exports['ACCESS'] = 1; + + ``` Warning: the right-hand side of such an assignment might have side-effects. Knip currently removes the whole declaration (feel free to open an issue/RFC). ### Dependencies Unused dependencies are removed from `package.json`: ```diff title="package.json" { "name": "my-package", "dependencies": { - "rimraf": "*", - "unused-dependency": "*" + "rimraf": "*" }, - "devDependencies": { - "unreferenced-package": "5.3.3" - } + "devDependencies": {} } ``` ### Catalog entries Unused [catalog][4] entries are removed from `pnpm-workspace.yaml`: ```diff title="pnpm-workspace.yaml" packages: - 'packages/*' catalog: react: ^18.0.0 - unused-package: ^1.0.0 ``` Catalogs in `package.json` are supported as well. ## What's not included Operations that auto-fix does not (yet) perform and why: - Add unlisted (dev) dependencies to `package.json` (should it go into `dependencies` or `devDependencies`? For monorepos in current workspace or root?) - Add unlisted binaries (which package and package version contains the used binary?) - Fix duplicate exports (which one should be removed?) [1]: ../reference/issue-types.md [2]: https://github.com/JoshuaKGoldberg/formatly [3]: https://github.com/webpro-nl/remove-unused-vars [4]: https://pnpm.io/catalogs ================================================ FILE: packages/docs/src/content/docs/features/compilers.md ================================================ --- title: Compilers --- Projects may have source files that are not JavaScript or TypeScript, and thus require compilation (or transpilation, or pre-processing, you name it). Files like `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files and external dependencies. So ideally, these files are included when linting the project. That's why Knip supports compilers. ## Built-in compilers Knip has built-in "compilers" for the following file extensions: - `.astro` - `.css` (only enabled by `tailwindcss`) - `.mdx` - `.prisma` - `.sass` + `.scss` - `.svelte` - `.vue` Knip does not include real compilers for those files, but regular expressions to collect `import` statements. This is fast, requires no dependencies, and enough for Knip to build the module graph. On the other hand, real compilers may expose their own challenges in the context of Knip. For instance, the Svelte compiler keeps `exports` intact, while they might represent component properties. This results in those exports being reported as unused by Knip. The built-in functions seem to do a decent job, but override them however you like. Compilers are enabled only if certain dependencies are found. If that's not working for your project, set `true` and enable any compiler manually: ```ts title="knip.ts" export default { compilers: { mdx: true, }, }; ``` ## Custom compilers Built-in compilers can be overridden, and additional compilers can be added. Since compilers are functions, the Knip configuration file must be a dynamic `.js` or `.ts` file. ### Interface The compiler function interface is straightforward. Text in, text out: ```ts (source: string, filename: string) => string; ``` This may also be an `async` function. :::tip[Note] Compilers will automatically have their extension added as a default extension to Knip. This means you don't need to add something like `**/*.{ts,vue}` to the `entry` or `project` file patterns manually. ::: ### Examples - [CSS][1] - [MDX][2] - [Svelte][3] - [Vue][4] #### CSS Here's an example, minimal compiler for CSS files: ```ts title="knip.ts" export default { compilers: { css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'), }, }; ``` You may wonder why the CSS compiler is not included by default. It's currently not clear if it should be included. And if so, what would be the best way to determine it should be enabled, and what syntax(es) it should support. Note that Tailwind CSS and SASS/SCSS compilers are included. #### MDX Another example, in case the built-in MDX compiler is not enough: ```ts import { compile } from '@mdx-js/mdx'; export default { compilers: { mdx: async text => (await compile(text)).toString(), }, }; ``` #### Svelte In a Svelte project, the compiler is automatically enabled. Override and use Svelte's compiler for better results if the built-in "compiler" is not enough: ```ts import type { KnipConfig } from 'knip'; import { compile } from 'svelte/compiler'; export default { compilers: { svelte: (source: string) => compile(source, {}).js.code, }, } satisfies KnipConfig; ``` #### Vue In a Vue project, the compiler is automatically enabled. Override and use Vue's parser for better results if the built-in "compiler" is not enough: ```ts import type { KnipConfig } from 'knip'; import { parse, type SFCScriptBlock, type SFCStyleBlock, } from 'vue/compiler-sfc'; function getScriptBlockContent(block: SFCScriptBlock | null): string[] { if (!block) return []; if (block.src) return [`import '${block.src}'`]; return [block.content]; } function getStyleBlockContent(block: SFCStyleBlock | null): string[] { if (!block) return []; if (block.src) return [`@import '${block.src}';`]; return [block.content]; } function getStyleImports(content: string): string { return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\n'); } const config = { compilers: { vue: (text: string, filename: string) => { const { descriptor } = parse(text, { filename, sourceMap: false }); return [ ...getScriptBlockContent(descriptor.script), ...getScriptBlockContent(descriptor.scriptSetup), ...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports), ].join('\n'); }, }, } satisfies KnipConfig; export default config; ``` [1]: #css [2]: #mdx [3]: #svelte [4]: #vue ================================================ FILE: packages/docs/src/content/docs/features/integrated-monorepos.md ================================================ --- title: Integrated Monorepos sidebar: order: 3 --- Some repositories have a single `package.json`, but consist of multiple projects with configuration files across the repository. A good example is the [Nx integrated monorepo style][1]. :::tip An integrated monorepo is a single workspace. ::: ## Entry Files The default entrypoints files might not be enough. Here's an idea that might fit this type of monorepo: ```json title="knip.json" { "entry": ["{apps,libs}/**/src/index.{ts,tsx}"], "project": ["{apps,libs}/**/src/**/*.{ts,tsx}"] } ``` ## Plugins Let's assume some of these projects are applications ("apps") which have their own ESLint configuration files and Cypress configuration and test files. This may result in those files getting reported as unused, and consequently also the dependencies they import and refer to. In that case, we could configure the ESLint and Cypress plugins like this: ```json title="knip.json" { "eslint": { "config": ["{apps,libs}/**/.eslintrc.json"] }, "cypress": { "entry": ["apps/**/cypress.config.ts", "apps/**/cypress/e2e/*.spec.ts"] } } ``` Adapt the file patterns to your project, and the relevant `config` and `entry` files and dependencies should no longer be reported as unused. ## Internal Workspace Dependencies A note about repositories with multiple `package.json` files and **internal** workspace packages: it is recommended to list all dependencies in each consuming `package.json`, allowing Knip to do fine-grained reporting of both unused and unlisted dependencies. An alternative is to `ignoreDependencies: ["@internal/*"]`. [1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial ================================================ FILE: packages/docs/src/content/docs/features/monorepos-and-workspaces.md ================================================ --- title: Monorepos & Workspaces sidebar: order: 2 --- Workspaces are handled out-of-the-box by Knip. Workspaces are sometimes also referred to as package-based monorepos, or as packages in a monorepo. Knip uses the term workspace exclusively to indicate a directory that has a `package.json`. ## Configuration Here's example configuration with custom `entry` and `project` patterns: ```json title="knip.json" { "workspaces": { ".": { "entry": "scripts/*.js", "project": "scripts/**/*.js" }, "packages/*": { "entry": "{index,cli}.ts", "project": "**/*.ts" }, "packages/cli": { "entry": "bin/cli.js" } } } ``` :::tip Run Knip without any configuration to see if and where custom `entry` and/or `project` files are necessary per workspace. ::: Each workspace has the same [default configuration][1]. The root workspace is named `"."` under `workspaces` (like in the example above). :::caution In a project with workspaces, the `entry` and `project` options at the root level are ignored. Use the workspace named `"."` for those (like in the example above). ::: ## Workspaces Knip reads workspaces from four possible locations: 1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna) 2. The `packages` array in `pnpm-workspace.yaml` (pnpm) 3. The `workspaces.packages` array in `package.json` (legacy) 4. The `workspaces` object in Knip configuration The `workspaces` in Knip configuration (4) not already defined in the root `package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis. :::caution A workspace must have a `package.json` file. ::: For projects with only a root `package.json`, please see [integrated monorepos][2]. ## Additional workspaces If a workspaces is not configured as such in `package.json#workspaces` (or `pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add their path to the `workspaces` configuration object the same way as `"packages/cli": {}` in the example above. ## Source mapping See [Source Mapping][3]. ## Additional options The following options are available inside workspace configurations: - [ignore][4] - [ignoreBinaries][5] - [ignoreDependencies][6] - [ignoreMembers][7] - [ignoreUnresolved][8] - [includeEntryExports][9] [Plugins][10] can be configured separately per workspace. Use `--debug` for verbose output and see the workspaces Knip includes, their configurations, enabled plugins, glob options and resolved files. ## Filter workspaces Use the `--workspace` (or `-W`) argument to select one or more workspaces: ```sh knip --workspace packages/my-lib ``` The filter supports multiple formats: ```sh knip --workspace @myorg/my-lib # Package name knip --workspace '@myorg/*' # Package name glob knip --workspace packages/my-lib # Directory path knip --workspace './apps/*' # Directory glob ``` Combine selectors to include or exclude workspaces: ```sh knip --workspace @myorg/* --workspace '!@myorg/legacy' knip --workspace './apps/*' --workspace '@shared/utils' ``` This will include the target workspace(s), but also ancestor and dependent workspaces. For two reasons: - Ancestor workspaces may list dependencies in `package.json` the linted workspace uses. - Dependent workspaces may reference exports from the linted workspace. To lint the workspace in isolation, there are two options: - Combine the `workspace` argument with [strict production mode][11]. - Run Knip from inside the workspace directory. [1]: ../overview/configuration.md#defaults [2]: ./integrated-monorepos.md [3]: ./source-mapping.md [4]: ../reference/configuration.md#ignore [5]: ../reference/configuration.md#ignorebinaries [6]: ../reference/configuration.md#ignoredependencies [7]: ../reference/configuration.md#ignoremembers [8]: ../reference/configuration.md#ignoreunresolved [9]: ../reference/configuration.md#includeentryexports [10]: ../reference/configuration.md#plugins [11]: ./production-mode.md#strict-mode ================================================ FILE: packages/docs/src/content/docs/features/production-mode.md ================================================ --- title: Production Mode sidebar: order: 1 --- The default mode for Knip is comprehensive and targets all project code, including configuration files, test files, Storybook stories, and so on. Test files usually import production files. This prevents production files or their exports from being reported as unused, while sometimes both of them can be deleted. Knip features a "production mode" to focus only on the code that you ship. ## Configuration To tell Knip what is production code, add an exclamation mark behind each `pattern!` that represents production code: ```json title="knip.json" { "entry": ["src/index.ts!", "build/script.js"], "project": ["src/**/*.ts!", "build/*.js"] } ``` Depending on file structure and enabled plugins, you might not need to modify your configuration at all. Run Knip with the `--production` flag: ```sh knip --production ``` Here's what's included in production mode: - Only `entry` and `project` patterns suffixed with `!` - Only production `entry` file patterns exported by plugins (such as Next.js and Remix) - Only the `start` script (of `package.json#scripts`) - Ignore exports with the [`@internal` tag][1] :::note The production run does not replace the default run. Depending on your needs you can run either of them or both separately. Usually both modes can share the same configuration. ::: To see the difference between default and production mode in great detail, use the `--debug` flag and inspect what entry and project files are used, and the plugins that are enabled. For instance, in production mode this shows that files such as tests and Storybook files (stories) are excluded from the analysis. In case files like mocks and test helpers are reported as unused files, use negated patterns to exclude those files in production mode: ```json title="knip.json" { "entry": ["src/index.ts!"], "project": ["src/**/*.ts!", "!src/test-helpers/**!"] } ``` Also see [configuring project files][2] to align `entry` and `project` with production mode. ## Strict Mode In production mode, only `dependencies` (not `devDependencies`) are considered when finding unused or unlisted dependencies. Additionally, the `--strict` flag can be added to: - Verify isolation: workspaces should use strictly their own `dependencies` - Include `peerDependencies` when finding unused or unlisted dependencies - Report type-only imports listed in `dependencies` ```sh knip --production --strict ``` Using `--strict` implies `--production`, so the latter can be omitted. ## Types Add `--exclude types` if you don't want to include types in the report: ```sh knip --production --exclude types ``` [1]: ../reference/jsdoc-tsdoc-tags.md#internal [2]: ../guides/configuring-project-files.md ================================================ FILE: packages/docs/src/content/docs/features/reporters.md ================================================ --- title: Reporters & Preprocessors --- ## Built-in Reporters Knip provides the following built-in reporters: - `codeowners` - `compact` - [`disclosure`][1] - [`github-actions`][2] - [`json`][3] - [`markdown`][4] - [`codeclimate`][5] - `symbols` (default) Example usage: ```sh knip --reporter compact ``` ### JSON The built-in `json` reporter output is meant to be consumed by other tools. It reports in JSON format with unused `files` and `issues` as an array with one object per file structured like this: ```json { "issues": [ { "file": "package.json", "owners": ["@org/admin"], "dependencies": [{ "name": "jquery", "line": 5, "col": 6, "pos": 71 }], "devDependencies": [{ "name": "lodash", "line": 9, "col": 6, "pos": 99 }], "unlisted": [{ "name": "react" }, { "name": "@org/unresolved" }], "exports": [], "types": [], "duplicates": [] }, { "file": "src/Registration.tsx", "owners": ["@org/owner"], "dependencies": [], "devDependencies": [], "binaries": [], "unresolved": [ { "name": "./unresolved", "line": 8, "col": 23, "pos": 407 } ], "exports": [{ "name": "unusedExport", "line": 1, "col": 14, "pos": 13 }], "types": [ { "name": "unusedEnum", "line": 3, "col": 13, "pos": 71 }, { "name": "unusedType", "line": 8, "col": 14, "pos": 145 } ], "enumMembers": [ { "namespace": "MyEnum", "name": "unusedMember", "line": 13, "col": 3, "pos": 167 }, { "namespace": "MyEnum", "name": "unusedKey", "line": 15, "col": 3, "pos": 205 } ], "duplicates": ["Registration", "default"] } ] } ``` The keys match the [reported issue types][6]. Example usage: ```sh knip --reporter json ``` ### GitHub Actions Use the GitHub Actions reporter in a workflow for annotations in pull requests. Example usage: ```sh knip --reporter github-actions ``` Changed files in pull requests will now contain inline annotations for lint findings. ### Markdown The built-in `markdown` reporter output is meant to be saved to a Markdown file. This allows following the changes in issues over time. It reports issues in Markdown tables separated by issue types as headings, for example: ```md # Knip report ## Unused files (1) - src/unused.ts ## Unlisted dependencies (2) | Name | Location | Severity | | :-------------- | :---------------- | :------- | | unresolved | src/index.ts:8:23 | error | | @org/unresolved | src/index.ts:9:23 | error | ## Unresolved imports (1) | Name | Location | Severity | | :----------- | :----------------- | :------- | | ./unresolved | src/index.ts:10:12 | error | ``` ### Disclosure This reporter is useful for sharing large reports. Groups of issues are rendered in a closed state initially. The reporter renders this: ````text $ knip --reporter disclosure
Unused files (2) ``` unused.ts dangling.js ```
Unused dependencies (2) ``` my-package package.json:17:5 unused-dep package.json:20:5 ```
```` The above can be copy-pasted where HTML and Markdown is supported, such as a GitHub issue or pull request, and renders like so:
Unused files (2) ``` unused.ts dangling.js ```
Unused dependencies (2) ``` my-package package.json:17:5 unused-dep package.json:20:5 ```
### CodeClimate The built-in `codeclimate` reporter generates output in the Code Climate Report JSON format. Example usage: ```text $ knip --reporter codeclimate [ { "type": "issue", "check_name": "Unused exports", "description": "isUnused", "categories": ["Bug Risk"], "location": { "path": "path/to/file.ts", "positions": { "begin": { "line": 6, "column": 1 } } } "severity": "major", "fingerprint": "e9789995c1fe9f7d75eed6a0c0f89e84", } ] ``` ## Custom Reporters When the provided built-in reporters are not sufficient, a custom local reporter can be implemented or an external reporter can be used. Multiple reporters can be used at once by repeating the `--reporter` argument. The results are passed to the function from its default export and can be used to write issues to `stdout`, a JSON or CSV file, or sent to a service. It supports a local JavaScript or TypeScript file or an external dependency. ### Local The default export of the reporter should be a function with this interface: ```ts type Reporter = async (options: ReporterOptions): void; type ReporterOptions = { report: Report; issues: Issues; counters: Counters; configurationHints: ConfigurationHints; isDisableConfigHints: boolean; isTreatConfigHintsAsErrors: boolean; cwd: string; isProduction: boolean; isShowProgress: boolean; options: string; }; ``` The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service. Here's a most minimal reporter example: ```ts title="./my-reporter.ts" import type { Reporter } from 'knip'; const reporter: Reporter = function (options) { console.log(options.issues); console.log(options.counters); }; export default reporter; ``` Example usage: ```sh knip --reporter ./my-reporter.ts ``` ### External Pass `--reporter [pkg-name]` to use an external reporter. The default exported function of the `main` script (default: `index.js`) will be invoked with the `ReporterOptions`, just like a local reporter. ## Preprocessors A preprocessor is a function that runs after the analysis is finished. It receives the results from the analysis and should return data in the same shape/structure (unless you pass it to only your own reporter). The data goes through the preprocessors before the final data is passed to the reporters. There are no built-in preprocessors. Just like reporters, use e.g. `--preprocessor ./my-preprocessor` from the command line (can be repeated). The default export of the preprocessor should be a function with this interface: ```ts type Preprocessor = async (options: ReporterOptions) => ReporterOptions; ``` Like reporters, you can use local JavaScript or TypeScript files and external npm packages as preprocessors. Example preprocessor: ```ts title="./preprocess.ts" import type { Preprocessor } from 'knip'; const preprocess: Preprocessor = function (options) { // modify options.issues and options.counters return options; }; export default preprocess; ``` Example usage: ```sh knip --preprocessor ./preprocess.ts ``` [1]: #disclosure [2]: #github-actions [3]: #json [4]: #markdown [5]: #codeclimate [6]: ../reference/issue-types.md ================================================ FILE: packages/docs/src/content/docs/features/rules-and-filters.md ================================================ --- title: Rules & Filters sidebar: order: 5 --- Use rules or filters to customize Knip's output. This has various use cases, a few examples: - Temporarily focus on a specific issue type. - You don't want to see unused `type`, `interface` and `enum` exports reported. - Specific issue types should be printed, but not counted against the total error count. If you're looking to handle one-off exceptions, also see [JSDoc tags][1]. ## Filters You can `--include` or `--exclude` any of the reported issue types to slice & dice the report to your needs. Alternatively, they can be added to the configuration (e.g. `"exclude": ["dependencies"]`). Use `--include` to report only specific issue types. The following example commands do the same: ```sh knip --include files --include dependencies knip --include files,dependencies ``` Or the other way around, use `--exclude` to ignore the types you're not interested in: ```sh knip --include files --exclude enumMembers,duplicates ``` Also see the [list of issue types][2]. ### Shorthands Knip has shortcuts to include only specific issue types. 1. The `--dependencies` flag includes: - `dependencies` (and `devDependencies` + `optionalPeerDependencies`) - `unlisted` - `binaries` - `unresolved` - `catalog` 2. The `--exports` flag includes: - `exports` - `types` - `enumMembers` - `namespaceMembers` - `duplicates` 3. The `--files` flag is a shortcut for `--include files` ## Rules Use `rules` in the configuration to customize the issue types that count towards the total error count, or to exclude them altogether. | Value | Default | Printed | Counted | Description | | :-------- | :-----: | :-----: | :-----: | :-------------------------------- | | `"error"` | ✓ | ✓ | ✓ | Similar to the `--include` filter | | `"warn"` | - | ✓ | - | Printed in faded/gray color | | `"off"` | - | - | - | Similar to the `--exclude` filter | Example: ```json title="knip.json" { "rules": { "files": "warn", "duplicates": "off" } } ``` Also see the [issue types overview][2]. NOTE: If the `dependencies` issue type is included, the `devDependencies` and `optionalPeerDependencies` types can still be set to `"warn"` separately. The rules are modeled after the ESLint `rules` configuration, and could be extended in the future. ## Rules or filters? Filters are meant to be used as command-line flags, rules allow for more fine-grained configuration. - Rules are more fine-grained since they also have "warn". - Rules could be extended in the future. - Filters can be set in configuration and from CLI (rules only in configuration). - Filters have shorthands (rules don't have this). [1]: ../reference/jsdoc-tsdoc-tags.md [2]: ../reference/issue-types.md ================================================ FILE: packages/docs/src/content/docs/features/script-parser.md ================================================ --- title: Script Parser --- Knip parses shell commands and scripts to find additional dependencies, entry files and configuration files in various places: - In [`package.json`][1] - In [CLI arguments][2] - In [scripts][3] - In [source code][4] Shell scripts can be read and statically analyzed, but they're not executed. ## package.json The `main`, `bin`, `exports` and `scripts` fields may contain entry files. Let's take a look at this example: ```json title="package.json" { "name": "my-package", "main": "index.js", "exports": { "./lib": { "import": "./dist/index.mjs", "require": "./dist/index.cjs" } }, "bin": { "program": "bin/cli.js" }, "scripts": { "build": "rollup src/entry.ts", "start": "node --loader tsx server.ts" } } ``` From this example, Knip automatically adds the following files as entry files: - `index.js` - `./dist/index.mjs` - `./dist/index.cjs` - `bin/cli.js` - `src/entry.ts` - `server.ts` ### Excluded files Knip would not add the `exports` if the `dist` folder is matching a pattern in a relevant `.gitignore` file or `ignore` option. Knip does not add scripts without a standard extension. For instance, the `bin/tool` file might be a valid executable for Node.js, but wouldn't be added or parsed by Knip. ### CLI Arguments When parsing the `scripts` of `package.json` and other files, Knip detects various types of inputs. Some examples: - The first positional argument is usually an entry file - Configuration files are often in the `-c` or `--config` argument - The `--require`, `--loader` or `--import` arguments are often dependencies ```json { "name": "my-lib", "scripts": { "start": "node --import tsx/esm run.ts", "bundle": "tsup -c tsup.lib.config.ts", "type-check": "tsc -p tsconfig.app.json" } } ``` The `"start"` script will have `tsx` marked as a referenced dependency, and adds `run.ts` as an entry file. Additionally, the following files are detected as configuration files: - `tsup.lib.config.ts` - to be handled by the tsup plugin - `tsconfig.app.json` - to be handled by the TypeScript plugin Such executables and their arguments are all defined in plugins separately for fine-grained results. ## Scripts Plugins may also use the script parser to extract entry files and dependencies from commands. A few examples: - GitHub Actions: workflow files may contain `run` commands (e.g. `.github/workflows/ci.yml`) - Husky & Lefthook: Git hooks such as `.git/hooks/pre-push` contain scripts; also `lefthook.yml` has `run` commands - Lint Staged: configuration values are all commands - Nx: task executors and `nx:run-commands` executors in `project.json` contains scripts - Release It: `hooks` contain commands Plugins can also return configuration files. Some examples: - The Angular plugin detects `options.tsConfig` as a TypeScript config file - The GitHub Actions plugin parses `run` commands which may contain configuration file paths ## Source Code When Knip is walking the abstract syntax trees (ASTs) of JavaScript and TypeScript source code files, it looks for imports and exports. But there's a few more (rather obscure) things that Knip detects in the process. Below are examples of additional scripts Knip parses to find entry files and dependencies. ### bun If the `bun` dependency is imported in source code, Knip considers the contents of `$` template tags to be scripts: ```ts import { $ } from 'bun'; await $`bun boxen I ❤ unicorns`; await $`boxen I ❤ unicorns`; ``` Parsing the script results in the `boxen` binary (the `boxen-cli` dependency) as referenced (twice). ### execa If the `execa` dependency is imported in source code, Knip considers the contents of `$` template tags to be scripts: ```ts await $({ stdio: 'inherit' })`c8 node hydrate.js`; ``` Parsing the script results in `hydrate.js` added as an entry file and the `c8` binary/dependency as referenced. ### zx If the `zx` dependency is imported in source code, Knip considers the contents of `$` template tags to be scripts: ```ts await $`node scripts/parse.js`; ``` This will add `scripts/parse.js` as an entry file. [1]: #packagejson [2]: #cli-arguments [3]: #scripts [4]: #source-code ================================================ FILE: packages/docs/src/content/docs/features/source-mapping.md ================================================ --- title: Source Mapping sidebar: order: 4 --- Knip is mostly interested in source code. Analyzing build artifacts hurts performance and often leads to false positives, as they potentially contain bundled code and unresolvable imports. That's why Knip tries to map such build artifacts back to their original source files and analyze those instead. This is done based on `tsconfig.json` settings. ## Example 1: package.json Let's look at an example case with `package.json` and `tsconfig.json` files, and see how "dist" files are mapped to "src" files. ```jsonc title="package.json" { "name": "my-workspace", "main": "index.js", "exports": { ".": "./src/entry.js", "./feat": "./lib/feat.js", "./public": "./dist/app.js", "./public/*": "./dist/*.js", "./public/*.js": "./dist/*.js", "./dist/internal/*": null, }, } ``` With this TypeScript configuration: ```json title="tsconfig.json" { "compilerOptions": { "baseUrl": "src", "outDir": "dist" } } ``` - `./src/entry.js` is not in an `outDir` folder, so it's added as an entry file - `./lib/feat.js` is not in an `outDir` folder, so it's added as an entry file - `./dist/app.js` is in a `dist` folder and mapped to `./src/app.{js,ts}` (¹) - `./dist/*.js` is in a `dist` folder and mapped to `./src/**/*.{js,ts}` (¹) - `./dist/internal/*` is translated to `./dist/internal/**` and files in this directory and deeper are ignored when globbing entry files (¹) full extensions list is actually: `js`, `mjs`, `cjs`, `jsx`, `ts`, `tsx`, `mts`, `cts` In `--debug` mode, look for "Source mapping" to see this in action. :::tip Using `./dist/*.js` means that all files matching `./src/**/*.{js,ts}` are added as entry files. By default, unused exports of entry files are not reported. Use [includeEntryExports][1] to include them. ::: ## Example 2: monorepo Let's say we have this module in a monorepo that imports `helper` from another workspace in the same monorepo: ```ts title="index.js" import { helper } from '@org/shared'; ``` The target workspace `@org/shared` has this `package.json`: ```json title="package.json" { "name": "@org/shared", "main": "dist/index.js" } ``` The module resolver will resolve `@org/shared` to `dist/index.js`. That file is usually compiled and git-ignored, while Knip wants the source file instead. :::tip You may need to compile build artifacts to `outDir` first before Knip can successfully apply source mapping for internal references in a monorepo. ::: If the target workspace has a `tsconfig.json` file with an `outDir` option, Knip will try to map the "dist" file to the "src" file. Then if `src/index.ts` exists, Knip will use that file instead of `dist/index.js`. Currently this only works based on `tsconfig.json`, in the future more source mappings may be added. [1]: ../reference/configuration.md#includeentryexports ================================================ FILE: packages/docs/src/content/docs/guides/configuring-project-files.md ================================================ --- title: Configuring Project Files sidebar: order: 1 --- The `entry` and `project` file patterns are the first and most important options. Getting those right is essential to help you delete more code and make Knip faster: - Start with defaults. Only add targeted `entry` overrides when needed. - Use `project` patterns (with negations) to define the scope for Knip. - Use production mode to exclude tests and other non-production files. - Use `ignore` only to suppress issues in specific files; it does not exclude files from analysis. Let's dive in and expand on all of these. ## Entry files Avoid adding too many files as `entry` files: 1. Knip does not report [unused exports][1] in entry files by default. 2. Proper `entry` and `project` patterns allow Knip to find unused files and exports. ## Unused files Files are reported as unused if they are in the set of `project` files, but are not resolved from the `entry` files: ``` unused files = project files - (entry files + resolved files) ``` See [entry files][2] to see where Knip looks for entry files. Fine-tune `entry` and adjust `project` to fit your codebase. :::tip Use negated `project` patterns to precisely include/exclude files for unused files detection. Use `ignore*` to suppress specific issues in matching files; it does not exclude files from analysis. ::: ## Negated patterns When there are too many files in the analysis, start here. For instance, routes are entry files except those prefixed with an underscore: ```json { "entry": ["src/routes/*.ts", "!src/routes/_*.ts"] } ``` Some files are not part of your source and are reported as unused (false positives)? Use negated `project` patterns: ```json { "entry": ["src/index.ts"], "project": ["src/**/*.ts", "!src/exclude/**"] } ``` ❌   Don't use `ignore` for generated artifacts: ```json title="knip.json" { "entry": ["src/index.ts", "scripts/*.ts"], "ignore": ["build/**", "dist/**", "src/generated.ts"] } ``` ✅   Do define your project boundaries: ```json title="knip.json" { "entry": ["src/index.ts", "scripts/*.ts"], "project": ["src/**", "scripts/**"], "ignore": ["src/generated.ts"] } ``` Why this is better: - `project` defines what belongs to the codebase, so build outputs are excluded from analysis and unused file detection - `ignore` is for the few files that should be analyzed but contain exceptions - Improves performance by analyzing fewer files ## Ignore issues in specific files Use `ignore` when a specific analyzed file is not handled properly by Knip or intentionally contains unused exports (e.g. generated files exporting "everything"): ```json { "entry": ["src/index.ts"], "project": ["src/**/*.ts"], "ignore": ["src/generated.ts"] } ``` Also see [ignoreExportsUsedInFile][3] for a more targeted approach. ## Production Mode Default mode includes tests and other non-production files in the analysis. To focus on production code, use [production mode][4]. Don't try to exclude tests via `ignore` or negated `project` patterns. That's inefficient and ineffective due to entries added by plugins. Use production mode instead. ❌   Don't do this: ```json { "ignore": ["**/*.test.js"] } ``` Why not: `ignore` hides issues from the report; it does not exclude files from analysis. ❌   Also don't do this: ```json { "entry": ["index.ts", "!**/*.test.js"] } ``` Why not: plugins add test files as `entry` files; you can't and shouldn't override that globally. ❌   Or this: ```json { "project": ["**/*.ts", "!**/*.spec.ts"] } ``` Why not: `project` is for unused file detection; negating test files is ineffective because they are `entry` files. ✅   Do this instead: ```shell knip --production ``` To fine-tune the resulting production file set, for instance to exclude test helper files that still show as unused, use the exclamation mark suffix on production patterns: ```json { "entry": ["src/index.ts!"], "project": ["src/**/*.ts!", "!src/test-helpers/**!"] } ``` Remember to keep adding the exclamation mark `suffix!` for production file patterns. :::tip Use the exclamation mark (`!`) on both ends (`!`) to exclude files in production mode. ::: ## Defaults & Plugins To reiterate, the default `entry` and `project` files for each workspace: ```json { "entry": [ "{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}", "src/{index,cli,main}.{js,cjs,mjs,jsx,ts,cts,mts,tsx}" ], "project": ["**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!"] } ``` Next to this, there are other places where [Knip looks for entry files][2]. Additionally, [plugins have plenty of entry files configured][5] that are automatically added as well. [1]: ../typescript/unused-exports.md [2]: ../explanations/entry-files.md [3]: ../reference/configuration.md#ignoreexportsusedinfile [4]: ../features/production-mode.md [5]: ../explanations/plugins.md#entry-files ================================================ FILE: packages/docs/src/content/docs/guides/contributing.md ================================================ --- title: Contributing to Knip --- Here are some ways to contribute to Knip: - Spread the word! - [Star the project][1] - [File an issue with a reproduction][2] - [Pull requests are welcome][3] [Writing a plugin][4] is a great and fun way to get started. The [CONTRIBUTING.md][3] and [DEVELOPMENT.md][5] guides should get you up and running quickly. The main goal of Knip is to keep projects clean & tidy. Everything that contributes to that goal is welcome! [1]: https://github.com/webpro-nl/knip [2]: ./issue-reproduction.md [3]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md [4]: ../writing-a-plugin/index.md [5]: https://github.com/webpro-nl/knip/blob/main/.github/DEVELOPMENT.md ================================================ FILE: packages/docs/src/content/docs/guides/handling-issues.mdx ================================================ --- title: Handling Issues sidebar: order: 3 --- import { Tabs, TabItem } from '@astrojs/starlight/components'; Issues reported by Knip may contain false positives, but also tons of useful information. Getting the most out of Knip may require some configuration. Go over the issue types one by one. For instance, reducing the number of unused files will also reduce the number of unused dependencies. 1. [Unused files][1] 2. [Unused dependencies][2] 3. [Unresolved imports][3] 4. [Unused exports][4] :::tip Try the [Knip Editor Extension][5]! Let your coding agent use the built-in MCP Server and create a custom `knip.json` for you. ::: ## Unused files Getting the list of unused files right trickles down into the other issue types as well, so we start here. Files are reported as unused if they are in the set of `project` files, but not in the set of files resolved from the `entry` files: ``` unused files = project files - (entry files + resolved files) ``` :::tip Addressing reported [Configuration Hints][6] first might help significantly, especially when handling unused files. ::: Common causes for unused files include: - [Missing generated files][7] - [Dynamic import specifiers][8] - [Unsupported arguments in scripts][9] - [Unsupported file formats][10] - [Missing plugin][11] - [Incomplete plugin][12] - [TypeScript path aliases in monorepos][13] - [Relative paths across workspaces][14] - [Integrated monorepos][15] - [Auto-mocking or auto-imports][16] In most cases you can add `entry` patterns manually. Use `--files` to [filter the report][17] and focus only on unused files: ```sh knip --files ``` This works with other issue types as well. For instance, use `--dependencies` to focus only on dependencies and exclude issues related to unused files and exports. :::caution Don't add unused files to the `ignore` option before reading [configuring project files][18]. Learn why and when to use `entry`, `project`, production mode and `ignore*` patterns for better results and performance. ::: ### Missing generated files For certain features, Knip needs to run after relevant files are generated. For instance, [source mapping][19] in a monorepo may require files to be built into `dist` folders first. And generated files in the `src` directory may import other files. For instance, the `src/routeTree.gen.ts` file generated by `@tanstack/router` must exist so Knip can find the imported route files. **Solution**: compile and/or generate the relevant files first so Knip can resolve and find the source files. If Knip still reports false positives, you may need to strategically add an `entry` file manually. ### Dynamic import specifiers Dynamic import specifiers aren't resolved, such as: ```ts const entry = await import(path.join(baseDir, 'entry.ts')); ``` **Solution**: add `entry.ts` to `entry` patterns. ### Unsupported arguments in scripts Some tooling command arguments aren't recognized: ```json { "name": "my-lib", "version": "1.0.0", "scripts": { "build": "unknown-build-cli --entry production.ts" } } ``` **Solution**: add `production.ts` to `entry` patterns. This works the same for any script, also those in GitHub Actions workflows or Git hooks. See [script parser][20] for more details about Knip's script parser. ### Unsupported file formats Entry files referenced in HTML files (e.g. ` ``` **Solution**: add `production.js` to `entry` patterns. Or add an `.html` compiler to extract and resolve the value of ` ================================================ FILE: packages/knip/fixtures/compilers/component.tsx ================================================ export default () =>
1
; ================================================ FILE: packages/knip/fixtures/compilers/enum.ts ================================================ export enum Enum { Member = 'member', } ================================================ FILE: packages/knip/fixtures/compilers/grid.css ================================================ @import "./grid.css"; ================================================ FILE: packages/knip/fixtures/compilers/index.ts ================================================ import identifier from './module.mdx'; import Component from './Component.vue'; import { createApp } from 'vue'; identifier; createApp(Component); ================================================ FILE: packages/knip/fixtures/compilers/knip.ts ================================================ import '@mdx-js/mdx'; export default { compilers: { md: (_text, path) => { if (!path) throw new Error('Path not passed to compiler'); return ''; }, css: async (text: string) => { return [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'); }, }, }; ================================================ FILE: packages/knip/fixtures/compilers/module.mdx ================================================ import Component from './component'; import Docs from './readme.md'; import Styles from './styles.css'; # Header Using a top-level `import type` declaration (`import type { A, B } from 'fake-module'`) ensures the entire import statement is removed during transpilation. You can also use `import { something } from 'another-fake'` inline. Multiple inline codes: `import x from 'x'` and `import y from 'y'` on same line. Nested backticks won't happen but edge case: `import Default from "double-quotes"`. ```js import { fenced } from 'fenced-module'; import * as ns from 'namespace-module'; const x = 1; ``` ```typescript import type { Type } from 'typed-module'; export const y = 2; ``` ``` import { noLang } from 'no-lang-module'; ``` Real import after fenced block should still work (see actual imports at top). ================================================ FILE: packages/knip/fixtures/compilers/package.json ================================================ { "name": "@fixtures/compilers", "devDependencies": { "@mdx-js/mdx": "*", "vue": "*" } } ================================================ FILE: packages/knip/fixtures/compilers/readme.md ================================================ # Header ================================================ FILE: packages/knip/fixtures/compilers/styles.css ================================================ @import "./grid.css"; ================================================ FILE: packages/knip/fixtures/compilers/tsconfig.json ================================================ { "compilerOptions": { "target": "ES2015", "jsx": "preserve" } } ================================================ FILE: packages/knip/fixtures/compilers/unused.css ================================================ ================================================ FILE: packages/knip/fixtures/compilers/unused.md ================================================ ================================================ FILE: packages/knip/fixtures/compilers-manual/component.tsx ================================================ export default () =>
1
; ================================================ FILE: packages/knip/fixtures/compilers-manual/index.ts ================================================ import identifier from './module.mdx'; import './styles.scss'; identifier; ================================================ FILE: packages/knip/fixtures/compilers-manual/knip.ts ================================================ export default { compilers: { mdx: true, scss: true, }, }; ================================================ FILE: packages/knip/fixtures/compilers-manual/module.mdx ================================================ import Component from './component'; # Header ================================================ FILE: packages/knip/fixtures/compilers-manual/package.json ================================================ { "name": "@fixtures/compilers-manual", "devDependencies": {} } ================================================ FILE: packages/knip/fixtures/compilers-manual/styles.scss ================================================ ================================================ FILE: packages/knip/fixtures/compilers-manual/tsconfig.json ================================================ { "compilerOptions": { "target": "ES2015", "jsx": "preserve" } } ================================================ FILE: packages/knip/fixtures/compilers-prisma/package.json ================================================ { "name": "@fixtures/compilers-prisma", "scripts": { "prisma:generate": "prisma generate" }, "devDependencies": { "prisma": "*", "prisma-json-types-generator": "*", "prisma-zod-generator": "*", "prisma-openapi": "*" } } ================================================ FILE: packages/knip/fixtures/compilers-prisma/prisma/schema.prisma ================================================ generator client { provider = "prisma-client" output = "../src/generated/prisma" engineType = "client" moduleFormat = "esm" } generator zod { provider = "prisma-zod-generator" output = "../src/generated/prisma-zod" } generator json { provider = "prisma-json-types-generator" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? } ================================================ FILE: packages/knip/fixtures/compilers-scss/_grid.scss ================================================ $max-width: 1200px; $gutter: 16px; ================================================ FILE: packages/knip/fixtures/compilers-scss/_partial.scss ================================================ $border-radius: 4px; $spacing: 1rem; ================================================ FILE: packages/knip/fixtures/compilers-scss/buttons.scss ================================================ @use "pkg:@fortawesome/fontawesome-free/scss/fontawesome"; @use "./variables" as *; .button { background-color: $primary; padding: 0.5rem 1rem; border: none; border-radius: 4px; &:hover { background-color: darken($primary, 10%); } &--secondary { background-color: $secondary; } } ================================================ FILE: packages/knip/fixtures/compilers-scss/cards.sass ================================================ @use "./variables" as * .card background: white border-radius: 8px padding: 1rem box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) &__header border-bottom: 1px solid $secondary padding-bottom: 0.5rem &__body padding: 1rem 0 ================================================ FILE: packages/knip/fixtures/compilers-scss/components.scss ================================================ .component { color: red; } ================================================ FILE: packages/knip/fixtures/compilers-scss/indented.sass ================================================ @use "./mixins" @use './variables' as vars @import "./legacy" @forward "./utils" .indented color: vars.$secondary ================================================ FILE: packages/knip/fixtures/compilers-scss/index.ts ================================================ import './styles.scss'; import './indented.sass'; import './buttons.scss'; import './cards.sass'; ================================================ FILE: packages/knip/fixtures/compilers-scss/legacy.scss ================================================ .legacy-component { display: block; margin: 0 auto; } ================================================ FILE: packages/knip/fixtures/compilers-scss/mixins.scss ================================================ @mixin center { display: flex; justify-content: center; align-items: center; } ================================================ FILE: packages/knip/fixtures/compilers-scss/package.json ================================================ { "name": "@fixtures/compilers-scss", "dependencies": { "@fortawesome/fontawesome-free": "*" }, "devDependencies": { "bootstrap": "*", "sass": "*" } } ================================================ FILE: packages/knip/fixtures/compilers-scss/styles.scss ================================================ @use "sass:math"; @use "pkg:@fortawesome/fontawesome-free"; @use "pkg:bootstrap/scss/bootstrap"; @use "components"; @use './variables' as vars; @use "./theme" as *; @use "./partial"; @use "./_grid"; @forward "./mixins"; @forward "./utils" as util-*; @import "./legacy"; .icon { @include fa-icon; color: vars.$primary; } ================================================ FILE: packages/knip/fixtures/compilers-scss/theme.scss ================================================ $font-size-base: 1rem; $line-height-base: 1.5; body { font-size: $font-size-base; line-height: $line-height-base; } ================================================ FILE: packages/knip/fixtures/compilers-scss/unused.scss ================================================ .unused { display: none; } ================================================ FILE: packages/knip/fixtures/compilers-scss/utils.scss ================================================ @mixin clearfix { &::after { content: ""; display: table; clear: both; } } @mixin visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; } ================================================ FILE: packages/knip/fixtures/compilers-scss/variables.scss ================================================ $primary: #007bff; $secondary: #6c757d; $success: #28a745; ================================================ FILE: packages/knip/fixtures/compilers-tailwind/components.css ================================================ @import "./unused.css"; .component { @apply bg-blue-500; } ================================================ FILE: packages/knip/fixtures/compilers-tailwind/index.ts ================================================ import './styles.css'; ================================================ FILE: packages/knip/fixtures/compilers-tailwind/local-js-plugin.js ================================================ export default function () {} ================================================ FILE: packages/knip/fixtures/compilers-tailwind/local-ts-plugin.ts ================================================ import { heroui } from '@heroui/react'; export default heroui(); ================================================ FILE: packages/knip/fixtures/compilers-tailwind/package.json ================================================ { "name": "@fixtures/compilers-tailwind", "dependencies": { "tailwindcss": "*" }, "devDependencies": { "@heroui/react": "*", "@tailwindcss/forms": "*", "@tailwindcss/typography": "*" } } ================================================ FILE: packages/knip/fixtures/compilers-tailwind/styles.css ================================================ @import "tailwindcss"; @import "./components.css"; @plugin "@tailwindcss/forms"; @plugin "@tailwindcss/typography"; @plugin "./local-js-plugin.js"; @plugin "./local-ts-plugin.ts"; @plugin "./missing-plugin.ts"; ================================================ FILE: packages/knip/fixtures/compilers-tailwind/unused.css ================================================ .unused { color: red; } ================================================ FILE: packages/knip/fixtures/config-js-async/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-js-async/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-js-async/knip.config.js ================================================ module.exports = async () => ({ ignore: ['dangling.js'], }); ================================================ FILE: packages/knip/fixtures/config-js-async/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-js-async/package.json ================================================ { "name": "@fixtures/config-js-async" } ================================================ FILE: packages/knip/fixtures/config-js-flat/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-js-flat/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-js-flat/knip.js ================================================ module.exports = { ignore: ['dangling.js'], }; ================================================ FILE: packages/knip/fixtures/config-js-flat/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-js-flat/package.json ================================================ { "name": "@fixtures/config-js-flat" } ================================================ FILE: packages/knip/fixtures/config-json/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-json/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-json/knip.json ================================================ { "ignore": ["dangling.js"] } ================================================ FILE: packages/knip/fixtures/config-json/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-json/package.json ================================================ { "name": "@fixtures/config-json" } ================================================ FILE: packages/knip/fixtures/config-mjs-async/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-mjs-async/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-mjs-async/knip.mjs ================================================ const config = async () => ({ ignore: ['dangling.js'], }); export default config; ================================================ FILE: packages/knip/fixtures/config-mjs-async/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-mjs-async/package.json ================================================ { "name": "@fixtures/config-mjs-async" } ================================================ FILE: packages/knip/fixtures/config-mjs-flat/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-mjs-flat/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-mjs-flat/knip.mjs ================================================ const config = { ignore: ['dangling.js'], }; export default config; ================================================ FILE: packages/knip/fixtures/config-mjs-flat/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-mjs-flat/package.json ================================================ { "name": "@fixtures/config-mjs-flat" } ================================================ FILE: packages/knip/fixtures/config-package-json/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-package-json/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-package-json/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-package-json/package.json ================================================ { "name": "@fixtures/config-package-json", "knip": { "ignore": [ "dangling.js" ] } } ================================================ FILE: packages/knip/fixtures/config-ts-async/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-ts-async/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-ts-async/knip.ts ================================================ import type { KnipConfig } from '../../src/index'; const config = async (): Promise => ({ ignore: ['dangling.js'], }); export default config; ================================================ FILE: packages/knip/fixtures/config-ts-async/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-ts-async/package.json ================================================ { "name": "@fixtures/config-ts-async" } ================================================ FILE: packages/knip/fixtures/config-ts-async/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/config-ts-flat/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-ts-flat/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-ts-flat/knip.config.ts ================================================ import type { KnipConfig } from '../../src/index'; const config: KnipConfig = { ignore: ['dangling.js'], }; export default config; ================================================ FILE: packages/knip/fixtures/config-ts-flat/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-ts-flat/package.json ================================================ { "name": "@fixtures/config-ts-flat" } ================================================ FILE: packages/knip/fixtures/config-ts-flat/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/config-ts-function/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-ts-function/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-ts-function/knip.ts ================================================ import type { KnipConfig } from '../../src/index'; const config = (): KnipConfig => ({ ignore: ['dangling.js'], }); export default config; ================================================ FILE: packages/knip/fixtures/config-ts-function/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-ts-function/package.json ================================================ { "name": "@fixtures/config-ts-function" } ================================================ FILE: packages/knip/fixtures/config-ts-function/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/config-yaml/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/config-yaml/index.js ================================================ import * as MyNamespace from './my-namespace'; export const b = MyNamespace.y; ================================================ FILE: packages/knip/fixtures/config-yaml/knip.yaml ================================================ ignore: - 'dangling.js' ================================================ FILE: packages/knip/fixtures/config-yaml/my-namespace.js ================================================ const x = 1; export const y = () => x; ================================================ FILE: packages/knip/fixtures/config-yaml/package.json ================================================ { "name": "@fixtures/config-yaml" } ================================================ FILE: packages/knip/fixtures/configuration-hints/knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "entry": ["src/entry.js"], "project": ["src/**"], "workspaces": {} } ================================================ FILE: packages/knip/fixtures/configuration-hints/lib/index.js ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints/lib/package.json ================================================ { "name": "@fixtures/configuration-hints__lib" } ================================================ FILE: packages/knip/fixtures/configuration-hints/package.json ================================================ { "name": "@fixtures/configuration-hints", "workspaces": [ "lib" ] } ================================================ FILE: packages/knip/fixtures/configuration-hints/src/entry.js ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin/create-typescript-app.config.js ================================================ export default {}; ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin/knip.json ================================================ { "entry": ["create-typescript-app.config.js", "svgo.config.mjs"], "project": ["create-typescript-app.config.js"] } ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin/package.json ================================================ { "name": "@fixtures/configuration-hints-plugin", "dependencies": { "create-typescript-app": "*", "svgo": "*" } } ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin/svgo.config.mjs ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin-override/create-typescript-app.config.ts ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin-override/knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "entry": ["svgo.config.js", "yarn.config.cjs"], "create-typescript-app": { "entry": ["create-typescript-app.config.ts"] } } ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin-override/package.json ================================================ { "name": "@fixtures/configuration-hints-plugin-override", "dependencies": { "create-typescript-app": "*", "svgo": "*", "yarn": "*" } } ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin-override/svgo.config.js ================================================ export default {}; ================================================ FILE: packages/knip/fixtures/configuration-hints-plugin-override/yarn.config.cjs ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints2/knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "entry": ["src/entry.js", "lib/index.js"], "project": ["src/**"], "workspaces": { ".": { "entry": ["src/entry.js", "lib/index.js"], "project": ["src/**", "lib/**"] } } } ================================================ FILE: packages/knip/fixtures/configuration-hints2/lib/index.js ================================================ ================================================ FILE: packages/knip/fixtures/configuration-hints2/lib/package.json ================================================ { "name": "@fixtures/configuration-hints__lib" } ================================================ FILE: packages/knip/fixtures/configuration-hints2/package.json ================================================ { "name": "@fixtures/configuration-hints", "workspaces": [ "lib" ] } ================================================ FILE: packages/knip/fixtures/configuration-hints2/src/entry.js ================================================ ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/.github/workflows/test.yml ================================================ on: push jobs: integration: runs-on: ubuntu-latest steps: - run: playwright test -c playwright.e2e.config.ts working-directory: e2e ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/components/package.json ================================================ { "name": "@fixtures/cross-workspace-inputs__components", "devDependencies": { "vitest": "*" } } ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/components/vitest.components.config.ts ================================================ ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/e2e/package.json ================================================ { "name": "@fixtures/cross-workspace-inputs__e2e", "devDependencies": { "@playwright/test": "*" } } ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/e2e/playwright.e2e.config.ts ================================================ const config = { testDir: 'tests', testMatch: ['**/*.ts'], }; export default config; ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/e2e/tests/feature.ts ================================================ ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/knip.json ================================================ {} ================================================ FILE: packages/knip/fixtures/cross-workspace-inputs/package.json ================================================ { "name": "@fixtures/cross-workspace-inputs", "workspaces": [ "e2e", "components" ], "scripts": { "test": "yarn --cwd components vitest -c vitest.components.config.ts" } } ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/index.ts ================================================ import anything from '~/my-module'; anything; ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/knip.json ================================================ { "$schema": "https://unpkg.com/knip@2/schema.json", "workspaces": { ".": { "paths": { "~/*": ["./*"], "@lib": ["./lib/index.ts"], "@lib/*": ["./lib/*"] } }, "ws": { "paths": { "#utilities/*": ["./util/*"], "~images/*": ["./assets/img/*"], "lib/*": ["./lib/*"] } } } } ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/lib/fn.ts ================================================ export default () => void 0; ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/lib/index.ts ================================================ export default () => void 0; ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/my-module.ts ================================================ import index from '@lib'; import fn from '@lib/fn'; index; fn; ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/package.json ================================================ { "name": "@fixtures/custom-paths-workspaces", "workspaces": [ "ws" ] } ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/ws/index.ts ================================================ import main from 'lib/main'; import lang from '#utilities/lang'; import svg from '~images/logo.svg'; main; lang; svg; ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/ws/lib/main.ts ================================================ ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/ws/package.json ================================================ { "name": "@fixtures/custom-paths-workspaces__ws" } ================================================ FILE: packages/knip/fixtures/custom-paths-workspaces/ws/util/lang.ts ================================================ export default () => void 0; ================================================ FILE: packages/knip/fixtures/definitely-typed/index.ts ================================================ import micromatch from 'micromatch'; import anything from 'next'; import type { Things } from '@types/without-the-package'; import type { Expression } from 'estree'; import type { Schema } from 'type-only-production-types'; ================================================ FILE: packages/knip/fixtures/definitely-typed/package.json ================================================ { "name": "@fixtures/definitely-typed", "scripts": { "test": "mocha" }, "dependencies": { "next": "*", "micromatch": "*", "type-only-production-types": "*" }, "devDependencies": { "@types/estree": "*", "@types/micromatch": "*", "@types/mocha": "*", "@types/react-dom": "*", "@types/node": "*", "@types/unused": "*", "@types/without-the-package": "*", "mocha": "*" } } ================================================ FILE: packages/knip/fixtures/dependencies/entry.ts ================================================ import is from '@sindresorhus/is'; import has, { program } from './my-module.js'; const what = is(has); const match = typeof program === 'function'; what; match; ================================================ FILE: packages/knip/fixtures/dependencies/knip.json ================================================ { "entry": ["entry.ts!"], "project": ["*.ts!"], "ignoreDependencies": ["stream"] } ================================================ FILE: packages/knip/fixtures/dependencies/my-module.ts ================================================ import has from 'has'; import JSONStream from 'JSONStream'; JSONStream; async function main() { return [require('ansi-regex'), import('ansi-regex')]; } export const program = main(); export default has(Object.prototype, 'hasOwnProperty'); ================================================ FILE: packages/knip/fixtures/dependencies/package.json ================================================ { "name": "@fixtures/dependencies", "scripts": { "start": "start-server", "test": "jest" }, "dependencies": { "@tootallnate/once": "*", "@sindresorhus/is": "*", "fs-extra": "*", "has": "*", "stream": "*", "JSONStream": "*" }, "peerDependencies": { "ansi-regex": "*", "jquery": "*" }, "optionalDependencies": { "fs-optional": "*" }, "devDependencies": { "mocha": "*" } } ================================================ FILE: packages/knip/fixtures/dependencies/tsconfig.json ================================================ { "compilerOptions": { "allowJs": true, "module": "commonjs", "moduleResolution": "node" } } ================================================ FILE: packages/knip/fixtures/dependencies/unused-module.ts ================================================ import { EventEmitter } from 'node:events'; import once from '@tootallnate/once'; const emitter = new EventEmitter(); setTimeout(() => emitter.emit('event', 'name'), 1); const result = await once(emitter, 'event'); result; ================================================ FILE: packages/knip/fixtures/dependencies-types/index.ts ================================================ import { meta } from '@eslint/js'; import { Ajv } from 'ajv'; meta; Ajv; ================================================ FILE: packages/knip/fixtures/dependencies-types/package.json ================================================ { "name": "@fixtures/dependencies-types", "dependencies": { "@eslint/js": "^9.20.0", "ajv": "^8.17.1" }, "devDependencies": { "@types/ajv": "^0.0.5", "@types/eslint__js": "^8.42.3", "@types/node": "^20.14.8" } } ================================================ FILE: packages/knip/fixtures/dts/assets.d.ts ================================================ /// declare module '*.svg'; declare module '*.html?raw' { const value: string; export default value; } ================================================ FILE: packages/knip/fixtures/dts/block.html ================================================
content
================================================ FILE: packages/knip/fixtures/dts/index.ts ================================================ import b from './block.html?raw'; import s from './image.svg'; import n from './normal'; import type { MyConfig } from './types.js'; import './types'; import { Palette } from './module-augmentation'; b; s; n; Palette.red; ================================================ FILE: packages/knip/fixtures/dts/module-augmentation.ts ================================================ interface AppTheme { color: string; } declare module '@org/ui' { export interface Theme extends AppTheme {} } export namespace Palette { export const red = '#f00'; export const blue = '#00f'; } ================================================ FILE: packages/knip/fixtures/dts/normal.ts ================================================ export default 1; ================================================ FILE: packages/knip/fixtures/dts/package.json ================================================ { "name": "@fixtures/dts" } ================================================ FILE: packages/knip/fixtures/dts/svg.d.ts ================================================ declare module '*.svg' { export const ReactComponent: SVGElement; const src: string; export default src; } ================================================ FILE: packages/knip/fixtures/dts/tsconfig.json ================================================ {} ================================================ FILE: packages/knip/fixtures/dts/types.d.ts ================================================ export interface MyConfig { name: string; } ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/package.json ================================================ { "name": "@fixtures/dts-baseurl-implicit-relative" } ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/components/Button.d.ts ================================================ export const Button: () => null; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/components/Button.jsx ================================================ export const Button = () => null; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/dir/subdir/index.d.ts ================================================ const h: () => number; export default h; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/dir/subdir/index.js ================================================ const h = () => { return 1; }; export default h; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/index.ts ================================================ import h from 'dir/subdir'; import { fn } from 'utils/fn'; import { obj } from 'utils/obj.cjs'; import { str } from 'utils/str.mjs'; import { Button } from 'components/Button'; h; fn; obj; str; Button; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/fn.d.ts ================================================ export const fn: () => void; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/fn.js ================================================ export const fn = () => {}; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/obj.cjs ================================================ module.exports.obj = () => {}; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/obj.d.cts ================================================ export const obj: () => void; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/str.d.mts ================================================ export const str: () => void; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/src/utils/str.mjs ================================================ export const str = () => {}; ================================================ FILE: packages/knip/fixtures/dts-baseurl-implicit-relative/tsconfig.json ================================================ { "compilerOptions": { "baseUrl": "src" } } ================================================ FILE: packages/knip/fixtures/dts-compiled/knip.ts ================================================ import type { KnipConfig } from 'knip'; const config: KnipConfig = { compilers: { graphql: () => '', }, }; export default config; ================================================ FILE: packages/knip/fixtures/dts-compiled/package.json ================================================ { "name": "@fixtures/dts-compiled", "private": true, "type": "module" } ================================================ FILE: packages/knip/fixtures/dts-compiled/src/App.tsx ================================================ import ExampleQuery from './ExampleQuery.graphql'; function App() { return ( <>

Vite + React

        {JSON.stringify(ExampleQuery, null, 2)}
      
); } export default App; ================================================ FILE: packages/knip/fixtures/dts-compiled/src/ExampleQuery.graphql ================================================ query ExampleQuery { example { name description } } ================================================ FILE: packages/knip/fixtures/dts-compiled/src/ExampleQuery.graphql.d.ts ================================================ import * as Types from './types'; export type ExampleQueryQueryVariables = Types.Exact<{ [key: string]: never }>; export type ExampleQueryQuery = { __typename?: 'Query'; example?: { __typename?: 'Example'; name?: string | null; description?: string | null } | null; }; ================================================ FILE: packages/knip/fixtures/dts-compiled/src/UnusedQuery.graphql ================================================ query UnusedQuery { example { name } } ================================================ FILE: packages/knip/fixtures/dts-compiled/src/UnusedQuery.graphql.d.ts ================================================ import * as Types from './types'; export type UnusedQueryQueryVariables = Types.Exact<{ [key: string]: never }>; export type UnusedQueryQuery = { __typename?: 'Query'; example?: { __typename?: 'Example'; name?: string | null } | null; }; ================================================ FILE: packages/knip/fixtures/dts-compiled/src/main.tsx ================================================ import App from './App.tsx'; App; ================================================ FILE: packages/knip/fixtures/dts-compiled/src/types.ts ================================================ export type Exact = { [K in keyof T]: T[K] }; ================================================ FILE: packages/knip/fixtures/dts-compiled/tsconfig.json ================================================ {} ================================================ FILE: packages/knip/fixtures/duplicate-dependencies/index.ts ================================================ import ts from 'typescript'; ts; ================================================ FILE: packages/knip/fixtures/duplicate-dependencies/knip.json ================================================ { "entry": ["index.ts!"], "project": ["*.ts!"] } ================================================ FILE: packages/knip/fixtures/duplicate-dependencies/package.json ================================================ { "name": "@fixtures/duplicate-dependencies", "dependencies": { "typescript": "*" }, "devDependencies": { "typescript": "*" } } ================================================ FILE: packages/knip/fixtures/duplicate-exports-alias/helpers.ts ================================================ export const isAlias = true; /** @alias */ export default isAlias; export const isUntagged = true; export const isUntaggedAlias = isUntagged; export { reExportedValue } from './reexported'; export const reExportedAlias = reExportedValue; ================================================ FILE: packages/knip/fixtures/duplicate-exports-alias/index.ts ================================================ import { isAlias, reExportedAlias } from './helpers'; import { handler } from './specifier-default'; isAlias; reExportedAlias; handler; ================================================ FILE: packages/knip/fixtures/duplicate-exports-alias/package.json ================================================ { "name": "@fixtures/duplicate-exports-alias" } ================================================ FILE: packages/knip/fixtures/duplicate-exports-alias/reexported.ts ================================================ export const reExportedValue = true; ================================================ FILE: packages/knip/fixtures/duplicate-exports-alias/specifier-default.ts ================================================ function handler() { return true; } export { handler }; export default handler; ================================================ FILE: packages/knip/fixtures/empty-main/index.ts ================================================ export const main = 1; ================================================ FILE: packages/knip/fixtures/empty-main/knip.json ================================================ { "entry": ["index.ts"] } ================================================ FILE: packages/knip/fixtures/empty-main/package.json ================================================ { "name": "@fixtures/empty-main", "main": "", "module": "", "types": "", "bin": "" } ================================================ FILE: packages/knip/fixtures/entry-exports-enum-members/fruit.ts ================================================ import type { Tree } from './tree'; export enum Fruit { apple = 'apple', orange = 'orange', } export interface Farmer { plants: Tree[]; } ================================================ FILE: packages/knip/fixtures/entry-exports-enum-members/index.ts ================================================ export { Fruit, Farmer } from './fruit'; export { Tree } from './tree'; ================================================ FILE: packages/knip/fixtures/entry-exports-enum-members/main.ts ================================================ import { Fruit } from '.'; const fruitBasket = { apple: Fruit.apple, orange: Fruit.orange, }; ================================================ FILE: packages/knip/fixtures/entry-exports-enum-members/package.json ================================================ { "name": "@fixtures/entry-exports-enum-members" } ================================================ FILE: packages/knip/fixtures/entry-exports-enum-members/tree.ts ================================================ import type { Fruit } from './fruit'; export interface Tree { fruit: Fruit; } ================================================ FILE: packages/knip/fixtures/entry-exports-namespace/index.ts ================================================ export { NS } from './mid'; ================================================ FILE: packages/knip/fixtures/entry-exports-namespace/main.ts ================================================ import { NS } from './mid'; NS.x; ================================================ FILE: packages/knip/fixtures/entry-exports-namespace/mid.ts ================================================ export * as NS from './ns'; ================================================ FILE: packages/knip/fixtures/entry-exports-namespace/ns.ts ================================================ export const x = 1; export const y = 1; ================================================ FILE: packages/knip/fixtures/entry-exports-namespace/package.json ================================================ { "name": "@fixtures/entry-exports-namespace" } ================================================ FILE: packages/knip/fixtures/entry-files/cli.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/export-index.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/local-default.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/local-import.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/local-node.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/local-require.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/main.js ================================================ ================================================ FILE: packages/knip/fixtures/entry-files/package.json ================================================ { "name": "@fixtures/entry-files", "main": "main.js", "bin": "./cli.js", "exports": { ".": "./export-index.js", "./local": { "default": "./local-default.js", "import": "./local-import.js", "node": "./local-node.js", "require": "./local-require.js" } } } ================================================ FILE: packages/knip/fixtures/entry-js/dangling.js ================================================ export const unusedFile = true; ================================================ FILE: packages/knip/fixtures/entry-js/index.js ================================================ import { myExport } from './my-module.js'; export const ignoredExportInEntryFile = myExport; ================================================ FILE: packages/knip/fixtures/entry-js/my-module.ts ================================================ import * as MyNamespace from './my-namespace.js'; const x = MyNamespace.x; const y = MyNamespace.y; export const unused = 1; export const myExport = y(x); export type AnyType = any; export default myExport; ================================================ FILE: packages/knip/fixtures/entry-js/my-namespace.ts ================================================ export const x = 1; export const y = (x: number) => x; export const key = 3; export interface MyNamespace {} ================================================ FILE: packages/knip/fixtures/entry-js/package.json ================================================ { "name": "@fixtures/entry-js", "knip": { "entry": [ "index.js" ], "project": [ "*.{js,ts}" ] } } ================================================ FILE: packages/knip/fixtures/entry-js/tsconfig.json ================================================ { "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { "allowJs": true } } ================================================ FILE: packages/knip/fixtures/enum-members/index.ts ================================================ import { MyEnum, TestEnum, Category } from './members'; const a: MyEnum.A_UsedExternal = 1; const b: TestEnum = { ['']: 'test' }; export enum EntryEnum { UsedMemberInEntryEnum = 1, UnusedMemberInEntryEnum = 1, } function setCategory(cat: Category) {} type CategoryKey = keyof typeof Category; ================================================ FILE: packages/knip/fixtures/enum-members/members.ts ================================================ import { type EntryEnum } from './index'; enum UnexportedEnun { Member = 1, } export enum MyEnum { A_UsedExternal = 1, B_Unused = 1, C_UsedInternal = 1, 'D-Key' = 'D-Value', } const myNumber: MyEnum.C_UsedInternal = 1; type Used = EntryEnum; const U: EntryEnum.UsedMemberInEntryEnum = 1; export enum TestEnum { '' = 'test', } export enum Category { Ambient = 'Ambient', Playback = 'Playback', } ================================================ FILE: packages/knip/fixtures/enum-members/package.json ================================================ { "name": "@fixtures/enum-members" } ================================================ FILE: packages/knip/fixtures/enum-members-enumerated/directions.ts ================================================ export enum Direction { NORTH = 'north', SOUTH = 'south', EAST = 'east', WEST = 'west', } interface Route { direction?: Direction; } ================================================ FILE: packages/knip/fixtures/enum-members-enumerated/fruits.ts ================================================ export enum Fruits { apple = 'apple', orange = 'orange', } ================================================ FILE: packages/knip/fixtures/enum-members-enumerated/index.ts ================================================ import { Fruits } from './fruits'; import { Direction } from './directions'; Fruits.apple; Object.keys(Fruits); Object.values(Fruits); Object.entries(Fruits); Object.getOwnPropertyNames(Direction); ================================================ FILE: packages/knip/fixtures/enum-members-enumerated/package.json ================================================ { "name": "@fixtures/enum-members-enumerated" } ================================================ FILE: packages/knip/fixtures/export-default-type/class.js ================================================ class MyClass {} export default MyClass; ================================================ FILE: packages/knip/fixtures/export-default-type/const.js ================================================ const fruit = 1; export default fruit; ================================================ FILE: packages/knip/fixtures/export-default-type/function.js ================================================ function fn() {} export default fn; ================================================ FILE: packages/knip/fixtures/export-default-type/index.js ================================================ import './const.js'; import './class.js'; import './let.js'; import './var.js'; import './function.js'; ================================================ FILE: packages/knip/fixtures/export-default-type/let.js ================================================ let fruit = 1; export default fruit; ================================================ FILE: packages/knip/fixtures/export-default-type/package.json ================================================ { "name": "@fixtures/export-default-type" } ================================================ FILE: packages/knip/fixtures/export-default-type/var.js ================================================ var fruit = 1; export default fruit; ================================================ FILE: packages/knip/fixtures/export-spread/array.ts ================================================ const numbers = [1, 2, 3]; export const [FIRST, ...SPREAD_ARR] = numbers; ================================================ FILE: packages/knip/fixtures/export-spread/index.ts ================================================ import { FIRST, SPREAD_ARR } from './array.ts'; import { FOURTH, SPREAD_OBJ } from './object.ts'; FIRST; SPREAD_ARR; FOURTH; SPREAD_OBJ; ================================================ FILE: packages/knip/fixtures/export-spread/object.ts ================================================ const numbers = { FOURTH: 4, FIFTH: 5, SIXTH: 6 }; export const { FOURTH, ...SPREAD_OBJ } = numbers; ================================================ FILE: packages/knip/fixtures/export-spread/package.json ================================================ { "name": "@fixed/export-spread", "type": "module" } ================================================ FILE: packages/knip/fixtures/exports/default-arrow-function.ts ================================================ export default () => 1; ================================================ FILE: packages/knip/fixtures/exports/default-class.ts ================================================ export default class {} ================================================ FILE: packages/knip/fixtures/exports/default-function.ts ================================================ export default function () {} ================================================ FILE: packages/knip/fixtures/exports/default-generator-function.ts ================================================ export default function* () {} ================================================ FILE: packages/knip/fixtures/exports/default-named-class.ts ================================================ export default class ClassName {} ================================================ FILE: packages/knip/fixtures/exports/default-named-function.ts ================================================ export default function functionName() {} ================================================ FILE: packages/knip/fixtures/exports/default-named-generator-function.ts ================================================ export default function* generatorFunctionName() {} ================================================ FILE: packages/knip/fixtures/exports/default.ts ================================================ export const NamedExport = 1; export default () => 1; ================================================ FILE: packages/knip/fixtures/exports/dynamic-import.ts ================================================ export default () => {}; export const unusedZero = 0; export const used = true; ================================================ FILE: packages/knip/fixtures/exports/export-is.ts ================================================ const x = 1; export = x; ================================================ FILE: packages/knip/fixtures/exports/index.ts ================================================ import './odd'; import { exportedResult } from './my-module.js'; import { num, str, functionName, className, generatorFunctionName, name1, name4, exportedA, exportedB, } from './named-exports'; import type { MyNum, MyString, MyInterface } from './types'; num; str; functionName; className; generatorFunctionName; name1; name4; exportedA; exportedB; type Used = MyNum | MyString | MyInterface; const dynamic = await import('./dynamic-import'); dynamic; async function main() { const { used } = await import('./dynamic-import'); used; } export const entryFileExport = exportedResult; export type EntryFileExportType = any; export type { MixType } from './my-mix'; export { MixClass } from './my-mix'; ================================================ FILE: packages/knip/fixtures/exports/my-mix.ts ================================================ export const unusedInMix = 1; export interface MixType {} export class MixClass {} ================================================ FILE: packages/knip/fixtures/exports/my-module.ts ================================================ import defaultArrowFn from './default-arrow-function'; import defaultClass from './default-class'; import defaultFn from './default-function'; import defaultGenFn from './default-generator-function'; import defaultNamedClass from './default-named-class'; import defaultNamedFn from './default-named-function'; import defaultNamedGenFn from './default-named-generator-function'; import _default from './default.js'; import * as MyNamespace from './my-namespace.js'; defaultArrowFn; defaultClass; defaultFn; defaultGenFn; defaultNamedClass; defaultNamedFn; defaultNamedGenFn; _default; const nsNumber = MyNamespace.nsNumber; const nsFunction = MyNamespace.nsFunction; export const unusedNumber = 1; export const unusedFunction = async (arg: T) => arg; export const exportedResult = nsFunction(nsNumber); export type MyAnyType = any; export default exportedResult; ================================================ FILE: packages/knip/fixtures/exports/my-namespace.ts ================================================ export const nsNumber = 1; export const nsFunction = (x: number) => x; export const nsUnusedKey = 3; export interface MyNamespace {} ================================================ FILE: packages/knip/fixtures/exports/named-exports.ts ================================================ export const num = 1; export const str = 'a'; export function functionName() {} export class className {} export function* generatorFunctionName() {} export const { name1, name2: renamedExport } = {}; export const [namedExport, name4] = []; function exportedA() {} function exportedB() {} export { exportedA, exportedB }; ================================================ FILE: packages/knip/fixtures/exports/odd.ts ================================================ import one = require('./export-is'); one; ================================================ FILE: packages/knip/fixtures/exports/package.json ================================================ { "name": "@fixtures/exports" } ================================================ FILE: packages/knip/fixtures/exports/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/exports/types.ts ================================================ export type MyNum = number; export type MyString = string; export enum MyEnum {} export interface MyInterface {} type MyType = 1; export type { MyType }; ================================================ FILE: packages/knip/fixtures/exports-default-interface/enum.ts ================================================ enum MyEnum { id = 0, } export default MyEnum; ================================================ FILE: packages/knip/fixtures/exports-default-interface/index.ts ================================================ import Default_MyType from './type'; import Default_MyEnum from './enum'; import Default_MyInterface from './interface'; const i: Default_MyInterface = { id: 0 }; const e: Default_MyEnum = 0; const m: Default_MyEnum.id = 0; const t: Default_MyType = {}; i; e; m; t; ================================================ FILE: packages/knip/fixtures/exports-default-interface/interface.ts ================================================ export default interface MyInterface { id: number; } ================================================ FILE: packages/knip/fixtures/exports-default-interface/package.json ================================================ { "name": "@fixtures/exports-default-interface" } ================================================ FILE: packages/knip/fixtures/exports-default-interface/type.ts ================================================ type MyType = unknown; export default MyType; ================================================ FILE: packages/knip/fixtures/exports-special-characters/exports.ts ================================================ export const $dollar = '$'; export const dollar$ = '$$'; export const _underscore = '_'; export const __underscores = '__'; export class DollarMembers { $member: string; member$: string; $method: () => string; method$: () => string; } export class $Dollar {} export type $DollarType = string; export enum Characters { Used = 1, ' ' = ' ', '-' = '-', ',' = ',', ':' = ':', '?' = '?', '.' = '.', '(' = '(', ')' = ')', '[' = '[', ']' = ']', '{' = '{', '}' = '}', '@' = '@', '*' = '*', '/' = '/', '\\' = '\\', '+' = '+', '|' = '|', $ = '$', Slash = '/', Space = ' ', } ================================================ FILE: packages/knip/fixtures/exports-special-characters/index.ts ================================================ import { type Characters, DollarMembers } from './exports'; type Ref = Characters; const u: Characters.Used = 1; const instance = new DollarMembers(); ================================================ FILE: packages/knip/fixtures/exports-special-characters/package.json ================================================ { "name": "@fixtures/exports-special-characters" } ================================================ FILE: packages/knip/fixtures/exports-value-refs/index.ts ================================================ import type { MyInterface } from './refs.js'; const x: MyInterface = { _class: 1, _type: { key: 1 }, _fn: () => {}, _const: 1 }; ================================================ FILE: packages/knip/fixtures/exports-value-refs/package.json ================================================ { "name": "@fixtures/exports-value-refs", "knip": { "ignoreExportsUsedInFile": { "interface": true, "type": true } } } ================================================ FILE: packages/knip/fixtures/exports-value-refs/refs.ts ================================================ export interface MyInterface { _class: MyClass; _type: MyType; _fn: typeof fn; _const: typeof myNumber; } export type MyType = { key: 1; }; export class MyClass {} export class NotInExportedType {} export interface FnOptions { verbose: boolean; } export function fn(n: unknown, options?: FnOptions) {} export const myNumber = 1; const instance = new MyClass(); const inst = new NotInExportedType(); const total = myNumber + myNumber; total; interface MyInterface2 { _class2: NotInExportedType; } const x: MyInterface2 = { _class2: 1 }; export const myValue: unknown = {}; export const myResult: unknown = fn(myValue); ================================================ FILE: packages/knip/fixtures/exports-value-refs-default/index.ts ================================================ import { Bird } from './refs.js'; const bird: Bird = { ref1: () => ({ skin: 'green' }), }; ================================================ FILE: packages/knip/fixtures/exports-value-refs-default/package.json ================================================ { "name": "@fixtures/exports-value-refs-default" } ================================================ FILE: packages/knip/fixtures/exports-value-refs-default/refs.ts ================================================ export interface Lizard { skin: string; } export class Reptile { skin: string; } export const SkinColor = 'green'; export type Bird = { ref0: typeof Reptile; ref1: () => Lizard; ref2: typeof SkinColor; }; export function logger(s: string) { return s; } function setLogger(log: typeof logger): void { log; } export type UnusedTypeInUnusedExport = { id: number }; export interface UnusedInterface { api: UnusedTypeInUnusedExport; } export class UnusedClass {} export type UnusedTypeWithClass = typeof UnusedClass; const obj = { destrRefObj: 1, }; const arr = [1, 2, 3]; export const { destrRefObj } = obj; export const [destrRefArr] = arr; destrRefObj; destrRefArr; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/index.ts ================================================ import styling1 from './styles1.css.ts'; import styling2 from './styles2.css.js'; import styling3 from './styles3.css.ts'; styling1; styling2; styling3; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/package.json ================================================ { "name": "@fixtures/extensions-css-ts" } ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles1.css.ts ================================================ import styles from './styles1a.css.ts'; export default styles; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles1a.css.ts ================================================ export default {}; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles2.css.ts ================================================ import styles from './styles2a.css.js'; export default styles; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles2a.css.ts ================================================ export default {}; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles3.css.ts ================================================ import styles from './styles3a.css'; export default styles; ================================================ FILE: packages/knip/fixtures/extensions-css-ts/styles3a.css.ts ================================================ export default {}; ================================================ FILE: packages/knip/fixtures/fix/.prettierrc ================================================ { "singleQuote": true, "arrowParens": "avoid", "trailingComma": "es5" } ================================================ FILE: packages/knip/fixtures/fix/access.js ================================================ module.exports.USED = 1; module.exports.UNUSED = 1; module.exports['ACCESS'] = 1; ================================================ FILE: packages/knip/fixtures/fix/default-x.mjs ================================================ const x = 1; export default x; export const dx = 1; ================================================ FILE: packages/knip/fixtures/fix/default.mjs ================================================ export default 1; export const d = 1; ================================================ FILE: packages/knip/fixtures/fix/exports.js ================================================ const identifier = 1; const identifier2 = 2; module.exports = { identifier, identifier2 }; ================================================ FILE: packages/knip/fixtures/fix/ignored.ts ================================================ export const a = 1; export const b = 2; export type T = number; ================================================ FILE: packages/knip/fixtures/fix/index.mjs ================================================ import { d } from './default.mjs'; import { dx } from './default-x.mjs'; import _ from 'lodash'; import { z, f, g, i } from './mod'; import { USED } from './access'; import { identifier } from './exports'; import { a } from './ignored'; import * as NS from './reexports.mjs'; d; dx; _; z; f; g; i; USED; identifier; a; NS.One; NS.Rectangle; NS.Nine; NS.setter; ================================================ FILE: packages/knip/fixtures/fix/knip.ts ================================================ export default { ignore: ['ignored.ts'], ignoreDependencies: ['ignored'], }; ================================================ FILE: packages/knip/fixtures/fix/mod.ts ================================================ export const x = 1; export const y = 2; export interface McInterFace {} export type McType = {}; export enum McEnum {} export const z = x + y; export const { a, b } = { a: 1, b: 1 }; export const [c, d] = [3, 4]; export const [e, f] = [5, 6]; export const [g, h, i] = [7, 8, 9]; export default class MyClass {} /** @lintignore */ export type U = number; ================================================ FILE: packages/knip/fixtures/fix/package.json ================================================ { "name": "@fixtures/fix", "dependencies": { "lodash": "*", "unused": "*", "ignored": "*" }, "devDependencies": { "unreferenced": "*" } } ================================================ FILE: packages/knip/fixtures/fix/reexported.ts ================================================ const Two = 2; const Three = 3; const Four = 4; const Five = 5; export { Two, Three }; export { Four as Fourth, Five as Fifth }; export { Four as Rectangle, Five as Pentagon }; type Six = any; type Seven = unknown; const Eight = 8; const Nine = 9; type Ten = unknown[]; export type { Six }; export { type Seven, Eight, Nine, type Ten }; export const One = 1; const fn = () => ({ get: () => 1, set: () => 1 }); export const { get: getter, set: setter } = fn(); ================================================ FILE: packages/knip/fixtures/fix/reexports.mjs ================================================ export { RangeSlider } from './reexported'; export { Rating } from './reexported'; export { One, Rectangle, Six, Seven, Eight, Nine, Ten, getter, setter } from './reexported'; export { Col, Col as KCol } from './reexported'; export { Row as KRow, Row } from './reexported'; ================================================ FILE: packages/knip/fixtures/fix-members/class.ts ================================================ export class Rectangle { constructor( public width: number, public height: number ) {} static Key = 1; public get unusedGetter(): string { return 'unusedGetter'; } private set unusedSetter(w: number) { this.width = w; } area() { return this.width * this.height; } } ================================================ FILE: packages/knip/fixtures/fix-members/enums.ts ================================================ export enum Directions { North = 1, East = 2, South = 3, West = 4, } export enum Fruits { apple = 'apple', orange = 'orange', } ================================================ FILE: packages/knip/fixtures/fix-members/index.js ================================================ import { Rectangle } from './class.js'; import { Directions, Fruits } from './enums.js'; import { Animals } from './namespaces.js'; Directions.East; Fruits.apple; Animals.cat; Animals.swim(); Animals.Birds.eagle; const rect = new Rectangle(); rect.area(); ================================================ FILE: packages/knip/fixtures/fix-members/namespaces.ts ================================================ export namespace Animals { export const cat = 'cat'; export const unusedDog = 'dog'; export function swim() {} export namespace Birds { export const eagle = 'eagle'; export const unusedParrot = 'parrot'; } } ================================================ FILE: packages/knip/fixtures/fix-members/package.json ================================================ { "name": "@fixtures/fix-members" } ================================================ FILE: packages/knip/fixtures/fix-workspaces/exports.ts ================================================ export const c = 1; export const d = 2; export type T = number; /** @lintignore */ export type U = number; ================================================ FILE: packages/knip/fixtures/fix-workspaces/ignored.ts ================================================ export const a = 1; export const b = 2; export type T = number; ================================================ FILE: packages/knip/fixtures/fix-workspaces/index.js ================================================ import { a } from './ignored'; import { c } from './exports'; a; c; ================================================ FILE: packages/knip/fixtures/fix-workspaces/knip.ts ================================================ export default { ignoreWorkspaces: ['packages/ignored'], workspaces: { '.': { ignore: ['ignored.ts'], ignoreDependencies: ['ignored'], }, 'packages/lib': { ignore: ['ignored.ts'], ignoreDependencies: ['ignored'], }, }, }; ================================================ FILE: packages/knip/fixtures/fix-workspaces/package.json ================================================ { "name": "@fixtures/fix-workspaces", "dependencies": { "unused": "*", "ignored": "*" }, "workspaces": [ "packages/*" ] } ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/ignored/exports.ts ================================================ export const a = 1; export const b = 2; export type T = number; ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/ignored/index.js ================================================ import { a } from './exports'; a; ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/ignored/package.json ================================================ { "name": "@fixtures/fix-workspaces__ignored", "dependencies": { "unused": "*" } } ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/lib/exports.ts ================================================ export const c = 1; export const d = 2; export type T = number; /** @lintignore */ export type U = number; ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/lib/ignored.ts ================================================ export const a = 1; export const b = 2; export type T = number; ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/lib/index.js ================================================ import { a } from './ignored'; import { c } from './exports'; a; c; ================================================ FILE: packages/knip/fixtures/fix-workspaces/packages/lib/package.json ================================================ { "name": "@fixtures/fix-workspaces__lib", "dependencies": { "unused": "*", "ignored": "*" } } ================================================ FILE: packages/knip/fixtures/git-branch-file/index.ts ================================================ export const main = true; ================================================ FILE: packages/knip/fixtures/git-branch-file/package.json ================================================ { "name": "@fixtures/git-branch-file", "knip": { "entry": "index.ts", "project": "**/*.ts" } } ================================================ FILE: packages/knip/fixtures/gitignore/.gitignore ================================================ build /b ================================================ FILE: packages/knip/fixtures/gitignore/package.json ================================================ { "name": "@fixtures/gitignore", "workspaces": [ "packages/a" ], "knip": { "workspaces": { ".": { "entry": "index.ts", "project": "**/*.{js,ts}" }, "packages/a": { "entry": "index.ts", "project": "**/*.{js,ts}" } } } } ================================================ FILE: packages/knip/fixtures/gitignore/packages/a/.gitignore ================================================ build dist.ts ================================================ FILE: packages/knip/fixtures/gitignore/packages/a/index.ts ================================================ export const a = 1; ================================================ FILE: packages/knip/fixtures/gitignore/packages/a/libs/.gitignore ================================================ *.ts ================================================ FILE: packages/knip/fixtures/gitignore/packages/a/libs/util/type/.gitignore ================================================ *.js ================================================ FILE: packages/knip/fixtures/gitignore/packages/a/package.json ================================================ { "name": "@fixtures/gitignore__a" } ================================================ FILE: packages/knip/fixtures/glob/.gitignore ================================================ a/b/c ================================================ FILE: packages/knip/fixtures/glob/a/.gitignore ================================================ ================================================ FILE: packages/knip/fixtures/glob/a/b/.gitignore ================================================ ================================================ FILE: packages/knip/fixtures/glob/a/b/c/.gitignore ================================================ ================================================ FILE: packages/knip/fixtures/glob-worktree/.gitignore ================================================ beyond-worktree-ignored ================================================ FILE: packages/knip/fixtures/glob-worktree/mock-git-dir/info/exclude ================================================ worktree-exclude-ignored ================================================ FILE: packages/knip/fixtures/glob-worktree/root/.gitignore ================================================ worktree-ignored ================================================ FILE: packages/knip/fixtures/glob-worktree/root/dot-git ================================================ gitdir: ../mock-git-dir ================================================ FILE: packages/knip/fixtures/glob-worktree/root/subdir/.gitignore ================================================ subdir-ignored ================================================ FILE: packages/knip/fixtures/ignore-dependencies-binaries/index.ts ================================================ import Picker from 'rc-picker/lib/interface'; import TreeSelect from 'rc-tree-select/lib/interface'; import Select from 'rc-select/lib/interface'; import P1 from '@org/pkg1'; import P2 from '@org/pkg2'; ================================================ FILE: packages/knip/fixtures/ignore-dependencies-binaries/knip.ts ================================================ export default { ignoreBinaries: ['eslint', /^ts.+/, /.*unused-bins.*/, 'executable!'], ignoreDependencies: ['stream', /^@org\/.*/, /^rc-.*/, /.+unused-deps.+/, 'package!'], }; ================================================ FILE: packages/knip/fixtures/ignore-dependencies-binaries/package.json ================================================ { "name": "@fixtures/ignore-dependencies-binaries", "type": "module", "scripts": { "build": "tsc", "c": "tsx index.ts", "d": "ts-node index.ts", "e": "eslint", "f": "formatter", "g": "executable", "h": "package" }, "devDependencies": { "tsx": "*" } } ================================================ FILE: packages/knip/fixtures/ignore-dependencies-binaries-json/index.ts ================================================ import Picker from 'rc-picker/lib/interface'; import TreeSelect from 'rc-tree-select/lib/interface'; import Select from 'rc-select/lib/interface'; import P1 from '@org/pkg1'; import P2 from '@org/pkg2'; ================================================ FILE: packages/knip/fixtures/ignore-dependencies-binaries-json/package.json ================================================ { "name": "@fixtures/ignore-dependencies-binaries-json", "type": "module", "scripts": { "build": "tsc", "c": "tsx index.ts", "d": "ts-node index.ts", "e": "eslint", "f": "formatter" }, "devDependencies": { "tsx": "*" }, "knip": { "ignoreBinaries": [ "eslint", "^ts.+", ".*unused-bins.*" ], "ignoreDependencies": [ "stream", "^@org/.*", "^rc-.*", ".+unused-deps.+" ] } } ================================================ FILE: packages/knip/fixtures/ignore-dependencies-eslint/.eslintrc.js ================================================ const path = require('node:path'); module.exports = { extends: ['@local/eslint-config'], plugins: ['import', 'prettier'], root: true, settings: { 'import/resolver': { typescript: { project: path.resolve(__dirname, 'tsconfig.json'), }, }, }, }; ================================================ FILE: packages/knip/fixtures/ignore-dependencies-eslint/knip.json ================================================ { "eslint": true, "ignoreDependencies": ["^eslint-.*"] } ================================================ FILE: packages/knip/fixtures/ignore-dependencies-eslint/package.json ================================================ { "name": "@fixtures/ignore-dependencies-eslint", "devDependencies": { "@local/eslint-config": "*" } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/computed-access.ts ================================================ export const QUERY_KEY = 'live'; const query: Record = {}; const value = query[QUERY_KEY]; query[QUERY_KEY] = 'updated'; delete query[QUERY_KEY]; value; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/control-flow.ts ================================================ export const WARRIOR = 'warrior'; export const MAGE = 'mage'; function selectClass(role: string) { switch (role) { case WARRIOR: return 1; case MAGE: return 2; } } export const BASE_DAMAGE = 10; function computeDamage(multiplier = BASE_DAMAGE) { return multiplier; } selectClass('warrior'); computeDamage(); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/expressions.ts ================================================ export const quest = Promise.resolve('dragon'); async function embark() { const result = await quest; return result; } export const loot = () => 'gold'; const reward = () => loot; embark(); reward(); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/imported.ts ================================================ export interface ReferencedNeverInterface { hello: boolean; } export interface ReferencedInterfaceInternally { message: string; repeat?: number; } export function referencedInternallyFunction(value: unknown) { // } export function usedFunction(options: ReferencedInterfaceInternally) { referencedInternallyFunction(options); } export function referencedNeverFunction() { // } function declaredThenExportedDefault() {} export default declaredThenExportedDefault; function DeclaredThenExportedNamed() {} export { DeclaredThenExportedNamed }; export const scout = () => {}; export const ranger = () => {}; export class Paladin { static ally = scout; } (0, ranger)(); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/index.ts ================================================ import { usedFunction } from './imported'; import './loops'; import './control-flow'; import './expressions'; import './jsx'; import './tagged-template'; import './type-assertions'; import './more'; import './computed-access'; usedFunction({ message: 'Hello, world!' }); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/jsx.tsx ================================================ export const Shield = () =>
shield
; export const durability = 100; export const enchantments = { fire: true }; const ArmorSet = () => (
); ArmorSet; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/knip.json ================================================ { "ignoreExportsUsedInFile": true } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/loops.ts ================================================ export const inventory = ['axe', 'bow', 'crossbow']; for (const weapon of inventory) { weapon; } export const armory = { sword: 1, shield: 2 }; for (const slot in armory) { slot; } export let patrol = true; while (patrol) { patrol = false; } export let guard = true; do { guard = false; } while (guard); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/more.ts ================================================ export const sentinel = 10; for (let i = 0; i < sentinel; i++) {} export const ore = {}; const refined = ore; refined; export const gem = 42; const polished = (gem); polished; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/tagged-template.ts ================================================ export function enchant(strings: TemplateStringsArray, ...values: unknown[]) { return strings.join(''); } const spell = enchant`fire`; spell; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/tsconfig.json ================================================ { "compilerOptions": { "jsx": "react-jsx" }, "include": ["*.ts", "*.tsx"] } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file/type-assertions.ts ================================================ export const blade = { damage: 50 }; export const hilt = { grip: 'leather' }; const forged = blade as unknown; const reinforced = hilt!; forged; reinforced; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-alias-exclude/exports.ts ================================================ const ash = 'ash'; const balau = 'balau'; balau; export { ash, balau }; export const cedar = 'cedar'; cedar; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-alias-exclude/index.ts ================================================ import './exports'; import './more'; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-alias-exclude/more.ts ================================================ const kauri = 'kauri'; const larch = 'larch'; export { kauri, larch }; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-alias-exclude/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-alias-exclude", "knip": { "ignoreExportsUsedInFile": true } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-false/imported.ts ================================================ interface ReferencedInterfaceInternally { message: string; } function referencedInternallyFunction(value: unknown) { // } export function usedFunction(options: ReferencedInterfaceInternally) { referencedInternallyFunction(options); } function declaredThenExportedDefault() {} export default declaredThenExportedDefault; function DeclaredThenExportedNamed() {} export { DeclaredThenExportedNamed }; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-false/index.ts ================================================ import { usedFunction } from './imported'; usedFunction({ message: 'test' }); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-false/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-false" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-chars/imported.ts ================================================ export const unusedFunction = () => 1; export const unusedFunction2 = () => 1; unusedFunction2(); export const unusedVar = 1; export const _unusedVar = 1; _unusedVar; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-chars/index.ts ================================================ import './imported'; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-chars/knip.json ================================================ { "ignoreExportsUsedInFile": true } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-chars/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-id-chars" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/imported.ts ================================================ export const __underscoresUnused = 'underscoresUnused'; export const __underscoresUsed = 'underscoresUsed'; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/index.ts ================================================ import { __underscoresUsed } from './imported'; import * as NS from './namespace'; __underscoresUsed; NS.__underscoresUsed; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/knip.json ================================================ { "ignoreExportsUsedInFile": true } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/namespace.ts ================================================ export const __underscoresUnused = 'underscoresUnused'; export const __underscoresUsed = 'underscoresUsed'; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-id-underscores" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-id-underscores/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-re-export/component.ts ================================================ import type { ComponentProps } from './interface'; export type { ComponentProps }; export default function Wrapper(props: ComponentProps) { return props; } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-re-export/index.ts ================================================ import Component from './component'; Component; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-re-export/interface.ts ================================================ export interface ComponentProps { n: number; } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-re-export/knip.json ================================================ { "ignoreExportsUsedInFile": true } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-re-export/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-re-export" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/knip.json ================================================ { "ignoreExportsUsedInFile": true } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-shorthand" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/src/antecedents.js ================================================ export const variableA = 1; export const variableB = 1; export const variableC = 1; const x = { variableC, depth: { variableB, }, variableA, }; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/src/fn.js ================================================ export function fn() {} const obj = { fn }; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/src/index.js ================================================ import './antecedents'; import './fn'; import { slice } from './slice'; slice; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-shorthand/src/slice.js ================================================ export const initialState = { value: 0 }; export const shorthandInitialState = { value: 0 }; export const slice = { name: 'counter', initialState: initialState, shorthandInitialState, }; ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-some/imported.ts ================================================ export interface ReferencedNeverInterface { hello: boolean; } export interface ReferencedInterfaceInternally { message: string; repeat?: number; } export function referencedInternallyFunction(value: unknown) { // } export function usedFunction(options: ReferencedInterfaceInternally) { referencedInternallyFunction(options); } export function referencedNeverFunction() { // } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-some/index.ts ================================================ import { usedFunction } from './imported'; usedFunction({ message: 'Hello, world!' }); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-some/knip.json ================================================ { "ignoreExportsUsedInFile": { "interface": true, "type": true } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-some/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-some" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-some/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"] } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-typeof-class/knip.json ================================================ { "ignoreExportsUsedInFile": { "enum": true, "interface": true, "type": true } } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-typeof-class/package.json ================================================ { "name": "@fixtures/ignore-exports-used-in-file-typeof-class" } ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-typeof-class/src/api.ts ================================================ export function logger(): void {} export function setLogger(fn: typeof logger): void { void fn; } export class TreeNode { children: TreeNode[] = []; } export class TreeLeaf { value = ''; } export function createTree(): TreeNode { const node = new TreeNode(); node.children.push(new TreeLeaf() as unknown as TreeNode); return node; } export class Leaf { text = ''; } export interface Collection { isLeaf(): this is Leaf; } export class Node { value = 0; } export interface Walker { visit(n: Node): void; } function internal(w: Walker) { w.visit(new Node()); } internal({ visit: () => {} }); ================================================ FILE: packages/knip/fixtures/ignore-exports-used-in-file-typeof-class/src/index.ts ================================================ import { setLogger, createTree, type Collection } from './api'; setLogger(() => {}); createTree(); const c: Collection = { isLeaf: () => false }; c.isLeaf(); ================================================ FILE: packages/knip/fixtures/ignore-files/apples/index.js ================================================ import './used.js'; ================================================ FILE: packages/knip/fixtures/ignore-files/apples/package.json ================================================ { "name": "@fixtures/ignore-files__apples" } ================================================ FILE: packages/knip/fixtures/ignore-files/apples/rooted.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/apples/unused.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/apples/used.js ================================================ export const unused = 1; ================================================ FILE: packages/knip/fixtures/ignore-files/bananas/index.js ================================================ import './used.js'; ================================================ FILE: packages/knip/fixtures/ignore-files/bananas/package.json ================================================ { "name": "@fixtures/ignore-files__bananas" } ================================================ FILE: packages/knip/fixtures/ignore-files/bananas/rooted.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/bananas/unused.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/bananas/used.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/index.js ================================================ import './used.js'; ================================================ FILE: packages/knip/fixtures/ignore-files/knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "ignoreFiles": ["bananas/**", "rooted.js"], "workspaces": { "apples": { "ignoreFiles": ["**/unused.js", "used.js"] }, "bananas": { "ignoreFiles": [] } } } ================================================ FILE: packages/knip/fixtures/ignore-files/package.json ================================================ { "name": "@fixtures/ignore-files", "workspaces": [ "apples" ] } ================================================ FILE: packages/knip/fixtures/ignore-files/rooted.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/unused.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-files/used.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-issues/knip.json ================================================ { "$schema": "../../schema.json", "includeEntryExports": true, "ignoreIssues": { "src/generated/**": ["exports", "types"], "**/*.generated.ts": ["exports"] } } ================================================ FILE: packages/knip/fixtures/ignore-issues/package.json ================================================ { "name": "@fixtures/ignore-issues" } ================================================ FILE: packages/knip/fixtures/ignore-issues/src/generated/types.ts ================================================ // This file is generated, unused exports should be ignored export const unusedGenerated = 'unused'; export type UnusedType = string; // But dependencies should still be reported import { nonExistent } from 'nonexistent-package'; ================================================ FILE: packages/knip/fixtures/ignore-issues/src/index.ts ================================================ export const used = 'used'; // Import files to ensure they're analyzed import './generated/types.js'; import './model.generated.js'; import './regular.js'; ================================================ FILE: packages/knip/fixtures/ignore-issues/src/model.generated.ts ================================================ // This file is generated, unused exports and class members should be ignored export class GeneratedModel { unusedMethod() { return 'unused'; } anotherUnusedMethod() { return 'also unused'; } } export const unusedExport = 'unused'; ================================================ FILE: packages/knip/fixtures/ignore-issues/src/regular.ts ================================================ // This is a regular file, unused exports SHOULD be reported export const unusedRegular = 'unused'; export class RegularClass { unusedMethod() { return 'unused'; } } ================================================ FILE: packages/knip/fixtures/ignore-members/MyClass.ts ================================================ class BaseClass { constructor() {} init() {} used() {} unused() {} } export class MyClass extends BaseClass { constructor() { super(); } ignored() {} init() { super.init(); } implemented() { this.used(); } } ================================================ FILE: packages/knip/fixtures/ignore-members/enums.ts ================================================ export enum Direction { Up = 1, Down, Left, Right, } ================================================ FILE: packages/knip/fixtures/ignore-members/index.ts ================================================ import { MyClass } from './MyClass'; import { Direction } from './enums'; MyClass.init(); Direction.Up; ================================================ FILE: packages/knip/fixtures/ignore-members/knip.ts ================================================ export default { ignoreMembers: ['ignored', /Left|Right/], }; ================================================ FILE: packages/knip/fixtures/ignore-members/package.json ================================================ { "name": "@fixtures/ignore-members" } ================================================ FILE: packages/knip/fixtures/ignore-members/tsconfig.json ================================================ { "compilerOptions": { "jsx": "preserve" } } ================================================ FILE: packages/knip/fixtures/ignore-negated/index.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-negated/knip.json ================================================ { "entry": ["index.js"], "project": ["**/*.js"], "ignore": ["!src/modules/B/**/*.js"] } ================================================ FILE: packages/knip/fixtures/ignore-negated/package.json ================================================ { "name": "@fixtures/ignore-negated" } ================================================ FILE: packages/knip/fixtures/ignore-negated/src/modules/A/unusedFileA.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-negated/src/modules/B/unusedFileB.js ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns/.gitignore ================================================ dist ================================================ FILE: packages/knip/fixtures/ignore-patterns/index.ts ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns/knip.json ================================================ { "ignore": ["dist/**", "generated/**", "scripts/**"], "ignoreFiles": ["temp/**"] } ================================================ FILE: packages/knip/fixtures/ignore-patterns/package.json ================================================ { "name": "@fixtures/ignore-patterns" } ================================================ FILE: packages/knip/fixtures/ignore-patterns/scripts/build.ts ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/index.ts ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/knip.json ================================================ { "ignore": ["build/**"], "workspaces": { "packages/lib": { "ignore": ["output/**", "cache/**"] } } } ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/package.json ================================================ { "name": "@fixtures/ignore-patterns-monorepo", "workspaces": [ "packages/*" ] } ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/packages/lib/index.ts ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/packages/lib/output/generated.ts ================================================ ================================================ FILE: packages/knip/fixtures/ignore-patterns-monorepo/packages/lib/package.json ================================================ { "name": "@fixtures/ignore-patterns-monorepo__lib" } ================================================ FILE: packages/knip/fixtures/ignore-unresolved/index.ts ================================================ import 'missing-module'; import '#/ignored-unresolved-module'; import './ignored-by-regex'; ================================================ FILE: packages/knip/fixtures/ignore-unresolved/knip.ts ================================================ export default { ignoreUnresolved: ['#/ignored-unresolved-module', /ignored.*regex/, 'unused-ignore'], }; ================================================ FILE: packages/knip/fixtures/ignore-unresolved/package.json ================================================ { "name": "@fixtures/ignore-unresolved", "type": "module" } ================================================ FILE: packages/knip/fixtures/ignore-unresolved2/knip.json ================================================ { "$schema": "https://unpkg.com/knip@6/schema.json", "ignoreUnresolved": [ "./unresolved-top-level", "unused-top-level", "./unresolved-workspace" ], "workspaces": { ".": { "ignoreUnresolved": [".+unresolved-root", "unused-root"] }, "packages/client": { "ignoreUnresolved": [".*unresolved-workspace", "unused-workspace"] } } } ================================================ FILE: packages/knip/fixtures/ignore-unresolved2/package.json ================================================ { "name": "@fixtures/ignore-unresolved2", "workspaces": [ "packages/*" ] } ================================================ FILE: packages/knip/fixtures/ignore-unresolved2/packages/client/package.json ================================================ { "name": "@fixtures/ignore-unresolved2__client" } ================================================ FILE: packages/knip/fixtures/ignore-unresolved2/packages/client/src/index.ts ================================================ import './unresolved-top-level'; import './unresolved-root'; import './unresolved-workspace'; ================================================ FILE: packages/knip/fixtures/import-equals/index.ts ================================================ import * as NS from './my-module.js'; import local = require('./local.js'); import external = require('external'); import something = NS.something; local; external; something; ================================================ FILE: packages/knip/fixtures/import-equals/local.ts ================================================ export default () => 1; ================================================ FILE: packages/knip/fixtures/import-equals/my-module.ts ================================================ export const something = {}; ================================================ FILE: packages/knip/fixtures/import-equals/package.json ================================================ { "name": "@fixtures/import-equals", "dependencies": { "external": "*" } } ================================================ FILE: packages/knip/fixtures/import-equals/tsconfig.json ================================================ {} ================================================ FILE: packages/knip/fixtures/import-errors/index.ts ================================================ import 'package'; ================================================ FILE: packages/knip/fixtures/import-errors/package.json ================================================ { "name": "@fixtures/import-errors", "devDependencies": { "package": "*" } } ================================================ FILE: packages/knip/fixtures/import-meta-glob/animals/cat.ts ================================================ ================================================ FILE: packages/knip/fixtures/import-meta-glob/animals/dog.ts ================================================ import 'vite'; ================================================ FILE: packages/knip/fixtures/import-meta-glob/animals/horse.ts ================================================ import 'vite'; ================================================ FILE: packages/knip/fixtures/import-meta-glob/flowers/rose.astro ================================================ --- import 'astro'; --- ================================================ FILE: packages/knip/fixtures/import-meta-glob/flowers/tulip.astro ================================================ --- import 'astro'; --- ================================================ FILE: packages/knip/fixtures/import-meta-glob/index.ts ================================================ import.meta.glob('./shapes/*.vue'); import.meta.glob(['./animals/*.ts', '!./animals/cat.ts', './flowers/**/*.astro']); ================================================ FILE: packages/knip/fixtures/import-meta-glob/package.json ================================================ { "name": "@fixtures/import-meta-glob", "devDependencies": { "astro": "*", "vite": "*", "vue": "*" } } ================================================ FILE: packages/knip/fixtures/import-meta-glob/shapes/circle.vue ================================================ ================================================ FILE: packages/knip/fixtures/import-meta-glob/shapes/square.vue ================================================ ================================================ FILE: packages/knip/fixtures/import-named-default-id/index.ts ================================================ import utilOne from './utils'; utilOne(); ================================================ FILE: packages/knip/fixtures/import-named-default-id/package.json ================================================ { "name": "@fixtures/import-named-default-id" } ================================================ FILE: packages/knip/fixtures/import-named-default-id/utils.ts ================================================ export const utilOne = () => 1; const utilTwo = () => 2; export default utilTwo; ================================================ FILE: packages/knip/fixtures/import-star-iteration/fruit.ts ================================================ export class Orange { public message = 'I am an orange'; } export class Apple { public message = 'I am an apple'; } ================================================ FILE: packages/knip/fixtures/import-star-iteration/index.ts ================================================ import * as fruitClasses from './fruit'; import * as veggieClasses from './vegetables'; // Outputs: // I am an orange // I am an apple // I am broccoli // I am spinach for (const className in fruitClasses) { const classInstance = new fruitClasses[className](); classInstance.message; } for (const myClass of veggieClasses) { const classInstance = new myClass(); classInstance.message; } ================================================ FILE: packages/knip/fixtures/import-star-iteration/package.json ================================================ { "name": "@fixtures/import-star-iteration" } ================================================ FILE: packages/knip/fixtures/import-star-iteration/tsconfig.json ================================================ { "compilerOptions": {} } ================================================ FILE: packages/knip/fixtures/import-star-iteration/vegetables.ts ================================================ class Broccoli { public message = 'I am broccoli'; } class Spinach { public message = 'I am spinach'; } // This is contrived, but this leads to us being able to use for (...of) in index.ts const veggieClasses = [Broccoli, Spinach]; export = veggieClasses; // Makes the file a module ================================================ FILE: packages/knip/fixtures/imports/aliased-binding.ts ================================================ export const named = 'named'; ================================================ FILE: packages/knip/fixtures/imports/await-import-call.ts ================================================ import console = require('node:console'); console.log('side effect'); ================================================ FILE: packages/knip/fixtures/imports/await-import.ts ================================================ export default () => {}; ================================================ FILE: packages/knip/fixtures/imports/catch.ts ================================================ export const identifier15 = 0; ================================================ FILE: packages/knip/fixtures/imports/default-and-named-binding.ts ================================================ export const named = 'named'; export default 'default'; ================================================ FILE: packages/knip/fixtures/imports/default-identifier.ts ================================================ export default 'default'; ================================================ FILE: packages/knip/fixtures/imports/default-prop-access.ts ================================================ export default 'default-prop-access'; export const elementAccess = 1; ================================================ FILE: packages/knip/fixtures/imports/dir/import-b.ts ================================================ export default 1; export const dynamic = () => 1; export const named = { default: 1, identifier13: 13, identifier14: 14 }; ================================================ FILE: packages/knip/fixtures/imports/dir/import-f.ts ================================================ export const dynamic = () => 1; export const named = { default: 1, identifier13: 13, identifier14: 14 }; ================================================ FILE: packages/knip/fixtures/imports/dir/mod.ts ================================================ export default 1; ================================================ FILE: packages/knip/fixtures/imports/empty-named-bindings.ts ================================================ // side-effects ================================================ FILE: packages/knip/fixtures/imports/import-a.ts ================================================ export default 'identifierA'; ================================================ FILE: packages/knip/fixtures/imports/import-c.ts ================================================ export default 'c'; export const namedC = 'namedC'; ================================================ FILE: packages/knip/fixtures/imports/import-d.ts ================================================ export default 'd'; ================================================ FILE: packages/knip/fixtures/imports/import-e.ts ================================================ export default 'e'; ================================================ FILE: packages/knip/fixtures/imports/import-g.ts ================================================ export function func() {} ================================================ FILE: packages/knip/fixtures/imports/import-meta-resolve.js ================================================ ================================================ FILE: packages/knip/fixtures/imports/index.ts ================================================ import './side-effects'; import { named as renamed } from './aliased-binding.js'; import defaultName1, { named as renamed2 } from './default-and-named-binding.js'; import defaultName2 from './default-identifier.js'; import { named as renamed3 } from './named-object-binding.js'; import type {} from './empty-named-bindings.js'; const fn = (_: any) => {}; const topLevel = await import('./top-level-await-import.js'); const { top } = await import('./top-level-await-import.js'); const dynamicB = () => import('./dir/import-b.js').then(m => m.dynamic); const dynamicF = () => import('./dir/import-f.js').then(({ dynamic, named: renamed }) => [dynamic, renamed]); const dynamicG = import('./import-g.js'); dynamicG.then(module => module.func()); import('./top-level-side-effects-call.js'); async function main() { import('./side-effects-call.js'); await import('./await-import-call.js'); const { default: defaultName, identifier11: renamedIdentifier, identifier12 } = await import('./object-bindings.js'); [defaultName, renamedIdentifier, identifier12]; } const dynamicImport = (value: string) => { return import(`./dir/${value}`); }; const templateStringExternal = () => { return import('./no-substitution-tpl-literal.js'); }; const templateStringLiteral = () => { return import('./string-literal.js'); }; const templateStringInternal = () => { return import('./dir/mod.js'); }; const importMetaResolve = () => { return import.meta.resolve('./import-meta-resolve.js'); }; function promiseAll() { return { async fn() { const [identifierA, { default: identifierB }] = await Promise.all([ import('./import-a.js'), import('./dir/import-b.js'), import('./dir/import-b.js'), ]); [identifierA, identifierB]; }, }; } function promiseTail() { return { async fn() { const [, , identifierB] = await Promise.all([ import('./dir/import-b.js'), import('./dir/import-b.js'), import('./dir/import-b.js'), ]); [identifierB]; }, }; } (await import('./prop-access.js')).propAccess; const { default: defaultName3, identifier13: renamedIdentifier, identifier14, } = (await import('./dir/import-b.js'))['named']; const defaultName4 = (await import('./default-prop-access.js')).default; (await import('./default-prop-access.js'))['elementAccess']; import('./promise-like').then(f => f).catch(err => err); const [defaultName5, { default: renamedIdentifier2, namedC }] = await Promise.all([ import('./import-a.js'), import('./import-c.js'), ]); const child1 = fn(() => import('./import-c.js')); const { identifier15 } = await import('./catch.js').catch(() => { throw new Error('caught'); }); const importPromise = import('./await-import.js'); const { default: awaitedImport } = await importPromise; awaitedImport(); export default fn({ components: { child1, child2: () => import('./import-d.js'), child3: import('./import-e.js'), }, }); [ topLevel, top, dynamicB, dynamicF, defaultName1, defaultName2, defaultName3, defaultName4, elementAccess, defaultName5, renamed, renamed2, renamed3, renamedIdentifier, renamedIdentifier2, namedC, identifier14, identifier15, ]; ================================================ FILE: packages/knip/fixtures/imports/named-object-binding.ts ================================================ export const named = 'named'; ================================================ FILE: packages/knip/fixtures/imports/no-substitution-tpl-literal.ts ================================================ export default 'no-substitution-tpl-literal'; ================================================ FILE: packages/knip/fixtures/imports/object-bindings.ts ================================================ export default 'default'; export const identifier11 = 'identifier11'; export const identifier12 = 'identifier12'; ================================================ FILE: packages/knip/fixtures/imports/package.json ================================================ { "name": "@fixtures/imports", "type": "module" } ================================================ FILE: packages/knip/fixtures/imports/promise-like.ts ================================================ export default 'f'; ================================================ FILE: packages/knip/fixtures/imports/prop-access.ts ================================================ export const propAccess = 'prop-access'; ================================================ FILE: packages/knip/fixtures/imports/side-effects-call.ts ================================================ import console = require('node:console'); console.log('side effect'); ================================================ FILE: packages/knip/fixtures/imports/side-effects.ts ================================================ // side effect ================================================ FILE: packages/knip/fixtures/imports/string-literal.ts ================================================ export default 'string-literal'; ================================================ FILE: packages/knip/fixtures/imports/top-level-await-import.ts ================================================ export default 'top-level'; export const top = 'top'; ================================================ FILE: packages/knip/fixtures/imports/top-level-side-effects-call.ts ================================================ import console from 'node:console'; console.log('side effect'); ================================================ FILE: packages/knip/fixtures/imports/tsconfig.json ================================================ { "compilerOptions": { "types": ["node"], "esModuleInterop": true, "module": "nodenext" } } ================================================ FILE: packages/knip/fixtures/imports-destructure-spread/index.js ================================================ import * as trees from './trees'; import { cedar } from './trees'; const { oak, ...rest } = trees; oak; cedar; rest; ================================================ FILE: packages/knip/fixtures/imports-destructure-spread/package.json ================================================ { "name": "@fixtures/imports-destructure-spread" } ================================================ FILE: packages/knip/fixtures/imports-destructure-spread/trees.js ================================================ export const oak = 1; export const pine = 1; export const maple = 1; export const cedar = 1; ================================================ FILE: packages/knip/fixtures/imports-dynamic-access/fruits.ts ================================================ export default 'fruit'; export const apple = 'apple'; export const banana = 'banana'; export const cherry = 'cherry'; export const durian = 'durian'; export const elderberry = 'elderberry'; export const fig = 'fig'; export const grape = 'grape'; ================================================ FILE: packages/knip/fixtures/imports-dynamic-access/index.ts ================================================ async function fn() { const fruit = await import('./fruits.ts'); fruit.default; const { apple, banana: b } = await import('./fruits.ts'); apple; b; const module = await import('./fruits.ts'); module.cherry; { const { durian, elderberry: e } = module; durian; e; } const notModule = { fig: false, grape: false }; const { grape } = notModule; notModule.fig; grape; } await fn(); export {}; ================================================ FILE: packages/knip/fixtures/imports-dynamic-access/package.json ================================================ { "name": "@fixtures/imports-dynamic", "type": "module" } ================================================ FILE: packages/knip/fixtures/imports-namespace/index.ts ================================================ export * as ReExported from './re-exported-module'; import * as NS from './namespace'; import * as NS2 from './namespace2'; import * as NS3 from './namespace3'; import * as NS3_OPAQUE from './namespace3-opaque'; import * as NS4 from './namespace4'; import * as NS5 from './namespace5'; import * as NS5_OPAQUE from './namespace5-opaque'; import * as NS6 from './namespace6'; import * as NS6_OPAQUE from './namespace6-opaque'; import * as NS7 from './namespace7'; import * as NS8 from './namespace8'; import * as NS9 from './namespace9'; import * as NS10 from './namespace10'; import fn from 'external'; NS.identifier15; NS['identifier16']; NS.identifier17(); const { identifier18, identifier19, identifier20 } = NS2; NS2.identifier21.method(); function usage() { const hello = { NS3 }; hello.NS3.identifier31; const goodbye = { NS3_OPAQUE }; } fn(NS4); const spread = { ...NS5 }; spread.identifier35; const butter = { ...NS5_OPAQUE }; const assign = NS6; assign.identifier37; const allot = NS6_OPAQUE; fn([NS7]); fn({ NS8 }); const func = () => { const cond = fn() ? NS9 : { identifier43: 43 }; cond.identifier43; }; const props: { values?: { identifier45: number; identifier46: number } } = {}; const { values = NS10 } = props; values.identifier45; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace.ts ================================================ export const identifier15 = 1; export const identifier16 = 1; export const identifier17 = () => 1; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace10.ts ================================================ export const identifier45 = 45; export const identifier46 = 46; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace2.ts ================================================ export const identifier18 = 1; export const identifier19 = 1; export const identifier20 = () => 1; export const identifier21 = { method: () => 1 }; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace3-opaque.ts ================================================ export const identifier31 = 31; export const identifier32 = 32; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace3.ts ================================================ export const identifier31 = 31; export const identifier32 = 32; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace4.ts ================================================ export const identifier33 = 33; export const identifier34 = 34; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace5-opaque.ts ================================================ export const identifier35 = 35; export const identifier36 = 36; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace5.ts ================================================ export const identifier35 = 35; export const identifier36 = 36; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace6-opaque.ts ================================================ export const identifier37 = 37; export const identifier38 = 38; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace6.ts ================================================ export const identifier37 = 37; export const identifier38 = 38; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace7.ts ================================================ export const identifier39 = 39; export const identifier40 = 40; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace8.ts ================================================ export const identifier41 = 41; export const identifier42 = 42; ================================================ FILE: packages/knip/fixtures/imports-namespace/namespace9.ts ================================================ export const identifier43 = 43; export const identifier44 = 44; ================================================ FILE: packages/knip/fixtures/imports-namespace/package.json ================================================ { "name": "@fixtures/imports-namespace" } ================================================ FILE: packages/knip/fixtures/imports-namespace/re-exported-module.ts ================================================ const myFunction = () => void 0; export default myFunction; ================================================ FILE: packages/knip/fixtures/imports-namespace-jsx/components.tsx ================================================ export const Container = () =>
; export const Header = () =>

; export const Footer = () =>