knip 6.32.2 → 6.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +1 -1
  2. package/dist/DependencyDeputy.d.ts +1 -2
  3. package/dist/DependencyDeputy.js +1 -2
  4. package/dist/ProjectPrincipal.js +1 -0
  5. package/dist/binaries/resolvers/bun.js +1 -0
  6. package/dist/binaries/resolvers/pnpm.js +10 -0
  7. package/dist/config.d.ts +2 -0
  8. package/dist/config.js +1 -0
  9. package/dist/constants.js +1 -0
  10. package/dist/graph/analyze.js +1 -1
  11. package/dist/graph/build.js +0 -1
  12. package/dist/graph-explorer/explorer.d.ts +1 -0
  13. package/dist/graph-explorer/explorer.js +2 -0
  14. package/dist/graph-explorer/operations/is-enumerated.d.ts +2 -0
  15. package/dist/graph-explorer/operations/is-enumerated.js +33 -0
  16. package/dist/manifest/helpers.d.ts +2 -3
  17. package/dist/manifest/helpers.js +6 -42
  18. package/dist/manifest/index.d.ts +1 -2
  19. package/dist/manifest/index.js +2 -2
  20. package/dist/plugins/dotenv/index.js +1 -8
  21. package/dist/plugins/eslint/helpers.d.ts +2 -1
  22. package/dist/plugins/eslint/helpers.js +1 -0
  23. package/dist/plugins/eslint/resolveFromAST.d.ts +1 -0
  24. package/dist/plugins/eslint/resolveFromAST.js +5 -2
  25. package/dist/plugins/eslint/types.d.ts +1 -1
  26. package/dist/plugins/lefthook/index.js +10 -2
  27. package/dist/plugins/moonrepo/index.js +3 -3
  28. package/dist/plugins/nuxt/index.js +25 -3
  29. package/dist/plugins/nuxt/types.d.ts +5 -1
  30. package/dist/plugins/oxlint/index.js +6 -2
  31. package/dist/plugins/oxlint/types.d.ts +2 -0
  32. package/dist/plugins/tsup/index.js +1 -1
  33. package/dist/plugins/typescript/index.js +22 -5
  34. package/dist/plugins/vitest/index.js +31 -20
  35. package/dist/plugins/vitest/types.d.ts +2 -1
  36. package/dist/plugins/vitest/visitors/mock.d.ts +2 -0
  37. package/dist/plugins/vitest/visitors/mock.js +50 -0
  38. package/dist/plugins/webdriver-io/index.js +1 -1
  39. package/dist/plugins/webpack/index.js +15 -14
  40. package/dist/types/config.d.ts +1 -0
  41. package/dist/types/tsconfig-json.d.ts +6 -0
  42. package/dist/typescript/get-imports-and-exports.js +3 -0
  43. package/dist/typescript/visitors/calls.js +1 -1
  44. package/dist/typescript/visitors/members.js +56 -8
  45. package/dist/typescript/visitors/walk.d.ts +1 -0
  46. package/dist/typescript/visitors/walk.js +0 -1
  47. package/dist/util/glob-core.js +9 -1
  48. package/dist/util/load-config.js +6 -1
  49. package/dist/util/resolve.d.ts +1 -0
  50. package/dist/util/resolve.js +11 -0
  51. package/dist/util/scripts.d.ts +1 -0
  52. package/dist/util/scripts.js +1 -0
  53. package/dist/version.d.ts +1 -1
  54. package/dist/version.js +1 -1
  55. package/package.json +13 -9
package/README.md CHANGED
@@ -51,7 +51,7 @@ following projects:
51
51
  [3]: https://img.shields.io/npm/dm/knip?color=f56e0f
52
52
  [4]: https://github.com/webpro-nl/knip
53
53
  [5]:
54
- https://img.shields.io/github/stars/webpro-nl/knip?style=flat-square&color=f56e0f
54
+ https://img.shields.io/github/stars/webpro-nl/knip?style=flat&color=f56e0f
55
55
  [6]: https://knip.dev
56
56
  [7]: https://www.npmx.dev/package/@knip/create-config
57
57
  [8]: https://www.npmx.dev/package/@knip/language-server
