From 83e18a1091daa2a63aff2b42e687ecbde2e53338 Mon Sep 17 00:00:00 2001 From: Josh Meads <8870827+joshmeads@users.noreply.github.com> Date: Sat, 29 Jun 2024 01:37:10 -0700 Subject: [PATCH] Fixes to config files + Cosmiconfig, Lilconfig and Unconfig generation. (#700) --- ...{.lockfile-lint.js => .lockfile-lintrc.js} | 0 .../xo/{xo-config.cjs => xo.config.cjs} | 0 packages/knip/package.json | 6 +- packages/knip/src/plugins/commitlint/index.ts | 10 +--- .../knip/src/plugins/graphql-codegen/index.ts | 9 ++- .../knip/src/plugins/lint-staged/index.ts | 11 ++-- packages/knip/src/plugins/linthtml/index.ts | 11 +--- .../knip/src/plugins/lockfile-lint/index.ts | 4 +- .../plugins/npm-package-json-lint/index.ts | 4 +- packages/knip/src/plugins/postcss/index.ts | 11 +++- packages/knip/src/plugins/prettier/index.ts | 5 +- packages/knip/src/plugins/release-it/index.ts | 4 +- .../src/plugins/semantic-release/index.ts | 4 +- packages/knip/src/plugins/size-limit/index.ts | 9 ++- packages/knip/src/plugins/stylelint/index.ts | 4 +- packages/knip/src/plugins/syncpack/index.ts | 7 ++- packages/knip/src/plugins/tailwind/index.ts | 1 + packages/knip/src/plugins/tsup/index.ts | 3 +- packages/knip/src/plugins/typedoc/index.ts | 9 +-- packages/knip/src/plugins/unocss/index.ts | 5 +- packages/knip/src/plugins/xo/index.ts | 6 +- packages/knip/src/util/plugin.ts | 58 ++++++++++++++++++- packages/knip/test/plugins/xo.test.ts | 2 +- 23 files changed, 124 insertions(+), 59 deletions(-) rename packages/knip/fixtures/plugins/lockfile-lint/{.lockfile-lint.js => .lockfile-lintrc.js} (100%) rename packages/knip/fixtures/plugins/xo/{xo-config.cjs => xo.config.cjs} (100%) diff --git a/packages/knip/fixtures/plugins/lockfile-lint/.lockfile-lint.js b/packages/knip/fixtures/plugins/lockfile-lint/.lockfile-lintrc.js similarity index 100% rename from packages/knip/fixtures/plugins/lockfile-lint/.lockfile-lint.js rename to packages/knip/fixtures/plugins/lockfile-lint/.lockfile-lintrc.js diff --git a/packages/knip/fixtures/plugins/xo/xo-config.cjs b/packages/knip/fixtures/plugins/xo/xo.config.cjs similarity index 100% rename from packages/knip/fixtures/plugins/xo/xo-config.cjs rename to packages/knip/fixtures/plugins/xo/xo.config.cjs diff --git a/packages/knip/package.json b/packages/knip/package.json index 2534f6d6b..ad6c83b96 100644 --- a/packages/knip/package.json +++ b/packages/knip/package.json @@ -54,11 +54,7 @@ "create-plugin": "bun ./scripts/create-new-plugin.ts", "postcreate-plugin": "biome format --write schema.json schema-jsonc.json src/ConfigurationValidator.ts" }, - "files": [ - "dist", - "schema.json", - "schema-jsonc.json" - ], + "files": ["dist", "schema.json", "schema-jsonc.json"], "dependencies": { "@ericcornelissen/bash-parser": "0.5.3", "@nodelib/fs.walk": "2.0.0", diff --git a/packages/knip/src/plugins/commitlint/index.ts b/packages/knip/src/plugins/commitlint/index.ts index 124a217b9..1a0ef6c44 100644 --- a/packages/knip/src/plugins/commitlint/index.ts +++ b/packages/knip/src/plugins/commitlint/index.ts @@ -1,9 +1,10 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; import type { CommitLintConfig } from './types.js'; // https://commitlint.js.org // https://github.com/conventional-changelog/commitlint#config +// https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/load/src/utils/load-config.ts const title = 'commitlint'; @@ -11,12 +12,7 @@ const enablers = ['@commitlint/cli']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = [ - '.commitlintrc', - '.commitlintrc.{json,yaml,yml,js,cjs,ts,cts}', - 'commitlint.config.{js,cjs,ts,cts}', - 'package.json', -]; +const config = ['package.json', 'package.yaml', ...toCosmiconfig('commitlint', { additionalExtensions: ['cts'] })]; const resolveConfig: ResolveConfig = async config => { const extendsConfigs = config.extends diff --git a/packages/knip/src/plugins/graphql-codegen/index.ts b/packages/knip/src/plugins/graphql-codegen/index.ts index 2d7dff08d..502dec661 100644 --- a/packages/knip/src/plugins/graphql-codegen/index.ts +++ b/packages/knip/src/plugins/graphql-codegen/index.ts @@ -3,7 +3,6 @@ import { get } from '#p/util/object.js'; import { isInternal } from '#p/util/path.js'; import { hasDependency } from '#p/util/plugin.js'; import { toEntryPattern } from '#p/util/protocols.js'; -import { isConfigurationOutput, isGraphqlConfigTypes, isGraphqlProjectsConfigTypes } from './types.js'; import type { ConfiguredPlugin, GraphqlCodegenTypes, @@ -11,9 +10,14 @@ import type { GraphqlProjectsConfigTypes, PresetNames, } from './types.js'; +import { isConfigurationOutput, isGraphqlConfigTypes, isGraphqlProjectsConfigTypes } from './types.js'; +// Both use Cosmiconfig with custom searchPlaces - not using helper as a result +// Codegen: // https://the-guild.dev/graphql/codegen/docs/config-reference/codegen-config // https://github.com/dotansimha/graphql-code-generator/blob/master/packages/graphql-codegen-cli/src/config.ts +// Config: +// https://the-guild.dev/graphql/config/docs/user/usage#config-search-places const title = 'GraphQL Codegen'; @@ -26,11 +30,10 @@ const packageJsonPath: Plugin['packageJsonPath'] = manifest => get(manifest, 'co const config = [ 'package.json', // graphql-codegen config files - 'codegen.{json,yml,yaml,js,ts,mjs,cts}', + 'codegen.{json,yml,yaml,js,ts}', '.codegenrc.{json,yml,yaml,js,ts}', 'codegen.config.js', // graphql-config config files - // https://the-guild.dev/graphql/config/docs/user/usage#config-search-places '.graphqlrc', '.graphqlrc.{json,yml,yaml,toml,js,ts}', 'graphql.config.{json,yml,yaml,toml,js,cjs,ts}', diff --git a/packages/knip/src/plugins/lint-staged/index.ts b/packages/knip/src/plugins/lint-staged/index.ts index 3e9403187..443fa30b7 100644 --- a/packages/knip/src/plugins/lint-staged/index.ts +++ b/packages/knip/src/plugins/lint-staged/index.ts @@ -1,5 +1,5 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; -import { getDependenciesFromScripts, hasDependency } from '#p/util/plugin.js'; +import { getDependenciesFromScripts, hasDependency, toLilconfig } from '#p/util/plugin.js'; import type { LintStagedConfig } from './types.js'; // https://github.com/okonet/lint-staged @@ -13,12 +13,11 @@ const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependenc const packageJsonPath = 'lint-staged'; const config = [ - '.lintstagedrc', - '.lintstagedrc.json', - '.lintstagedrc.{yml,yaml}', - '.lintstagedrc.{js,mjs,cjs}', - 'lint-staged.config.{js,mjs,cjs}', 'package.json', + 'package.yaml', + 'package.yml', + ...toLilconfig('lint-staged'), + ...toLilconfig('lintstaged'), ]; const resolveConfig: ResolveConfig = async (config, options) => { diff --git a/packages/knip/src/plugins/linthtml/index.ts b/packages/knip/src/plugins/linthtml/index.ts index 0e324cd12..4144ba218 100644 --- a/packages/knip/src/plugins/linthtml/index.ts +++ b/packages/knip/src/plugins/linthtml/index.ts @@ -1,6 +1,6 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; import { isInternal } from '#p/util/path.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; import { toEntryPattern } from '#p/util/protocols.js'; import type { PluginConfig } from './types.js'; @@ -14,14 +14,7 @@ const enablers = ['@linthtml/linthtml']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = [ - '.linthtmlrc', - '.linthtmlrc.json', - '.linthtmlrc.yml', - '.linthtmlrc.{js,cjs}', - 'linthtml.config.js', - 'package.json', -]; +const config = ['package.json', ...toCosmiconfig('linthtml')]; const resolveConfig: ResolveConfig = config => { const extensions = [config.extends ?? []] diff --git a/packages/knip/src/plugins/lockfile-lint/index.ts b/packages/knip/src/plugins/lockfile-lint/index.ts index f90e8af6b..008429711 100644 --- a/packages/knip/src/plugins/lockfile-lint/index.ts +++ b/packages/knip/src/plugins/lockfile-lint/index.ts @@ -1,6 +1,6 @@ import type { EnablerPatterns } from '#p/types/config.js'; import type { IsPluginEnabled, Plugin } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; // https://github.com/lirantal/lockfile-lint/blob/main/packages/lockfile-lint/README.md @@ -10,7 +10,7 @@ const enablers: EnablerPatterns = ['lockfile-lint']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = ['.lockfile-lintrc', '.lockfile-lint.{js,toml}', 'lockfile-lint.config.js', 'package.json']; +const config = ['package.json', ...toCosmiconfig('lockfile-lint', { additionalExtensions: ['toml'] })]; export default { title, diff --git a/packages/knip/src/plugins/npm-package-json-lint/index.ts b/packages/knip/src/plugins/npm-package-json-lint/index.ts index 527f2b1dc..86ce74183 100644 --- a/packages/knip/src/plugins/npm-package-json-lint/index.ts +++ b/packages/knip/src/plugins/npm-package-json-lint/index.ts @@ -1,5 +1,5 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; import type { NpmPkgJsonLintConfig } from './types.js'; // https://npmpackagejsonlint.org/docs/ @@ -12,7 +12,7 @@ const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependenc const packageJsonPath = 'npmpackagejsonlint'; -const config = ['.npmpackagejsonlintrc.json', 'npmpackagejsonlint.config.js', 'package.json']; +const config = ['package.json', ...toCosmiconfig('npmpackagejsonlint')]; const resolveConfig: ResolveConfig = localConfig => { return localConfig?.extends ? [localConfig.extends] : []; diff --git a/packages/knip/src/plugins/postcss/index.ts b/packages/knip/src/plugins/postcss/index.ts index 4b36da559..1177ab73c 100644 --- a/packages/knip/src/plugins/postcss/index.ts +++ b/packages/knip/src/plugins/postcss/index.ts @@ -1,14 +1,21 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toLilconfig } from '#p/util/plugin.js'; import type { PostCSSConfig } from './types.js'; +// https://github.com/postcss/postcss-load-config/blob/main/src/index.js#L110 +// Additionally postcss.config.json is loaded by nextjs + const title = 'PostCSS'; const enablers = ['postcss', 'postcss-cli', 'next']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = ['postcss.config.{cjs,js}', 'postcss.config.json', 'package.json']; +const config = [ + 'package.json', + 'postcss.config.json', + ...toLilconfig('postcss', { configDir: false, additionalExtensions: ['ts', 'mts', 'cts', 'yaml', 'yml'] }), +]; const resolveConfig: ResolveConfig = config => { return config.plugins diff --git a/packages/knip/src/plugins/prettier/index.ts b/packages/knip/src/plugins/prettier/index.ts index 2eaea29ca..6f434398b 100644 --- a/packages/knip/src/plugins/prettier/index.ts +++ b/packages/knip/src/plugins/prettier/index.ts @@ -3,6 +3,7 @@ import { hasDependency } from '#p/util/plugin.js'; import type { PrettierConfig } from './types.js'; // https://prettier.io/docs/en/configuration.html +// https://github.com/prettier/prettier/blob/main/src/config/prettier-config/config-searcher.js const title = 'Prettier'; @@ -13,9 +14,9 @@ const isEnabled: IsPluginEnabled = ({ dependencies, config }) => const config = [ '.prettierrc', - '.prettierrc.{json,js,cjs,mjs,yml,yaml}', + '.prettierrc.{json,js,cjs,mjs,yml,yaml,toml,json5}', 'prettier.config.{js,cjs,mjs}', - 'package.json', + 'package.{json,yaml}', ]; const resolveConfig: ResolveConfig = config => { diff --git a/packages/knip/src/plugins/release-it/index.ts b/packages/knip/src/plugins/release-it/index.ts index 657373490..d8fcba644 100644 --- a/packages/knip/src/plugins/release-it/index.ts +++ b/packages/knip/src/plugins/release-it/index.ts @@ -3,6 +3,8 @@ import { getDependenciesFromScripts, hasDependency } from '#p/util/plugin.js'; import type { ReleaseItConfig } from './types.js'; // https://github.com/release-it/release-it/blob/master/docs/plugins.md#using-a-plugin +// Uses CosmiConfig but with custom searchPlaces +// https://github.com/release-it/release-it/blob/main/lib/config.js const title = 'Release It'; @@ -12,7 +14,7 @@ const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependenc const packageJsonPath = 'release-it'; -const config = ['.release-it.json', '.release-it.{js,cjs}', '.release-it.{yml,yaml}', 'package.json']; +const config = ['.release-it.{json,js,cjs,ts,yml,yaml,toml}', 'package.json']; const resolveConfig: ResolveConfig = (config, options) => { const plugins = config.plugins ? Object.keys(config.plugins) : []; diff --git a/packages/knip/src/plugins/semantic-release/index.ts b/packages/knip/src/plugins/semantic-release/index.ts index 7b4e4ef02..42039663b 100644 --- a/packages/knip/src/plugins/semantic-release/index.ts +++ b/packages/knip/src/plugins/semantic-release/index.ts @@ -1,5 +1,5 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; import type { SemanticReleaseConfig } from './types.js'; // https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration-file @@ -12,7 +12,7 @@ const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependenc const packageJsonPath = 'release'; -const config = ['.releaserc', '.releaserc.{yaml,yml,json,js,cjs}', 'release.config.{js,cjs}', 'package.json']; +const config = ['package.json', ...toCosmiconfig('release')]; const resolveConfig: ResolveConfig = config => { const plugins = (config?.plugins ?? []).map(plugin => (Array.isArray(plugin) ? plugin[0] : plugin)); diff --git a/packages/knip/src/plugins/size-limit/index.ts b/packages/knip/src/plugins/size-limit/index.ts index 7cfa0ec09..10d485ee0 100644 --- a/packages/knip/src/plugins/size-limit/index.ts +++ b/packages/knip/src/plugins/size-limit/index.ts @@ -1,8 +1,10 @@ import type { EnablerPatterns } from '#p/types/config.js'; import type { IsPluginEnabled, Plugin } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toLilconfig } from '#p/util/plugin.js'; // https://github.com/ai/size-limit +// Uses lilconfig but with custom searchPlaces +// https://github.com/ai/size-limit/blob/main/packages/size-limit/get-config.js const title = 'size-limit'; @@ -10,7 +12,10 @@ const enablers: EnablerPatterns = ['size-limit']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config: string[] = ['.size-limit.{json,js,cjs,ts}', 'package.json']; +const config = [ + 'package.json', + ...toLilconfig('size-limit', { configDir: false, additionalExtensions: ['ts', 'mts', 'cts'], rcSuffix: '' }), +]; export default { title, diff --git a/packages/knip/src/plugins/stylelint/index.ts b/packages/knip/src/plugins/stylelint/index.ts index 9e506ad5f..794611228 100644 --- a/packages/knip/src/plugins/stylelint/index.ts +++ b/packages/knip/src/plugins/stylelint/index.ts @@ -1,6 +1,6 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '#p/types/plugins.js'; import { isInternal } from '#p/util/path.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; import type { BaseStyleLintConfig, StyleLintConfig } from './types.js'; // https://stylelint.io/user-guide/configure/ @@ -11,7 +11,7 @@ const enablers = ['stylelint']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = ['.stylelintrc', '.stylelintrc.{cjs,js,json,yaml,yml}', 'stylelint.config.{cjs,mjs,js}']; +const config = ['package.json', ...toCosmiconfig('stylelint')]; const resolve = (config: StyleLintConfig | BaseStyleLintConfig): string[] => { const extend = config.extends ? [config.extends].flat().filter(id => !isInternal(id)) : []; diff --git a/packages/knip/src/plugins/syncpack/index.ts b/packages/knip/src/plugins/syncpack/index.ts index 0100a486b..529bca12a 100644 --- a/packages/knip/src/plugins/syncpack/index.ts +++ b/packages/knip/src/plugins/syncpack/index.ts @@ -1,6 +1,7 @@ import type { EnablerPatterns } from '#p/types/config.js'; import type { IsPluginEnabled, Plugin } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { get } from '#p/util/object.js'; +import { hasDependency, toCosmiconfig } from '#p/util/plugin.js'; // link to syncpack docs https://jamiemason.github.io/syncpack/config/syncpackrc/ @@ -10,11 +11,13 @@ const enablers: EnablerPatterns = ['syncpack']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = ['.syncpackrc', '.syncpackrc.{json,yaml,yml,js,cjs}', '.syncpack.config.{js,cjs}']; +const config = ['package.json', ...toCosmiconfig('syncpack')]; +const packageJsonPath: Plugin['packageJsonPath'] = manifest => get(manifest, 'syncpack'); export default { title, enablers, isEnabled, config, + packageJsonPath, } satisfies Plugin; diff --git a/packages/knip/src/plugins/tailwind/index.ts b/packages/knip/src/plugins/tailwind/index.ts index d5308936a..94745291d 100644 --- a/packages/knip/src/plugins/tailwind/index.ts +++ b/packages/knip/src/plugins/tailwind/index.ts @@ -2,6 +2,7 @@ import type { IsPluginEnabled, Plugin } from '#p/types/plugins.js'; import { hasDependency } from '#p/util/plugin.js'; // https://tailwindcss.com/docs/configuration +// Tailwinds lilconfig dependency is only used for postcss const title = 'Tailwind'; diff --git a/packages/knip/src/plugins/tsup/index.ts b/packages/knip/src/plugins/tsup/index.ts index c34b3a85b..d38056f70 100644 --- a/packages/knip/src/plugins/tsup/index.ts +++ b/packages/knip/src/plugins/tsup/index.ts @@ -4,6 +4,7 @@ import { toProductionEntryPattern } from '#p/util/protocols.js'; import type { TsupConfig } from './types.js'; // https://paka.dev/npm/tsup/api +// https://github.com/egoist/tsup/blob/dev/src/load.ts const title = 'tsup'; @@ -11,7 +12,7 @@ const enablers = ['tsup']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config = ['tsup.config.{js,ts,cjs,json}', 'package.json']; +const config = ['tsup.config.{js,ts,cjs,mjs,json}', 'package.json']; const resolveConfig: ResolveConfig = async config => { if (typeof config === 'function') config = await config({}); diff --git a/packages/knip/src/plugins/typedoc/index.ts b/packages/knip/src/plugins/typedoc/index.ts index 558bd8b92..7051ab7b4 100644 --- a/packages/knip/src/plugins/typedoc/index.ts +++ b/packages/knip/src/plugins/typedoc/index.ts @@ -3,6 +3,7 @@ import { hasDependency } from '#p/util/plugin.js'; import type { TypeDocConfig } from './types.js'; // https://typedoc.org/guides/overview/ +// https://github.com/TypeStrong/typedoc/blob/9f0fb048399c7a1273dc452d01cca92b34f4675b/src/lib/utils/options/readers/typedoc.ts#L168 const title = 'TypeDoc'; @@ -13,10 +14,10 @@ const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependenc const packageJsonPath = 'typedocOptions'; const config = [ - 'typedoc.{js,cjs,json,jsonc}', - 'typedoc.config.{js,cjs}', - '.config/typedoc.{js,cjs,json,jsonc}', - '.config/typedoc.config.{js,cjs}', + 'typedoc.{js,cjs,mjs,json,jsonc}', + 'typedoc.config.{js,cjs,mjs}', + '.config/typedoc.{js,cjs,mjs,json,jsonc}', + '.config/typedoc.config.{js,cjs,mjs}', 'package.json', 'tsconfig.json', ]; diff --git a/packages/knip/src/plugins/unocss/index.ts b/packages/knip/src/plugins/unocss/index.ts index 0e682f4cd..14f573d54 100644 --- a/packages/knip/src/plugins/unocss/index.ts +++ b/packages/knip/src/plugins/unocss/index.ts @@ -1,8 +1,9 @@ import type { EnablerPatterns } from '#p/types/config.js'; import type { IsPluginEnabled, Plugin } from '#p/types/plugins.js'; -import { hasDependency } from '#p/util/plugin.js'; +import { hasDependency, toUnconfig } from '#p/util/plugin.js'; // https://unocss.dev/guide/config-file +// https://github.com/unocss/unocss/blob/main/packages/config/src/index.ts const title = 'UnoCSS'; @@ -10,7 +11,7 @@ const enablers: EnablerPatterns = ['unocss']; const isEnabled: IsPluginEnabled = ({ dependencies }) => hasDependency(dependencies, enablers); -const config: string[] = ['uno.config.{js,ts,mjs,mts}', 'unocss.config.{js,ts,mjs,mts}']; +const config = [...toUnconfig('uno.config'), ...toUnconfig('unocss.config')]; export default { title, diff --git a/packages/knip/src/plugins/xo/index.ts b/packages/knip/src/plugins/xo/index.ts index 055f15a3f..f046de92d 100644 --- a/packages/knip/src/plugins/xo/index.ts +++ b/packages/knip/src/plugins/xo/index.ts @@ -5,6 +5,8 @@ import { getDependenciesDeep } from '../eslint/helpers.js'; import type { XOConfig } from './types.js'; // link to xo docs: https://github.com/xojs/xo#config +// Uses custom cosmiconfig search paths +// https://github.com/xojs/xo/blob/ee9f0a3d72d55df098fc321c4d54a1ea3804e226/lib/constants.js const title = 'xo'; @@ -14,9 +16,9 @@ const isEnabled: IsPluginEnabled = ({ dependencies, config }) => hasDependency(dependencies, enablers) || 'xo' in config; const packageJsonPath = 'xo'; -const config: string[] = ['{.,}xo-config.{js,cjs,json,}', 'package.json']; +const config = ['package.json', '.xo-config', '.xo-config.{js,cjs,json}', 'xo.config.{js,cjs}']; -const entry: string[] = ['{.,}xo-config.{js,cjs}']; +const entry: string[] = ['.xo-config.{js,cjs}', 'xo.config.{js,cjs}']; const resolveConfig: ResolveConfig = async (config, options) => { const dependencies = await getDependenciesDeep(config, options); diff --git a/packages/knip/src/util/plugin.ts b/packages/knip/src/util/plugin.ts index 4a981ff31..d865ecfb5 100644 --- a/packages/knip/src/util/plugin.ts +++ b/packages/knip/src/util/plugin.ts @@ -1,7 +1,7 @@ -export { _load as load } from './loader.js'; +export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js'; export { _loadJSON as loadJSON } from './fs.js'; +export { _load as load } from './loader.js'; export { _tryResolve as tryResolve } from './require.js'; -export { _getDependenciesFromScripts as getDependenciesFromScripts } from '../binaries/index.js'; import type { RawPluginConfiguration } from '../types/config.js'; import type { Plugin, PluginOptions } from '../types/plugins.js'; import { arrayify } from './array.js'; @@ -81,3 +81,57 @@ export const getFinalEntryPaths = (plugin: Plugin, options: PluginOptions, confi ? configEntryPaths : [...(plugin.entry ?? []).map(toEntryPattern), ...(plugin.production ?? []).map(toProductionEntryPattern)]; }; + +const toConfigMap = + ( + defaultExtensions: string[], + builderConfig: { + rcPrefix?: string; + rcSuffix?: string; + configDir?: boolean; + configFiles?: boolean; + configFilesAllExtensions?: boolean; + additionalExtensions?: string[]; + } + ) => + (moduleName: string, options?: typeof builderConfig) => { + const config = { + rcPrefix: '.', + rcSuffix: 'rc', + // Generate .config/ + configDir: true, + // Generate .config. + configFiles: true, + // Allow for .json, .yaml, .yml, .toml etc + configFilesAllExtensions: false, + additionalExtensions: [], + ...builderConfig, + ...options, + }; + const { rcPrefix, rcSuffix } = config; + const jsTypeExtensions = ['js', 'ts', 'cjs', 'mjs', 'cts', 'mts']; + const extensions = [...defaultExtensions, ...config.additionalExtensions]; + + const baseFiles = [ + `${rcPrefix}${moduleName}${rcSuffix}`, + ...(config.configDir ? [`.config/${moduleName}${rcSuffix}`] : []), + ]; + + const rcFiles = `${rcPrefix}${moduleName}${rcSuffix}.{${extensions.join(',')}}`; + const configExtensions = extensions.filter( + ext => config.configFilesAllExtensions || jsTypeExtensions.includes(ext) + ); + const configFiles = !!config.configFiles && `${moduleName}.config.{${configExtensions.join(',')}}`; + const configDirFiles = !!config.configDir && `.config/${moduleName}${rcSuffix}.{${extensions.join(',')}}`; + + return [...baseFiles, rcFiles, configFiles, configDirFiles].filter(item => item !== false); + }; + +export const toCosmiconfig = toConfigMap(['json', 'yaml', 'yml', 'js', 'ts', 'cjs', 'mjs'], { configDir: true }); +export const toLilconfig = toConfigMap(['json', 'js', 'cjs', 'mjs'], { configDir: true }); +export const toUnconfig = toConfigMap(['json', 'ts', 'mts', 'cts', 'js', 'mjs', 'cjs'], { + configDir: false, + rcPrefix: '', + rcSuffix: '', + configFiles: false, +}); diff --git a/packages/knip/test/plugins/xo.test.ts b/packages/knip/test/plugins/xo.test.ts index 7774edbea..f184bcbae 100644 --- a/packages/knip/test/plugins/xo.test.ts +++ b/packages/knip/test/plugins/xo.test.ts @@ -14,7 +14,7 @@ test('Find dependencies with the xo plugin', async () => { }); assert(issues.unlisted['.xo-config.js']['eslint-plugin-unused-imports']); - assert(issues.unlisted['xo-config.cjs']['glob']); + assert(issues.unlisted['xo.config.cjs']['glob']); assert(issues.unlisted['package.json']['eslint-plugin-eslint-comments']); assert.deepEqual(counters, {