knip 5.62.0 → 5.63.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 (64) hide show
  1. package/README.md +22 -24
  2. package/dist/ConfigurationChief.d.ts +3 -0
  3. package/dist/ConfigurationChief.js +12 -4
  4. package/dist/IssueCollector.js +1 -1
  5. package/dist/ProjectPrincipal.d.ts +1 -0
  6. package/dist/ProjectPrincipal.js +9 -3
  7. package/dist/binaries/fallback.js +4 -2
  8. package/dist/cli.js +3 -2
  9. package/dist/compilers/index.d.ts +20 -0
  10. package/dist/graph/analyze.js +1 -1
  11. package/dist/graph/build.js +18 -8
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +2 -1
  14. package/dist/plugins/astro/index.d.ts +1 -0
  15. package/dist/plugins/astro/index.js +4 -0
  16. package/dist/plugins/index.d.ts +19 -1
  17. package/dist/plugins/index.js +4 -0
  18. package/dist/plugins/lefthook/index.js +2 -0
  19. package/dist/plugins/node-modules-inspector/index.d.ts +12 -0
  20. package/dist/plugins/node-modules-inspector/index.js +17 -0
  21. package/dist/plugins/playwright/index.js +8 -1
  22. package/dist/plugins/playwright/types.d.ts +20 -14
  23. package/dist/plugins/preconstruct/index.js +2 -1
  24. package/dist/plugins/react-router/index.js +18 -8
  25. package/dist/plugins/rsbuild/index.js +11 -2
  26. package/dist/plugins/rsbuild/types.d.ts +8 -0
  27. package/dist/plugins/rslib/index.d.ts +10 -0
  28. package/dist/plugins/rslib/index.js +15 -0
  29. package/dist/plugins/rslib/types.d.ts +1 -0
  30. package/dist/plugins/rslib/types.js +1 -0
  31. package/dist/plugins/rspack/index.js +1 -1
  32. package/dist/plugins/typescript/index.d.ts +1 -1
  33. package/dist/reporters/symbols.js +3 -1
  34. package/dist/reporters/util/configuration-hints.d.ts +1 -1
  35. package/dist/reporters/util/configuration-hints.js +55 -19
  36. package/dist/reporters/util/util.d.ts +0 -2
  37. package/dist/reporters/util/util.js +2 -2
  38. package/dist/schema/configuration.d.ts +112 -0
  39. package/dist/schema/plugins.d.ts +46 -0
  40. package/dist/schema/plugins.js +2 -0
  41. package/dist/types/PluginNames.d.ts +2 -2
  42. package/dist/types/PluginNames.js +2 -0
  43. package/dist/types/entries.d.ts +3 -0
  44. package/dist/types/entries.js +1 -0
  45. package/dist/types/issues.d.ts +3 -1
  46. package/dist/types/package-json.d.ts +4 -0
  47. package/dist/types/tsconfig-json.d.ts +14 -0
  48. package/dist/types/tsconfig-json.js +1 -0
  49. package/dist/typescript/ast-helpers.js +1 -1
  50. package/dist/util/fs.d.ts +1 -1
  51. package/dist/util/glob-core.d.ts +1 -1
  52. package/dist/util/glob-core.js +8 -7
  53. package/dist/util/glob.d.ts +1 -0
  54. package/dist/util/glob.js +1 -1
  55. package/dist/util/is-identifier-referenced.js +17 -17
  56. package/dist/util/package-json.d.ts +2 -1
  57. package/dist/util/package-json.js +24 -12
  58. package/dist/util/parse-and-convert-gitignores.js +2 -0
  59. package/dist/util/reporter.js +3 -3
  60. package/dist/util/table.js +1 -3
  61. package/dist/version.d.ts +1 -1
  62. package/dist/version.js +1 -1
  63. package/package.json +9 -14
  64. package/schema.json +8 -0
package/README.md CHANGED
@@ -20,29 +20,28 @@ performance, less maintenance and easier refactorings.
20
20
  - Website: [knip.dev][6]
21
21
  - GitHub repo: [webpro-nl/knip][4]
22
22
  - npm package: [knip][1]
23
- - [Discord][7]
24
- - [Contributing Guide][8]
25
- - [Sponsor Knip!][9]
23
+ - [Contributing Guide][7]
24
+ - [Sponsor Knip!][8]
26
25
 
27
26
  ## Contributors
28
27
 
29
- Special thanks to [the wonderful people who have contributed to Knip][10]!
28
+ Special thanks to [the wonderful people who have contributed to Knip][9]!
30
29
 
31
30
  ## Knip
32
31
 
33
- /'knɪp/ means "(to) cut" and is [pronounced with a hard "K"][11] 🇳🇱
32
+ /'knɪp/ means "(to) cut" and is [pronounced with a hard "K"][10] 🇳🇱
34
33
 
35
34
  ## License
36
35
 
37
- Knip is free and open-source software licensed under the [ISC License][12].
36
+ Knip is free and open-source software licensed under the [ISC License][11].
38
37
 