@@ -22,9 +22,8 @@ export declare class DependencyDeputy {
22
22
  installedBinaries: Map<string, InstalledBinaries>;
23
23
  hasTypesIncluded: Map<string, Set<string>>;
24
24
  constructor({ isProduction, isStrict, isReportDependencies }: MainOptions);
25
- addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }: {
25
+ addWorkspace({ name, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }: {
26
26
  name: string;
27
- cwd: string;
28
27
  dir: string;
29
28
  manifestPath: string;
30
29
  manifestStr: string;
@@ -26,7 +26,7 @@ export class DependencyDeputy {
26
26
  this.installedBinaries = new Map();
27
27
  this.hasTypesIncluded = new Map();
28
28
  }
29
- addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }) {
29
+ addWorkspace({ name, dir, manifestPath, manifestStr, manifest, ignoreDependencies: id, ignoreBinaries: ib, ignoreUnresolved: iu, }) {
30
30
  const dependencies = Object.keys(manifest.dependencies ?? {});
31
31
  const peerDependencies = Object.keys(manifest.peerDependencies ?? {});
32
32
  const optionalDependencies = Object.keys(manifest.optionalDependencies ?? {});
@@ -45,7 +45,6 @@ export class DependencyDeputy {
45
45
  const { hostDependencies, installedBinaries, hasTypesIncluded } = getDependencyMetaData({
46
46
  packageNames,
47
47
  dir,
48
- cwd,
49
48
  });
50
49
  this.setHostDependencies(name, hostDependencies);
51
50
  this.installedBinaries.set(name, installedBinaries);
@@ -21,6 +21,7 @@ export class ProjectPrincipal {
21
21
  sourceText: '',
22
22
  addScript: () => { },
23
23
  addImport: () => { },
24
+ markImportExpressionHandled: () => { },
24
25
  addImportGlob: () => { },
25
26
  markExportRegistered: () => { },
26
27
  };
@@ -15,6 +15,7 @@ const commands = new Set([
15
15
  'completions',
16
16
  'config',
17
17
  'create',
18
+ 'dedupe',
18
19
  'deploy',
19
20
  'discord',
20
21
  'exec',
@@ -15,6 +15,7 @@ const commands = [
15
15
  'clean-install',
16
16
  'clean',
17
17
  'config',
18
+ 'create',
18
19
  'dedupe',
19
20
  'deploy',
20
21
  'dlx',
@@ -28,6 +29,7 @@ const commands = [
28
29
  'ic',
29
30
  'ignored-builds',
30
31
  'import',
32
+ 'info',
31
33
  'init',
32
34
  'install-clean',
33
35
  'install-test',
@@ -39,6 +41,8 @@ const commands = [
39
41
  'list',
40
42
  'll',
41
43
  'ln',
44
+ 'login',
45
+ 'logout',
42
46
  'ls',
43
47
  'outdated',
44
48
  'pack-app',
@@ -70,6 +74,7 @@ const commands = [
70
74
  'store',
71
75
  't',
72
76
  'test',
77
+ 'token',
73
78
  'tst',
74
79
  'un',
75
80
  'uninstall',
@@ -78,9 +83,11 @@ const commands = [
78
83
  'update',
79
84
  'upgrade',
80
85
  'version',
86
+ 'view',
81
87
  'why',
82
88
  'with',
83
89
  ];
90
+ const recursiveCommands = ['recursive', 'multi', 'm'];
84
91
  export const resolve = (_binary, words, options) => {
85
92
  const parsed = parseArgs(words, {
86
93
  boolean: ['aggregate-output', 'if-present', 'parallel', 'recursive', 'reverse', 'shell-mode', 'silent', 'stream'],
@@ -92,6 +99,9 @@ export const resolve = (_binary, words, options) => {
92
99
  const wordsForDlx = words.filter(word => word.value !== 'dlx');
93
100
  return resolveDlx(wordsForDlx, options);
94
101
  }
102
+ if (recursiveCommands.includes(command)) {
103
+ return resolve(_binary, argsAfter(words, command), options);
104
+ }
95
105
  const { manifest, fromArgs } = options;
96
106
  if (parsed.filter && !parsed.recursive)
97
107
  return [];
@@ -0,0 +1,2 @@
1
+ import type { KnipConfig } from './types.ts';
2
+ export declare const defineConfig: (config: KnipConfig) => KnipConfig;
package/dist/config.js ADDED
@@ -0,0 +1 @@
1
+ export const defineConfig = (config) => config;
package/dist/constants.js CHANGED
@@ -108,6 +108,7 @@ export const IGNORED_GLOBAL_BINARIES = new Set([
108
108
  'powershell.exe',
109
109
  'pr',
110
110
  'printenv',
111
+ 'printf',
111
112
  'ps',
112
113
  'pulumi',
113
114
  'pwd',
@@ -106,7 +106,7 @@ export const analyze = async ({ analyzedFiles, counselor, chief, collector, depu
106
106
  exportedItem.members.length > 0 &&
107
107
  exportedItem.type !== 'enum';
108
108
  if ((isEnumMembers || isNsMembers) && exportedItem.members.length > 0) {
109
- if (importsForExport.enumerated?.has(identifier))
109
+ if (explorer.isEnumerated(filePath, identifier))
110
110
  continue;
111
111
  if (!options.includedIssueTypes.nsTypes && importsForExport.refs.has(identifier))
112
112
  continue;
@@ -41,7 +41,6 @@ export async function build({ chief, collector, counselor, deputy, principal, is
41
41
  continue;
42
42
  deputy.addWorkspace({
43
43
  name,
44
- cwd: options.cwd,
45
44
  dir,
46
45
  manifestPath,
47
46
  manifestStr,
@@ -5,6 +5,7 @@ export declare const createGraphExplorer: (graph: ModuleGraph, entryPaths: Set<s
5
5
  treatStarAtEntryAsReferenced?: boolean;
6
6
  }) => readonly [false, string | undefined];
7
7
  hasStrictlyNsReferences: (filePath: string, identifier: string) => [boolean, (string | undefined)?];
8
+ isEnumerated: (filePath: string, identifier: string) => boolean;
8
9
  buildExportsTree: (options: {
9
10
  filePath?: string;
10
11
  identifier?: string;
@@ -6,12 +6,14 @@ import { getContention } from './operations/get-contention.js';
6
6
  import { getDependencyUsage } from './operations/get-dependency-usage.js';
7
7
  import { getUsage } from './operations/get-usage.js';
8
8
  import { hasStrictlyNsReferences } from './operations/has-strictly-ns-references.js';
9
+ import { isEnumerated } from './operations/is-enumerated.js';
9
10
  import { isReferenced } from './operations/is-referenced.js';
10
11
  import { resolveDefinition } from './operations/resolve-definition.js';
11
12
  export const createGraphExplorer = (graph, entryPaths) => {
12
13
  return {
13
14
  isReferenced: (filePath, identifier, options) => isReferenced(graph, entryPaths, filePath, identifier, options),
14
15
  hasStrictlyNsReferences: (filePath, identifier) => hasStrictlyNsReferences(graph, filePath, graph.get(filePath)?.importedBy, identifier),
16
+ isEnumerated: (filePath, identifier) => isEnumerated(graph, filePath, graph.get(filePath)?.importedBy, identifier),
15
17
  buildExportsTree: (options) => buildExportsTree(graph, entryPaths, options),
16
18
  getDependencyUsage: (pattern) => getDependencyUsage(graph, pattern),
17
19
  resolveDefinition: (filePath, identifier) => resolveDefinition(graph, filePath, identifier),
@@ -0,0 +1,2 @@
1
+ import type { ImportMaps, ModuleGraph } from '../../types/module-graph.ts';
2
+ export declare const isEnumerated: (graph: ModuleGraph, filePath: string, importsForExport: ImportMaps | undefined, identifier: string) => boolean;
@@ -0,0 +1,33 @@
1
+ import { getAliasReExportMap, getPassThroughReExportSources, getStarReExportSources } from '../visitors.js';
2
+ export const isEnumerated = (graph, filePath, importsForExport, identifier) => {
3
+ const seen = new Set();
4
+ const walkDown = (path, importMaps, id) => {
5
+ if (!importMaps || seen.has(path))
6
+ return false;
7
+ seen.add(path);
8
+ if (importMaps.enumerated?.has(id))
9
+ return true;
10
+ const follow = (sources, nextId) => {
11
+ for (const source of sources) {
12
+ if (walkDown(source, graph.get(source)?.importedBy, nextId))
13
+ return true;
14
+ }
15
+ return false;
16
+ };
17
+ const directSources = getPassThroughReExportSources(importMaps, id);
18
+ if (directSources && follow(directSources, id))
19
+ return true;
20
+ const starSources = getStarReExportSources(importMaps);
21
+ if (starSources && follow(starSources, id))
22
+ return true;
23
+ const aliasMap = getAliasReExportMap(importMaps, id);
24
+ if (aliasMap) {
25
+ for (const [alias, sources] of aliasMap) {
26
+ if (follow(sources, alias))
27
+ return true;
28
+ }
29
+ }
30
+ return false;
31
+ };
32
+ return walkDown(filePath, importsForExport, identifier);
33
+ };
@@ -1,9 +1,8 @@
1
- import type { Scripts } from '../types/package-json.ts';
1
+ import type { PackageJson, Scripts } from '../types/package-json.ts';
2
2
  type LoadPackageManifestOptions = {
3
3
  dir: string;
4
4
  packageName: string;
5
- cwd: string;
6
5
  };
7
- export declare const loadPackageManifest: ({ dir, packageName, cwd }: LoadPackageManifestOptions) => any;
6
+ export declare const loadPackageManifest: ({ dir, packageName }: LoadPackageManifestOptions) => PackageJson | undefined;
8
7
  export declare const getFilteredScripts: (scripts: Scripts) => Scripts[];
9
8
  export {};
@@ -1,49 +1,13 @@
1
- import { existsSync, readFileSync } from 'node:fs';
2
- import { dirname, join } from '../util/path.js';
1
+ import { resolvePackageManifestPath } from '../util/resolve.js';
3
2
  import { _require } from '../util/require.js';
4
- const monorepoRootCache = new Map();
5
- const findMonorepoRootAbove = (startDir) => {
6
- if (monorepoRootCache.has(startDir))
7
- return monorepoRootCache.get(startDir);
8
- let current = dirname(startDir);
9
- let result;
10
- while (current !== dirname(current)) {
11
- if (existsSync(join(current, 'pnpm-workspace.yaml'))) {
12
- result = current;
13
- break;
14
- }
15
- try {
16
- const pkg = JSON.parse(readFileSync(join(current, 'package.json'), 'utf8'));
17
- if (pkg.workspaces) {
18
- result = current;
19
- break;
20
- }
21
- }
22
- catch { }
23
- current = dirname(current);
24
- }
25
- monorepoRootCache.set(startDir, result);
26
- return result;
27
- };
28
- export const loadPackageManifest = ({ dir, packageName, cwd }) => {
3
+ export const loadPackageManifest = ({ dir, packageName }) => {
4
+ const manifestPath = resolvePackageManifestPath(packageName, dir);
5
+ if (!manifestPath)
6
+ return;
29
7
  try {
30
- return _require(join(dir, 'node_modules', packageName, 'package.json'));
8
+ return _require(manifestPath);
31
9
  }
32
10
  catch { }
33
- if (dir !== cwd) {
34
- try {
35
- return _require(join(cwd, 'node_modules', packageName, 'package.json'));
36
- }
37
- catch { }
38
- return;
39
- }
40
- const root = findMonorepoRootAbove(cwd);
41
- if (root) {
42
- try {
43
- return _require(join(root, 'node_modules', packageName, 'package.json'));
44
- }
45
- catch { }
46
- }
47
11
  };
48
12
  export const getFilteredScripts = (scripts) => {
49
13
  if (!scripts)
@@ -2,9 +2,8 @@ import type { HostDependencies, InstalledBinaries } from '../types/workspace.ts'
2
2
  type Options = {
3
3
  packageNames: string[];
4
4
  dir: string;
5
- cwd: string;
6
5
  };
7
- declare const getMetaDataFromPackageJson: ({ cwd, dir, packageNames }: Options) => {
6
+ declare const getMetaDataFromPackageJson: ({ dir, packageNames }: Options) => {
8
7
  hostDependencies: HostDependencies;
9
8
  installedBinaries: InstalledBinaries;
10
9
  hasTypesIncluded: Set<string>;
@@ -1,7 +1,7 @@
1
1
  import { isDefinitelyTyped } from '../util/modules.js';
2
2
  import { timerify } from '../util/Performance.js';
3
3
  import { loadPackageManifest } from './helpers.js';
4
- const getMetaDataFromPackageJson = ({ cwd, dir, packageNames }) => {
4
+ const getMetaDataFromPackageJson = ({ dir, packageNames }) => {
5
5
  const hostDependencies = new Map();
6
6
  const installedBinaries = new Map();
7
7
  const hasTypesIncluded = new Set();
@@ -13,7 +13,7 @@ const getMetaDataFromPackageJson = ({ cwd, dir, packageNames }) => {
13
13
  installedBinaries.set(key, new Set([value]));
14
14
  };
15
15
  for (const packageName of packageNames) {
16
- const manifest = loadPackageManifest({ cwd, dir, packageName });
16
+ const manifest = loadPackageManifest({ dir, packageName });
17
17
  if (manifest) {
18
18
  const defaultBinaryName = packageName.replace(/^@[^/]+\//, '');
19
19
  const binaries = typeof manifest.bin === 'string' ? [defaultBinaryName] : Object.keys(manifest.bin ?? {});
@@ -1,14 +1,7 @@
1
1
  import { argsFrom } from '../../binaries/util.js';
2
2
  const title = 'dotenv';
3
3
  const args = {
4
- fromArgs: (parsed, args) => {
5
- if (parsed._[0])
6
- return argsFrom(args, parsed._[0]);
7
- if (!parsed['--'] || parsed['--'].length === 0)
8
- return [];
9
- const script = parsed['--'].map(arg => (arg.includes(' ') ? `"${arg}"` : arg)).join(' ');
10
- return [script];
11
- },
4
+ fromArgs: (parsed, args) => (parsed._[0] ? argsFrom(args, parsed._[0]) : (parsed['--'] ?? [])),
12
5
  };
13
6
  const plugin = {
14
7
  title,
@@ -1,6 +1,7 @@
1
1
  import type { PluginOptions } from '../../types/config.ts';
2
2
  import { type ConfigInput, type Input } from '../../util/input.ts';
3
- import type { ESLintConfig, ESLintConfigDeprecated, OverrideConfigDeprecated } from './types.ts';
3
+ import type { ESLintConfig, ESLintConfigDeprecated, OverrideConfigDeprecated, Settings } from './types.ts';
4
4
  export declare const isFlatConfig: (fileName: string) => boolean;
5
5
  export declare const getInputs: (config: ESLintConfigDeprecated | OverrideConfigDeprecated | ESLintConfig, options: PluginOptions) => (Input | ConfigInput)[];
6
+ export declare const getInputsFromSettings: (settings?: Settings) => Input[];
6
7
  export declare const resolveFormatters: (formatters: string | string[]) => Set<Input>;
@@ -80,6 +80,7 @@ const getDependenciesFromSettings = (settings = {}) => {
80
80
  }
81
81
  });
82
82
  };
83
+ export const getInputsFromSettings = (settings) => compact(getDependenciesFromSettings(settings)).map(id => toDeferResolve(id, { optional: true }));
83
84
  const builtinFormatters = new Set(['html', 'json-with-metadata', 'json', 'stylish']);
84
85
  export const resolveFormatters = (formatters) => {
85
86
  const inputs = new Set();
@@ -1,3 +1,4 @@
1
1
  import type { Program } from 'oxc-parser';
2
2
  import { type Input } from '../../util/input.ts';
3
+ export declare const getInputsFromSettingsAST: (program: Program) => Input[];
3
4
  export declare const getInputsFromFlatConfigAST: (program: Program) => Input[];
@@ -3,7 +3,7 @@ import { toDeferResolve } from '../../util/input.js';
3
3
  import { findProperty, getPropertyKey } from '../../typescript/ast-helpers.js';
4
4
  import { getStringValue } from '../../typescript/ast-nodes.js';
5
5
  import { isInternal } from '../../util/path.js';
6
- export const getInputsFromFlatConfigAST = (program) => {
6
+ export const getInputsFromSettingsAST = (program) => {
7
7
  const inputs = [];
8
8
  const addResolver = (key, resolver) => {
9
9
  if (!resolver || resolver === 'node' || isInternal(resolver))
@@ -35,6 +35,9 @@ export const getInputsFromFlatConfigAST = (program) => {
35
35
  },
36
36
  });
37
37
  visitor.visit(program);
38
- inputs.push(toDeferResolve('eslint-import-resolver-typescript', { optional: true }));
39
38
  return inputs;
40
39
  };
40
+ export const getInputsFromFlatConfigAST = (program) => [
41
+ ...getInputsFromSettingsAST(program),
42
+ toDeferResolve('eslint-import-resolver-typescript', { optional: true }),
43
+ ];
@@ -6,7 +6,7 @@ type ParserOptions = {
6
6
  presets: string[];
7
7
  };
8
8
  };
9
- type Settings = Record<string, Record<string, unknown> | string>;
9
+ export type Settings = Record<string, Record<string, unknown> | string>;
10
10
  type Rules = Record<string, string | number>;
11
11
  type BaseConfig = {
12
12
  extends?: string | string[];
@@ -6,12 +6,20 @@ import { hasDependency } from '../../util/plugin.js';
6
6
  const title = 'Lefthook';
7
7
  const enablers = ['lefthook', '@arkweid/lefthook', '@evilmartians/lefthook'];
8
8
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
9
+ const configFiles = [
10
+ 'lefthook.{yml,yaml,json,jsonc,toml}',
11
+ '.lefthook.{yml,yaml,json,jsonc,toml}',
12
+ '.config/lefthook.{yml,yaml,json,jsonc,toml}',
13
+ 'lefthook-local.{yml,yaml,json,jsonc,toml}',
14
+ '.lefthook-local.{yml,yaml,json,jsonc,toml}',
15
+ '.config/lefthook-local.{yml,yaml,json,jsonc,toml}',
16
+ ];
9
17
  const resolveConfig = async (localConfig, options) => {
10
18
  if (options.isProduction)
11
19
  return [];
12
20
  const { manifest, configFileName, cwd, getInputsFromScripts } = options;
13
21
  const inputs = manifest.devDependencies ? Object.keys(manifest.devDependencies).map(id => toDependency(id)) : [];
14
- if (extname(configFileName) === '.yml') {
22
+ if (extname(configFileName) !== '') {
15
23
  const scripts = findByKeyDeep(localConfig, 'run').flatMap(command => {
16
24
  const deps = getInputsFromScripts([command.run], { ...options, knownBinsOnly: true });
17
25
  const dir = command.root ?? cwd;
@@ -33,7 +41,7 @@ const plugin = {
33
41
  title,
34
42
  enablers,
35
43
  isEnabled,
36
- config: options => ['lefthook.yml', ...getGitHookPaths('.git/hooks', true, options.cwd)],
44
+ config: options => [...configFiles, ...getGitHookPaths('.git/hooks', true, options.cwd)],
37
45
  resolveConfig,
38
46
  };
39
47
  export default plugin;
@@ -1,4 +1,5 @@
1
1
  import { hasDependency } from '../../util/plugin.js';
2
+ import { toShellCommand } from '../../util/scripts.js';
2
3
  const title = 'moonrepo';
3
4
  const enablers = ['@moonrepo/cli'];
4
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
@@ -6,12 +7,11 @@ const isRootOnly = true;
6
7
  const config = ['moon.yml', '.moon/tasks.yml', '.moon/tasks/*.yml'];
7
8
  const resolveConfig = async (config, options) => {
8
9
  const tasks = config.tasks ? Object.values(config.tasks) : [];
10
+ const expand = (value) => value.replace('$workspaceRoot', options.rootCwd).replace('$projectRoot', options.cwd);
9
11
  const inputs = tasks
10
12
  .map(task => task.command)
11
13
  .filter(command => command)
12
- .map(command => (Array.isArray(command) ? command.join(' ') : command))
13
- .map(command => command.replace('$workspaceRoot', options.rootCwd))
14
- .map(command => command.replace('$projectRoot', options.cwd))
14
+ .map(command => (Array.isArray(command) ? toShellCommand(command.map(expand)) : expand(command)))
15
15
  .flatMap(command => options.getInputsFromScripts(command));
16
16
  return [...inputs];
17
17
  };
@@ -49,6 +49,26 @@ const resolveAlias = (specifier, srcDir, rootDir) => {
49
49
  return join(srcDir, specifier.slice(2));
50
50
  return specifier;
51
51
  };
52
+ const remoteSourcePrefixes = ['gh:', 'github:', 'gitlab:', 'bitbucket:', 'https://', 'http://'];
53
+ const toLayerSource = (layer) => {
54
+ if (typeof layer === 'string')
55
+ return layer;
56
+ if (Array.isArray(layer))
57
+ return layer[0];
58
+ if (layer && typeof layer === 'object' && 'source' in layer)
59
+ return layer.source;
60
+ };
61
+ const toLayerSources = (extend) => {
62
+ const sources = [];
63
+ if (!extend)
64
+ return sources;
65
+ for (const layer of Array.isArray(extend) ? extend : [extend]) {
66
+ const source = toLayerSource(layer);
67
+ if (typeof source === 'string')
68
+ sources.push(source);
69
+ }
70
+ return sources;
71
+ };
52
72
  const addAppEntries = (inputs, srcDir, serverDir, config, dir) => {
53
73
  for (const id of entry)
54
74
  inputs.push(toEntry(join(srcDir, id)));
@@ -111,15 +131,17 @@ const resolveConfig = async (localConfig, options) => {
111
131
  }
112
132
  }
113
133
  }
114
- for (const ext of localConfig.extends ?? []) {
115
- const target = resolveAlias(ext, srcDir, cwd);
134
+ for (const source of toLayerSources(localConfig.extends)) {
135
+ if (remoteSourcePrefixes.some(prefix => source.startsWith(prefix)))
136
+ continue;
137
+ const target = resolveAlias(source, srcDir, cwd);
116
138
  const resolved = isInternal(target) ? toAbsolute(target, cwd) : target;
117
139
  const configs = _syncGlob({ cwd: resolved, patterns: config });
118
140
  if (configs.length > 0)
119
141
  for (const cfg of configs)
120
142
  inputs.push(toConfig('nuxt', cfg));
121
143
  else
122
- inputs.push(toDependency(ext));
144
+ inputs.push(toDependency(source));
123
145
  }
124
146
  for (const layerConfig of findLayerConfigs(cwd)) {
125
147
  inputs.push(toConfig('nuxt', layerConfig));
@@ -1,3 +1,6 @@
1
+ type NuxtLayer = string | [string, unknown?] | {
2
+ source: string;
3
+ };
1
4
  export interface NuxtConfig {
2
5
  srcDir?: string;
3
6
  buildDir?: string;
@@ -14,7 +17,7 @@ export interface NuxtConfig {
14
17
  autoImport?: boolean;
15
18
  dirs?: string[];
16
19
  };
17
- extends?: string[];
20
+ extends?: NuxtLayer | NuxtLayer[];
18
21
  components?: Array<string | {
19
22
  path: string;
20
23
  }> | {
@@ -25,3 +28,4 @@ export interface NuxtConfig {
25
28
  css?: string[];
26
29
  alias?: Record<string, string>;
27
30
  }
31
+ export {};
@@ -3,10 +3,12 @@ import { findProperty, getPropertyValues } from '../../typescript/ast-helpers.js
3
3
  import { toDependency, toEntry } from '../../util/input.js';
4
4
  import { isInternal } from '../../util/path.js';
5
5
  import { hasDependency } from '../../util/plugin.js';
6
+ import { getInputsFromSettings } from '../eslint/helpers.js';
7
+ import { getInputsFromSettingsAST } from '../eslint/resolveFromAST.js';
6
8
  const title = 'Oxlint';
7
9
  const enablers = ['oxlint', 'vite-plus'];
8
10
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
9
- const config = ['.oxlintrc.json', 'oxlint.config.{ts,mts}', 'vite.config.{js,mjs,ts,cjs,mts,cts}'];
11
+ const config = ['.oxlintrc.{json,jsonc}', 'oxlint.config.{ts,mts}', 'vite.config.{js,mjs,ts,cjs,mts,cts}'];
10
12
  const isViteConfig = (configFileName) => configFileName.startsWith('vite.config.');
11
13
  const args = {
12
14
  config: true,
@@ -29,6 +31,8 @@ const resolveConfig = config => {
29
31
  for (const input of resolveJsPlugins(override.jsPlugins))
30
32
  inputs.push(input);
31
33
  }
34
+ for (const input of getInputsFromSettings(config.settings))
35
+ inputs.push(input);
32
36
  return inputs;
33
37
  };
34
38
  const resolveFromAST = (program, options) => {
@@ -51,7 +55,7 @@ const resolveFromAST = (program, options) => {
51
55
  },
52
56
  });
53
57
  visitor.visit(program);
54
- return resolveJsPlugins([...jsPlugins]);
58
+ return [...resolveJsPlugins([...jsPlugins]), ...getInputsFromSettingsAST(program)];
55
59
  };
56
60
  const plugin = {
57
61
  title,
@@ -1,3 +1,4 @@
1
+ import type { Settings } from '../eslint/types.ts';
1
2
  type JsPlugin = string | {
2
3
  name: string;
3
4
  specifier: string;
@@ -8,5 +9,6 @@ type Override = {
8
9
  export type OxlintConfig = {
9
10
  jsPlugins?: JsPlugin[];
10
11
  overrides?: Override[];
12
+ settings?: Settings;
11
13
  };
12
14
  export {};
@@ -4,7 +4,7 @@ import { hasDependency } from '../../util/plugin.js';
4
4
  const title = 'tsup';
5
5
  const enablers = ['tsup'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
- const config = ['tsup.config.{js,ts,cjs,mjs,json}', 'package.json'];
7
+ const config = ['tsup.config.{js,ts,cjs,mjs,cts,mts,json}', 'package.json'];
8
8
  const isLoadConfig = ({ configFileName }) => configFileName === 'package.json' || configFileName.endsWith('.json');
9
9
  const resolveConfig = async (config) => {
10
10
  if (typeof config === 'function')
@@ -1,12 +1,21 @@
1
1
  import { compact } from '../../util/array.js';
2
- import { toConfig, toDeferResolve, toProductionDependency } from '../../util/input.js';
2
+ import { toConfig, toDeferResolve, toDependency, toProductionDependency } from '../../util/input.js';
3
3
  import { join } from '../../util/path.js';
4
4
  import { hasDependency } from '../../util/plugin.js';
5
+ import { toShellCommand } from '../../util/scripts.js';
5
6
  const title = 'TypeScript';
6
7
  const enablers = ['typescript', '@typescript/native', '@typescript/native-preview'];
7
8
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
8
- const config = ['tsconfig.json'];
9
- const resolveConfig = async (localConfig, options) => {
9
+ const config = ['tsconfig.json', 'package.json'];
10
+ const packageJsonPath = 'typescript.contentMapper';
11
+ const resolveContentMapper = ({ exec }, options) => {
12
+ if (!Array.isArray(exec) || exec.some(arg => typeof arg !== 'string'))
13
+ return [];
14
+ return options
15
+ .getInputsFromScripts(toShellCommand(exec))
16
+ .map(input => input.type === 'entry' || input.type === 'deferResolveEntry' ? { ...input, production: true } : input);
17
+ };
18
+ const resolveTsConfig = (localConfig, options) => {
10
19
  const { compilerOptions } = localConfig;
11
20
  const extend = localConfig.extends
12
21
  ? [localConfig.extends]
@@ -16,8 +25,9 @@ const resolveConfig = async (localConfig, options) => {
16
25
  const references = localConfig.references
17
26
  ?.filter(reference => reference.path.endsWith('.json'))
18
27
  .map(reference => toConfig('typescript', reference.path, { containingFilePath: options.configFilePath })) ?? [];
28
+ const contentMappers = localConfig.contentMappers?.map(contentMapper => toDependency(contentMapper.package)) ?? [];
19
29
  if (!(compilerOptions && localConfig))
20
- return compact([...extend, ...references]);
30
+ return compact([...contentMappers, ...extend, ...references]);
21
31
  const jsx = (compilerOptions?.jsxImportSource ? [compilerOptions.jsxImportSource] : []).map(toProductionDependency);
22
32
  const types = compilerOptions.types ?? [];
23
33
  const plugins = Array.isArray(compilerOptions?.plugins)
@@ -25,6 +35,7 @@ const resolveConfig = async (localConfig, options) => {
25
35
  : [];
26
36
  const importHelpers = compilerOptions?.importHelpers ? ['tslib'] : [];
27
37
  return compact([
38
+ ...contentMappers,
28
39
  ...extend,
29
40
  ...references,
30
41
  ...types.map(id => toDeferResolve(id, { isTypeOnly: true, dir: options.cwd })),
@@ -32,19 +43,25 @@ const resolveConfig = async (localConfig, options) => {
32
43
  ...jsx,
33
44
  ]);
34
45
  };
46
+ const resolveConfig = (localConfig, options) => options.configFileName === 'package.json'
47
+ ? resolveContentMapper(localConfig, options)
48
+ : resolveTsConfig(localConfig, options);
35
49
  const args = {
36
50
  binaries: ['tsc', 'tsgo'],
37
51
  string: ['project'],
38
52
  alias: { project: ['p'] },
39
53
  config: [['project', (p) => (p.endsWith('.json') ? p : join(p, 'tsconfig.json'))]],
40
54
  };
41
- const note = "[What's up with that configurable tsconfig.json location?](/reference/faq#whats-up-with-that-configurable-tsconfigjson-location)";
55
+ const note = `[What's up with that configurable tsconfig.json location?](/reference/faq#whats-up-with-that-configurable-tsconfigjson-location)
56
+
57
+ In a content mapper package, the command in \`package.json#typescript.contentMapper.exec\` is resolved to a production entry.`;
42
58
  export const docs = { note };
43
59
  const plugin = {
44
60
  title,
45
61
  enablers,
46
62
  isEnabled,
47
63
  config,
64
+ packageJsonPath,
48
65
  resolveConfig,
49
66
  args,
50
67
  };