39
38
  Parts of Knip have been inspired by and/or partially copy code from the
40
39
  following projects:
41
40
 
42
- - [@npmcli/package-json][17] ([ISC][18])
43
- - [@pnpm/deps.graph-sequencer][15] ([MIT][16])
44
- - [file-entry-cache][13] ([MIT][14])
45
- - [json-parse-even-better-errors][19] ([MIT][20])
41
+ - [@npmcli/package-json][12] ([ISC][13])
42
+ - [@pnpm/deps.graph-sequencer][14] ([MIT][15])
43
+ - [file-entry-cache][16] ([MIT][17])
44
+ - [json-parse-even-better-errors][18] ([MIT][19])
46
45
 
47
46
  [1]: https://www.npmjs.com/package/knip
48
47
  [2]: https://img.shields.io/npm/v/knip?color=f56e0f
@@ -51,18 +50,17 @@ following projects:
51
50
  [5]:
52
51
  https://img.shields.io/github/stars/webpro-nl/knip?style=flat-square&color=f56e0f
53
52
  [6]: https://knip.dev
54
- [7]: https://discord.gg/r5uXTtbTpc
55
- [8]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md
56
- [9]: https://knip.dev/sponsors
57
- [10]: https://knip.dev/#created-by-awesome-contributors
58
- [11]: https://www.youtube.com/watch?v=PE7h7KvQoUI&t=9s
59
- [12]: ./license
60
- [13]: https://github.com/jaredwray/cacheable/tree/main/packages/file-entry-cache
61
- [14]:
53
+ [7]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md
54
+ [8]: https://knip.dev/sponsors
55
+ [9]: https://knip.dev/#created-by-awesome-contributors
56
+ [10]: https://www.youtube.com/watch?v=PE7h7KvQoUI&t=9s
57
+ [11]: ./license
58
+ [12]: https://github.com/npm/package-json
59
+ [13]: https://github.com/npm/package-json/blob/main/LICENSE
60
+ [14]: https://github.com/pnpm/pnpm/tree/main/deps/graph-sequencer
61
+ [15]: https://github.com/pnpm/pnpm/blob/main/LICENSE
62
+ [16]: https://github.com/jaredwray/cacheable/tree/main/packages/file-entry-cache
63
+ [17]:
62
64
  https://github.com/jaredwray/cacheable/blob/main/packages/file-entry-cache/LICENSE
63
- [15]: https://github.com/pnpm/pnpm/tree/main/deps/graph-sequencer
64
- [16]: https://github.com/pnpm/pnpm/blob/main/LICENSE
65
- [17]: https://github.com/npm/package-json
66
- [18]: https://github.com/npm/package-json/blob/main/LICENSE
67
- [19]: https://github.com/npm/json-parse-even-better-errors
68
- [20]: https://github.com/npm/json-parse-even-better-errors/blob/main/LICENSE.md
65
+ [18]: https://github.com/npm/json-parse-even-better-errors
66
+ [19]: https://github.com/npm/json-parse-even-better-errors/blob/main/LICENSE.md
@@ -60,6 +60,7 @@ export declare class ConfigurationChief {
60
60
  private normalize;
61
61
  private setWorkspaces;
62
62
  private getListedWorkspaces;
63
+ private getIgnoredWorkspaces;
63
64
  private getIgnoredWorkspacePatterns;
64
65
  private getConfiguredWorkspaceKeys;
65
66
  private getAdditionalWorkspaceNames;
@@ -129,6 +130,7 @@ export declare class ConfigurationChief {
129
130
  nest?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
130
131
  netlify?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
131
132
  next?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
133
+ "node-modules-inspector"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
132
134
  nodemon?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
133
135
  "npm-package-json-lint"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
134
136
  nuxt?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -152,6 +154,7 @@ export declare class ConfigurationChief {
152
154
  remix?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
153
155
  rollup?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
154
156
  rsbuild?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
157
+ rslib?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
155
158
  rspack?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
156
159
  "semantic-release"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
157
160
  sentry?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -10,7 +10,7 @@ import { createWorkspaceGraph } from './util/create-workspace-graph.js';
10
10
  import { ConfigurationError } from './util/errors.js';
11
11
  import { findFile, isDirectory, isFile, loadJSON } from './util/fs.js';
12
12
  import { getIncludedIssueTypes } from './util/get-included-issue-types.js';
13
- import { _dirGlob } from './util/glob.js';
13
+ import { _dirGlob, removeProductionSuffix } from './util/glob.js';
14
14
  import { graphSequencer } from './util/graph-sequencer.js';
15
15
  import { defaultRules } from './util/issue-initializers.js';
16
16
  import { _load } from './util/loader.js';
@@ -110,6 +110,8 @@ export class ConfigurationChief {
110
110
  this.rawConfig = this.resolvedConfigFilePath
111
111
  ? await this.loadResolvedConfigurationFile(this.resolvedConfigFilePath)
112
112
  : manifest.knip;
113
+ if (manifest.knip)
114
+ this.resolvedConfigFilePath = manifestPath;
113
115
  this.parsedConfig = this.rawConfig ? knipConfigurationSchema.parse(partitionCompilers(this.rawConfig)) : {};
114
116
  this.config = this.normalize(this.parsedConfig);
115
117
  await this.setWorkspaces();
@@ -214,17 +216,23 @@ export class ConfigurationChief {
214
216
  : [];
215
217
  return workspaces.map(pattern => pattern.replace(/(?<=!?)\.\//, ''));
216
218
  }
219
+ getIgnoredWorkspaces() {
220
+ const ignoreWorkspaces = this.config.ignoreWorkspaces;
221
+ if (this.isProduction)
222
+ return ignoreWorkspaces.map(removeProductionSuffix);
223
+ return ignoreWorkspaces.filter(pattern => !pattern.endsWith('!'));
224
+ }
217
225
  getIgnoredWorkspacePatterns() {
218
226
  const ignoredWorkspacesManifest = this.getListedWorkspaces()
219
227
  .filter(name => name.startsWith('!'))
220
228
  .map(name => name.replace(/^!/, ''));
221
- return [...ignoredWorkspacesManifest, ...this.config.ignoreWorkspaces];
229
+ return [...ignoredWorkspacesManifest, ...this.getIgnoredWorkspaces()];
222
230
  }
223
231
  getConfiguredWorkspaceKeys() {
224
232
  const initialWorkspaces = this.rawConfig?.workspaces
225
233
  ? Object.keys(this.rawConfig.workspaces)
226
234
  : [ROOT_WORKSPACE_NAME];
227
- const ignoreWorkspaces = this.rawConfig?.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
235
+ const ignoreWorkspaces = this.getIgnoredWorkspaces();
228
236
  return initialWorkspaces.filter(workspaceName => !ignoreWorkspaces.includes(workspaceName));
229
237
  }
230
238
  async getAdditionalWorkspaceNames() {
@@ -405,7 +413,7 @@ export class ConfigurationChief {
405
413
  return this.includedWorkspaces.find(workspace => workspace.dir === workspaceDir);
406
414
  }
407
415
  getUnusedIgnoredWorkspaces() {
408
- const ignoredWorkspaceNames = this.config.ignoreWorkspaces;
416
+ const ignoredWorkspaceNames = this.config.ignoreWorkspaces.map(removeProductionSuffix);
409
417
  const workspaceNames = [...this.workspacePackages.keys(), ...this.additionalWorkspaceNames];
410
418
  return ignoredWorkspaceNames
411
419
  .filter(ignoredWorkspaceName => !workspaceNames.some(name => picomatch.isMatch(name, ignoredWorkspaceName)))
@@ -56,7 +56,7 @@ export class IssueCollector {
56
56
  issue.severity = this.rules[type];
57
57
  const issues = this.issues[type];
58
58
  issues[key] = issues[key] ?? {};
59
- const symbol = type.endsWith('Members') && issue.parentSymbol ? `${issue.parentSymbol}.${issue.symbol}` : issue.symbol;
59
+ const symbol = issue.parentSymbol ? `${issue.parentSymbol}.${issue.symbol}` : issue.symbol;
60
60
  if (!issues[key][symbol]) {
61
61
  issues[key][symbol] = issue;
62
62
  this.counters[issue.type]++;
@@ -30,6 +30,7 @@ export declare class ProjectPrincipal {
30
30
  languageServiceHost: ts.LanguageServiceHost;
31
31
  };
32
32
  findReferences?: ts.LanguageService['findReferences'];
33
+ getImplementationAtPosition?: ts.LanguageService['getImplementationAtPosition'];
33
34
  constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, isProduction, }: PrincipalOptions);
34
35
  init(): void;
35
36
  addPaths(paths: Paths, basePath: string): void;
@@ -42,6 +42,7 @@ export class ProjectPrincipal {
42
42
  toSourceFilePath;
43
43
  backend;
44
44
  findReferences;
45
+ getImplementationAtPosition;
45
46
  constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, isProduction, }) {
46
47
  this.cwd = cwd;
47
48
  this.compilerOptions = {
@@ -174,14 +175,18 @@ export class ProjectPrincipal {
174
175
  this.backend.fileManager.sourceFileCache.delete(filePath);
175
176
  }
176
177
  findUnusedMembers(filePath, members) {
177
- if (!this.findReferences) {
178
+ if (!this.findReferences || !this.getImplementationAtPosition) {
178
179
  const languageService = ts.createLanguageService(this.backend.languageServiceHost, ts.createDocumentRegistry());
179
180
  this.findReferences = timerify(languageService.findReferences);
181
+ this.getImplementationAtPosition = timerify(languageService.getImplementationAtPosition);
180
182
  }
181
183
  return members.filter(member => {
182
184
  if (member.jsDocTags.has(PUBLIC_TAG))
183
185
  return false;
184
- const referencedSymbols = this.findReferences?.(filePath, member.pos) ?? [];
186
+ const implementations = this.getImplementationAtPosition?.(filePath, member.pos)?.filter(impl => impl.fileName !== filePath || impl.textSpan.start !== member.pos) ?? [];
187
+ const referencedSymbols = this.findReferences?.(filePath, member.pos)?.filter(sym => !implementations.some(impl => impl.fileName === sym.definition.fileName &&
188
+ impl.textSpan.start === sym.definition.textSpan.start &&
189
+ impl.textSpan.length === sym.definition.textSpan.length)) ?? [];
185
190
  const refs = referencedSymbols.flatMap(refs => refs.references).filter(ref => !ref.isDefinition);
186
191
  return refs.length === 0;
187
192
  });
@@ -189,9 +194,10 @@ export class ProjectPrincipal {
189
194
  hasExternalReferences(filePath, exportedItem) {
190
195
  if (exportedItem.jsDocTags.has(PUBLIC_TAG))
191
196
  return false;
192
- if (!this.findReferences) {
197
+ if (!this.findReferences || !this.getImplementationAtPosition) {
193
198
  const languageService = ts.createLanguageService(this.backend.languageServiceHost, ts.createDocumentRegistry());
194
199
  this.findReferences = timerify(languageService.findReferences);
200
+ this.getImplementationAtPosition = timerify(languageService.getImplementationAtPosition);
195
201
  }
196
202
  const referencedSymbols = this.findReferences(filePath, exportedItem.pos);
197
203
  if (!referencedSymbols?.length)
@@ -4,11 +4,13 @@ import { toBinary, toDeferResolve, toEntry } from '../util/input.js';
4
4
  const spawningBinaries = ['cross-env', 'retry-cli'];
5
5
  const endOfCommandBinaries = ['dotenvx'];
6
6
  const positionals = new Set(['babel-node', 'esbuild', 'execa', 'jiti', 'oxnode', 'vite-node', 'zx']);
7
+ const positionalBinaries = new Set(['concurrently']);
7
8
  export const resolve = (binary, args, { fromArgs }) => {
8
9
  const parsed = parseArgs(args, { boolean: ['quiet', 'verbose'], '--': endOfCommandBinaries.includes(binary) });
9
- const bin = binary.startsWith('.') ? toEntry(binary) : toBinary(binary);
10
+ const bin = binary.startsWith('.') ? toEntry(binary) : binary.includes('*') ? undefined : toBinary(binary);
10
11
  const shiftedArgs = spawningBinaries.includes(binary) ? fromArgs(args) : [];
11
12
  const pos = positionals.has(binary) ? [toDeferResolve(parsed._[0])] : [];
12
13
  const newCommand = parsed['--'] && parsed['--'].length > 0 ? fromArgs(parsed['--']) : [];
13
- return compact([bin, ...shiftedArgs, ...pos, ...newCommand]);
14
+ const commands = positionalBinaries.has(binary) ? parsed._.flatMap(cmd => fromArgs([cmd])) : [];
15
+ return compact([bin, ...shiftedArgs, ...pos, ...newCommand, ...commands]);
14
16
  };
package/dist/cli.js CHANGED
@@ -23,7 +23,7 @@ const isShowProgress = isNoProgress === false && process.stdout.isTTY && typeof
23
23
  const workspace = rawWorkspaceArg ? toPosix(rawWorkspaceArg).replace(/^\.\//, '').replace(/\/$/, '') : undefined;
24
24
  const run = async () => {
25
25
  try {
26
- const { report, issues, counters, rules, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaces, } = await main({
26
+ const { report, issues, counters, rules, tagHints, configurationHints, isTreatConfigHintsAsErrors, includedWorkspaces, configFilePath, } = await main({
27
27
  cacheLocation,
28
28
  cwd,
29
29
  excludedIssueTypes,
@@ -59,13 +59,14 @@ const run = async () => {
59
59
  tagHints,
60
60
  configurationHints,
61
61
  isDisableConfigHints,
62
- isTreatConfigHintsAsErrors,
62
+ isTreatConfigHintsAsErrors: treatConfigHintsAsErrors ?? isTreatConfigHintsAsErrors,
63
63
  cwd,
64
64
  isProduction,
65
65
  isShowProgress,
66
66
  options: reporterOptions,
67
67
  preprocessorOptions,
68
68
  includedWorkspaces,
69
+ configFilePath,
69
70
  };
70
71
  const finalData = await runPreprocessors(preprocessor, initialData);
71
72
  await runReporters(reporter, finalData);
@@ -264,6 +264,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
264
264
  entry?: string | string[] | undefined;
265
265
  project?: string | string[] | undefined;
266
266
  } | undefined;
267
+ 'node-modules-inspector'?: string | boolean | string[] | {
268
+ config?: string | string[] | undefined;
269
+ entry?: string | string[] | undefined;
270
+ project?: string | string[] | undefined;
271
+ } | undefined;
267
272
  nodemon?: string | boolean | string[] | {
268
273
  config?: string | string[] | undefined;
269
274
  entry?: string | string[] | undefined;
@@ -379,6 +384,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
379
384
  entry?: string | string[] | undefined;
380
385
  project?: string | string[] | undefined;
381
386
  } | undefined;
387
+ rslib?: string | boolean | string[] | {
388
+ config?: string | string[] | undefined;
389
+ entry?: string | string[] | undefined;
390
+ project?: string | string[] | undefined;
391
+ } | undefined;
382
392
  rspack?: string | boolean | string[] | {
383
393
  config?: string | string[] | undefined;
384
394
  entry?: string | string[] | undefined;
@@ -825,6 +835,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
825
835
  entry?: string | string[] | undefined;
826
836
  project?: string | string[] | undefined;
827
837
  } | undefined;
838
+ 'node-modules-inspector'?: string | boolean | string[] | {
839
+ config?: string | string[] | undefined;
840
+ entry?: string | string[] | undefined;
841
+ project?: string | string[] | undefined;
842
+ } | undefined;
828
843
  nodemon?: string | boolean | string[] | {
829
844
  config?: string | string[] | undefined;
830
845
  entry?: string | string[] | undefined;
@@ -940,6 +955,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
940
955
  entry?: string | string[] | undefined;
941
956
  project?: string | string[] | undefined;
942
957
  } | undefined;
958
+ rslib?: string | boolean | string[] | {
959
+ config?: string | string[] | undefined;
960
+ entry?: string | string[] | undefined;
961
+ project?: string | string[] | undefined;
962
+ } | undefined;
943
963
  rspack?: string | boolean | string[] | {
944
964
  config?: string | string[] | undefined;
945
965
  entry?: string | string[] | undefined;
@@ -6,7 +6,7 @@ import { getShouldIgnoreHandler, getShouldIgnoreTagHandler } from '../util/tag.j
6
6
  import { createAndPrintTrace, printTrace } from '../util/trace.js';
7
7
  export const analyze = async (options) => {
8
8
  const { analyzedFiles, chief, collector, deputy, entryPaths, factory, fixer, graph, isFix, isIncludeLibs, isProduction, report, streamer, tags, unreferencedFiles, } = options;
9
- const isReportDependencies = report.dependencies || report.unlisted || report.unresolved;
9
+ const isReportDependencies = report.dependencies || report.unlisted || report.unresolved || report.binaries;
10
10
  const isReportValues = report.exports || report.nsExports || report.classMembers;
11
11
  const isReportTypes = report.types || report.nsTypes || report.enumMembers;
12
12
  const isReportClassMembers = report.classMembers;
@@ -5,12 +5,12 @@ import { DEFAULT_EXTENSIONS, FOREIGN_FILE_EXTENSIONS } from '../constants.js';
5
5
  import { perfObserver } from '../util/Performance.js';
6
6
  import { debugLog, debugLogArray } from '../util/debug.js';
7
7
  import { getReferencedInputsHandler } from '../util/get-referenced-inputs.js';
8
- import { _glob, negate } from '../util/glob.js';
8
+ import { _glob, _syncGlob, negate } from '../util/glob.js';
9
9
  import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
10
10
  import { loadTSConfig } from '../util/load-tsconfig.js';
11
11
  import { getOrCreateFileNode, updateImportMap } from '../util/module-graph.js';
12
12
  import { getPackageNameFromModuleSpecifier, isStartsLikePackageName, sanitizeSpecifier } from '../util/modules.js';
13
- import { getEntryPathsFromManifest } from '../util/package-json.js';
13
+ import { getEntrySpecifiersFromManifest, getManifestImportDependencies } from '../util/package-json.js';
14
14
  import { dirname, extname, isAbsolute, join, relative, toRelative } from '../util/path.js';
15
15
  import { augmentWorkspace, getToSourcePathHandler, getToSourcePathsHandler } from '../util/to-source-path.js';
16
16
  export async function build({ cacheLocation, chief, collector, cwd, deputy, factory, gitignore, isCache, isFixExports, isFixTypes, isGitIgnored, isIsolateWorkspaces, isProduction, isSkipLibs, isStrict, isWatch, report, streamer, tags, tsConfigFile, workspaces, }) {
@@ -28,7 +28,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
28
28
  deputy.addWorkspace({ name, cwd, dir, manifestPath, manifestStr, manifest, ...chief.getIgnores(name) });
29
29
  }
30
30
  for (const workspace of workspaces) {
31
- const { name, dir, ancestors, pkgName } = workspace;
31
+ const { name, dir, ancestors, pkgName, manifestPath: filePath } = workspace;
32
32
  streamer.cast('Analyzing workspace', name);
33
33
  const manifest = chief.getManifestForWorkspace(name);
34
34
  if (!manifest)
@@ -72,10 +72,20 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
72
72
  const ignore = worker.getIgnorePatterns();
73
73
  const sharedGlobOptions = { cwd, dir, gitignore };
74
74
  collector.addIgnorePatterns(ignore.map(pattern => join(cwd, pattern)));
75
- const entryPathsFromManifest = getEntryPathsFromManifest(manifest);
76
- for (const filePath of await toSourceFilePaths(entryPathsFromManifest, dir, extensionGlobStr)) {
75
+ const entrySpecifiersFromManifest = getEntrySpecifiersFromManifest(manifest);
76
+ for (const filePath of await toSourceFilePaths(entrySpecifiersFromManifest, dir, extensionGlobStr)) {
77
77
  inputs.add(toProductionEntry(filePath));
78
78
  }
79
+ for (const identifier of entrySpecifiersFromManifest) {
80
+ if (!identifier.startsWith('!') && !isGitIgnored(join(dir, identifier))) {
81
+ const files = _syncGlob({ patterns: [identifier], cwd: dir });
82
+ if (files.length === 0) {
83
+ collector.addConfigurationHint({ type: 'package-entry', filePath, identifier, workspaceName: name });
84
+ }
85
+ }
86
+ }
87
+ for (const dep of getManifestImportDependencies(manifest))
88
+ deputy.addReferencedDependency(name, dep);
79
89
  const principal = factory.createPrincipal({
80
90
  cwd: dir,
81
91
  isFile,
@@ -160,7 +170,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
160
170
  principal.addEntryPaths(workspaceEntryPaths);
161
171
  }
162
172
  {
163
- const label = 'production entry paths from plugins (skip exports analysis)';
173
+ const label = 'production entry paths from plugins (ignore exports)';
164
174
  const patterns = Array.from(productionPatternsSkipExports);
165
175
  const pluginWorkspaceEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
166
176
  principal.addEntryPaths(pluginWorkspaceEntryPaths, { skipExportsAnalysis: true });
@@ -181,7 +191,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
181
191
  }
182
192
  else {
183
193
  {
184
- const label = 'entry paths from plugins (skip exports analysis)';
194
+ const label = 'entry paths from plugins (ignore exports)';
185
195
  const patterns = worker.getPluginEntryFilePatterns([
186
196
  ...entryPatternsSkipExports,
187
197
  ...productionPatternsSkipExports,
@@ -212,7 +222,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
212
222
  principal.addProjectPath(projectPath);
213
223
  }
214
224
  {
215
- const label = 'plugin configuration paths (skip exports analysis)';
225
+ const label = 'plugin configuration paths (ignore exports)';
216
226
  const patterns = worker.getPluginConfigPatterns();
217
227
  const configurationEntryPaths = await _glob({ ...sharedGlobOptions, patterns, label });
218
228
  principal.addEntryPaths(configurationEntryPaths, { skipExportsAnalysis: true });
package/dist/index.d.ts CHANGED
@@ -10,4 +10,5 @@ export declare const main: (unresolvedConfiguration: CommandLineOptions) => Prom
10
10
  configurationHints: Set<import("./types/issues.js").ConfigurationHint>;
11
11
  isTreatConfigHintsAsErrors: boolean;
12
12
  includedWorkspaces: import("./ConfigurationChief.js").Workspace[];
13
+ configFilePath: string | undefined;
13
14
  }>;
package/dist/index.js CHANGED
@@ -106,7 +106,7 @@ export const main = async (unresolvedConfiguration) => {
106
106
  const touchedFiles = await fixer.fixIssues(issues);
107
107
  if (isFormat) {
108
108
  const report = await formatly(Array.from(touchedFiles), { cwd });
109
- if (report.ran && report.result.code === 0) {
109
+ if (report.ran && report.result && (report.result.runner === 'virtual' || report.result.code === 0)) {
110
110
  debugLogArray('*', `Formatted files using ${report.formatter.name} (${report.formatter.runner})`, touchedFiles);
111
111
  }
112
112
  else {
@@ -125,5 +125,6 @@ export const main = async (unresolvedConfiguration) => {
125
125
  configurationHints,
126
126
  isTreatConfigHintsAsErrors: chief.config.isTreatConfigHintsAsErrors,
127
127
  includedWorkspaces: chief.includedWorkspaces,
128
+ configFilePath: chief.resolvedConfigFilePath,
128
129
  };
129
130
  };
@@ -9,5 +9,6 @@ declare const _default: {
9
9
  production: string[];
10
10
  resolveFromAST: ResolveFromAST;
11
11
  resolve: Resolve;
12
+ project: string[];
12
13
  };
13
14
  export default _default;
@@ -6,8 +6,11 @@ const enablers = ['astro'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
7
  export const config = ['astro.config.{js,cjs,mjs,ts,mts}'];
8
8
  const entry = ['src/content/config.ts', 'src/content.config.ts'];
9
+ const project = ['src/**/*'];
9
10
  const production = [
10
11
  'src/pages/**/*.{astro,mdx,js,ts}',
12
+ '!src/pages/**/_*',
13
+ '!src/pages/**/_*/**',
11
14
  'src/content/**/*.mdx',
12
15
  'src/middleware.{js,ts}',
13
16
  'src/actions/index.{js,ts}',
@@ -39,4 +42,5 @@ export default {
39
42
  production,
40
43
  resolveFromAST,
41
44
  resolve,
45
+ project,
42
46
  };
@@ -15,6 +15,7 @@ export declare const Plugins: {
15
15
  production: string[];
16
16
  resolveFromAST: import("../types/config.js").ResolveFromAST;
17
17
  resolve: import("../types/config.js").Resolve;
18
+ project: string[];
18
19
  };
19
20
  ava: {
20
21
  title: string;
@@ -405,6 +406,16 @@ export declare const Plugins: {
405
406
  args: (args: string[]) => string[];
406
407
  };
407
408
  };
409
+ 'node-modules-inspector': {
410
+ title: string;
411
+ enablers: string[];
412
+ isEnabled: import("../types/config.js").IsPluginEnabled;
413
+ config: string[];
414
+ args: {
415
+ binaries: string[];
416
+ config: boolean;
417
+ };
418
+ };
408
419
  nodemon: {
409
420
  title: string;
410
421
  args: {
@@ -599,6 +610,13 @@ export declare const Plugins: {
599
610
  config: string[];
600
611
  resolveConfig: import("../types/config.js").ResolveConfig<import("./rsbuild/types.js").RsbuildConfig>;
601
612
  };
613
+ rslib: {
614
+ title: string;
615
+ enablers: string[];
616
+ isEnabled: import("../types/config.js").IsPluginEnabled;
617
+ entry: string[];
618
+ resolveConfig: import("../types/config.js").ResolveConfig<import("./rslib/types.js").RslibConfig>;
619
+ };
602
620
  rspack: {
603
621
  title: string;
604
622
  enablers: string[];
@@ -770,7 +788,7 @@ export declare const Plugins: {
770
788
  enablers: string[];
771
789
  isEnabled: import("../types/config.js").IsPluginEnabled;
772
790
  config: string[];
773
- resolveConfig: import("../types/config.js").ResolveConfig<import("type-fest").TsConfigJson>;
791
+ resolveConfig: import("../types/config.js").ResolveConfig<import("../types/tsconfig-json.js").TsConfigJson>;
774
792
  args: {
775
793
  binaries: string[];
776
794
  string: string[];
@@ -48,6 +48,7 @@ import { default as nanoStaged } from './nano-staged/index.js';
48
48
  import { default as nest } from './nest/index.js';
49
49
  import { default as netlify } from './netlify/index.js';
50
50
  import { default as next } from './next/index.js';
51
+ import { default as nodeModulesInspector } from './node-modules-inspector/index.js';
51
52
  import { default as node } from './node/index.js';
52
53
  import { default as nodemon } from './nodemon/index.js';
53
54
  import { default as npmPackageJsonLint } from './npm-package-json-lint/index.js';
@@ -72,6 +73,7 @@ import { default as remark } from './remark/index.js';
72
73
  import { default as remix } from './remix/index.js';
73
74
  import { default as rollup } from './rollup/index.js';
74
75
  import { default as rsbuild } from './rsbuild/index.js';
76
+ import { default as rslib } from './rslib/index.js';
75
77
  import { default as rspack } from './rspack/index.js';
76
78
  import { default as semanticRelease } from './semantic-release/index.js';
77
79
  import { default as sentry } from './sentry/index.js';
@@ -159,6 +161,7 @@ export const Plugins = {
159
161
  netlify,
160
162
  next,
161
163
  node,
164
+ 'node-modules-inspector': nodeModulesInspector,
162
165
  nodemon,
163
166
  'npm-package-json-lint': npmPackageJsonLint,
164
167
  nuxt,
@@ -182,6 +185,7 @@ export const Plugins = {
182
185
  remix,
183
186
  rollup,
184
187
  rsbuild,
188
+ rslib,
185
189
  rspack,
186
190
  'semantic-release': semanticRelease,
187
191
  sentry,
@@ -9,6 +9,8 @@ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
9
9
  const gitHookPaths = getGitHookPaths();
10
10
  const config = ['lefthook.yml', ...gitHookPaths];
11
11
  const resolveConfig = async (localConfig, options) => {
12
+ if (options.isProduction)
13
+ return [];
12
14
  const { manifest, configFileName, cwd, getInputsFromScripts } = options;
13
15
  const inputs = manifest.devDependencies ? Object.keys(manifest.devDependencies).map(id => toDependency(id)) : [];
14
16
  if (extname(configFileName) === '.yml') {
@@ -0,0 +1,12 @@
1
+ import type { IsPluginEnabled } from '../../types/config.js';
2
+ declare const _default: {
3
+ title: string;
4
+ enablers: string[];
5
+ isEnabled: IsPluginEnabled;
6
+ config: string[];
7
+ args: {
8
+ binaries: string[];
9
+ config: boolean;
10
+ };
11
+ };
12
+ export default _default;
@@ -0,0 +1,17 @@
1
+ import { toUnconfig } from '../../util/plugin-config.js';
2
+ import { hasDependency } from '../../util/plugin.js';
3
+ const title = 'node-modules-inspector';
4
+ const enablers = ['node-modules-inspector'];
5
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
+ const config = [...toUnconfig('node-modules-inspector.config')];
7
+ const args = {
8
+ binaries: ['node-modules-inspector'],
9
+ config: true,
10
+ };
11
+ export default {
12
+ title,
13
+ enablers,
14
+ isEnabled,
15
+ config,
16
+ args,
17
+ };
@@ -1,3 +1,4 @@
1
+ import { arrayify } from '../../util/array.js';
1
2
  import { toDeferResolve, toEntry } from '../../util/input.js';
2
3
  import { join, relative } from '../../util/path.js';
3
4
  import { hasDependency } from '../../util/plugin.js';
@@ -15,6 +16,11 @@ const toEntryPatterns = (testMatch, cwd, configDir, localConfig, rootConfig) =>
15
16
  const builtinReporters = ['dot', 'line', 'list', 'junit', 'html', 'blob', 'json', 'github'];
16
17
  export const resolveConfig = async (localConfig, options) => {
17
18
  const { cwd, configFileDir } = options;
19
+ const inputs = [];
20
+ for (const id of arrayify(localConfig.globalSetup))
21
+ inputs.push(toEntry(id));
22
+ for (const id of arrayify(localConfig.globalTeardown))
23
+ inputs.push(toEntry(id));
18
24
  const projects = localConfig.projects ? [localConfig, ...localConfig.projects] : [localConfig];
19
25
  const reporters = [localConfig.reporter].flat().flatMap(reporter => {
20
26
  const name = typeof reporter === 'string' ? reporter : reporter?.[0];
@@ -24,7 +30,8 @@ export const resolveConfig = async (localConfig, options) => {
24
30
  });
25
31
  return projects
26
32
  .flatMap(config => toEntryPatterns(config.testMatch ?? entry, cwd, configFileDir, config, localConfig))
27
- .concat(reporters.map(id => toDeferResolve(id)));
33
+ .concat(reporters.map(id => toDeferResolve(id)))
34
+ .concat(inputs);
28
35
  };
29
36
  const args = {
30
37
  binaries: ['playwright'],
@@ -1,27 +1,31 @@
1
1
  type LiteralUnion<T extends U, U = string> = T | (U & {
2
2
  zz_IGNORE_ME?: never;
3
3
  });
4
- type ReporterDescription = Readonly<['blob'] | ['blob', {
4
+ type BlobReporterOptions = {
5
5
  outputDir?: string;
6
6
  fileName?: string;
7
- }] | ['dot'] | ['line'] | ['list'] | ['list', {
7
+ };
8
+ type ListReporterOptions = {
8
9
  printSteps?: boolean;
9
- }] | ['github'] | ['junit'] | ['junit', {
10
+ };
11
+ type JUnitReporterOptions = {
10
12
  outputFile?: string;
11
13
  stripANSIControlSequences?: boolean;
12
14
  includeProjectInTestName?: boolean;
13
- }] | ['json'] | ['json', {
15
+ };
16
+ type JsonReporterOptions = {
14
17
  outputFile?: string;
15
- }] | ['html'] | [
16
- 'html',
17
- {
18
- outputFolder?: string;
19
- open?: 'always' | 'never' | 'on-failure';
20
- host?: string;
21
- port?: number;
22
- attachmentsBaseURL?: string;
23
- }
24
- ] | ['null'] | [string] | [string, any]>;
18
+ };
19
+ type HtmlReporterOptions = {
20
+ outputFolder?: string;
21
+ open?: 'always' | 'never' | 'on-failure';
22
+ host?: string;
23
+ port?: number;
24
+ attachmentsBaseURL?: string;
25
+ title?: string;
26
+ noSnippets?: boolean;
27
+ };
28
+ type ReporterDescription = Readonly<['blob'] | ['blob', BlobReporterOptions] | ['dot'] | ['line'] | ['list'] | ['list', ListReporterOptions] | ['github'] | ['junit'] | ['junit', JUnitReporterOptions] | ['json'] | ['json', JsonReporterOptions] | ['html'] | ['html', HtmlReporterOptions] | ['null'] | [string] | [string, any]>;
25
29
  type Project = {
26
30
  name: string;
27
31
  use: string;
@@ -32,5 +36,7 @@ export type PlaywrightTestConfig = {
32
36
  testMatch?: string | RegExp | (string | RegExp)[];
33
37
  testDir?: string;
34
38
  reporter?: LiteralUnion<'dot' | 'line' | 'list' | 'junit' | 'html' | 'json' | 'github' | 'null', string> | ReporterDescription[];
39
+ globalSetup?: string | Array<string>;
40
+ globalTeardown?: string | Array<string>;
35
41
  };
36
42
  export {};