@macrulez/devtoolz 0.1.0 → 0.2.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 (129) hide show
  1. package/README.md +164 -3
  2. package/dist/cli.js +233 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/circular-imports/core.d.ts +15 -0
  5. package/dist/commands/circular-imports/core.js +95 -0
  6. package/dist/commands/circular-imports/core.js.map +1 -0
  7. package/dist/commands/circular-imports/report.d.ts +3 -0
  8. package/dist/commands/circular-imports/report.js +41 -0
  9. package/dist/commands/circular-imports/report.js.map +1 -0
  10. package/dist/commands/circular-imports/run.d.ts +19 -0
  11. package/dist/commands/circular-imports/run.js +29 -0
  12. package/dist/commands/circular-imports/run.js.map +1 -0
  13. package/dist/commands/dead-exports/core.d.ts +1 -1
  14. package/dist/commands/dead-exports/core.js +2 -2
  15. package/dist/commands/dead-exports/core.js.map +1 -1
  16. package/dist/commands/dead-exports/entry.d.ts +0 -1
  17. package/dist/commands/dead-exports/entry.js +1 -14
  18. package/dist/commands/dead-exports/entry.js.map +1 -1
  19. package/dist/commands/dead-exports/run.js +3 -2
  20. package/dist/commands/dead-exports/run.js.map +1 -1
  21. package/dist/commands/empty-catch/core.d.ts +8 -0
  22. package/dist/commands/empty-catch/core.js +61 -0
  23. package/dist/commands/empty-catch/core.js.map +1 -0
  24. package/dist/commands/empty-catch/report.d.ts +3 -0
  25. package/dist/commands/empty-catch/report.js +27 -0
  26. package/dist/commands/empty-catch/report.js.map +1 -0
  27. package/dist/commands/empty-catch/run.d.ts +17 -0
  28. package/dist/commands/empty-catch/run.js +34 -0
  29. package/dist/commands/empty-catch/run.js.map +1 -0
  30. package/dist/commands/empty-catch/vue.d.ts +2 -0
  31. package/dist/commands/empty-catch/vue.js +16 -0
  32. package/dist/commands/empty-catch/vue.js.map +1 -0
  33. package/dist/commands/orphan-tests/core.d.ts +9 -0
  34. package/dist/commands/orphan-tests/core.js +42 -0
  35. package/dist/commands/orphan-tests/core.js.map +1 -0
  36. package/dist/commands/orphan-tests/report.d.ts +3 -0
  37. package/dist/commands/orphan-tests/report.js +30 -0
  38. package/dist/commands/orphan-tests/report.js.map +1 -0
  39. package/dist/commands/orphan-tests/run.d.ts +25 -0
  40. package/dist/commands/orphan-tests/run.js +55 -0
  41. package/dist/commands/orphan-tests/run.js.map +1 -0
  42. package/dist/commands/readme-check/run.js +8 -3
  43. package/dist/commands/readme-check/run.js.map +1 -1
  44. package/dist/commands/scripts-check/core.d.ts +18 -0
  45. package/dist/commands/scripts-check/core.js +121 -0
  46. package/dist/commands/scripts-check/core.js.map +1 -0
  47. package/dist/commands/scripts-check/report.d.ts +3 -0
  48. package/dist/commands/scripts-check/report.js +34 -0
  49. package/dist/commands/scripts-check/report.js.map +1 -0
  50. package/dist/commands/scripts-check/run.d.ts +15 -0
  51. package/dist/commands/scripts-check/run.js +81 -0
  52. package/dist/commands/scripts-check/run.js.map +1 -0
  53. package/dist/commands/stale-ts-ignore/check.d.ts +23 -0
  54. package/dist/commands/stale-ts-ignore/check.js +104 -0
  55. package/dist/commands/stale-ts-ignore/check.js.map +1 -0
  56. package/dist/commands/stale-ts-ignore/core.d.ts +11 -0
  57. package/dist/commands/stale-ts-ignore/core.js +42 -0
  58. package/dist/commands/stale-ts-ignore/core.js.map +1 -0
  59. package/dist/commands/stale-ts-ignore/report.d.ts +3 -0
  60. package/dist/commands/stale-ts-ignore/report.js +30 -0
  61. package/dist/commands/stale-ts-ignore/report.js.map +1 -0
  62. package/dist/commands/stale-ts-ignore/run.d.ts +23 -0
  63. package/dist/commands/stale-ts-ignore/run.js +101 -0
  64. package/dist/commands/stale-ts-ignore/run.js.map +1 -0
  65. package/dist/commands/stale-ts-ignore/vue.d.ts +9 -0
  66. package/dist/commands/stale-ts-ignore/vue.js +16 -0
  67. package/dist/commands/stale-ts-ignore/vue.js.map +1 -0
  68. package/dist/commands/strip-comments/core.js +2 -56
  69. package/dist/commands/strip-comments/core.js.map +1 -1
  70. package/dist/commands/todo-report/core.d.ts +16 -0
  71. package/dist/commands/todo-report/core.js +112 -0
  72. package/dist/commands/todo-report/core.js.map +1 -0
  73. package/dist/commands/todo-report/report.d.ts +3 -0
  74. package/dist/commands/todo-report/report.js +31 -0
  75. package/dist/commands/todo-report/report.js.map +1 -0
  76. package/dist/commands/todo-report/run.d.ts +22 -0
  77. package/dist/commands/todo-report/run.js +41 -0
  78. package/dist/commands/todo-report/run.js.map +1 -0
  79. package/dist/commands/todo-report/vue.d.ts +2 -0
  80. package/dist/commands/todo-report/vue.js +71 -0
  81. package/dist/commands/todo-report/vue.js.map +1 -0
  82. package/dist/commands/unused-deps/config-files.d.ts +9 -0
  83. package/dist/commands/unused-deps/config-files.js +64 -0
  84. package/dist/commands/unused-deps/config-files.js.map +1 -0
  85. package/dist/commands/unused-deps/core.d.ts +25 -0
  86. package/dist/commands/unused-deps/core.js +121 -0
  87. package/dist/commands/unused-deps/core.js.map +1 -0
  88. package/dist/commands/unused-deps/disk-resolve.d.ts +11 -0
  89. package/dist/commands/unused-deps/disk-resolve.js +40 -0
  90. package/dist/commands/unused-deps/disk-resolve.js.map +1 -0
  91. package/dist/commands/unused-deps/package-name.d.ts +8 -0
  92. package/dist/commands/unused-deps/package-name.js +20 -0
  93. package/dist/commands/unused-deps/package-name.js.map +1 -0
  94. package/dist/commands/unused-deps/report.d.ts +3 -0
  95. package/dist/commands/unused-deps/report.js +32 -0
  96. package/dist/commands/unused-deps/report.js.map +1 -0
  97. package/dist/commands/unused-deps/run.d.ts +18 -0
  98. package/dist/commands/unused-deps/run.js +68 -0
  99. package/dist/commands/unused-deps/run.js.map +1 -0
  100. package/dist/index.d.ts +51 -5
  101. package/dist/index.js +33 -3
  102. package/dist/index.js.map +1 -1
  103. package/dist/utils/escape-regexp.d.ts +1 -0
  104. package/dist/utils/escape-regexp.js +4 -0
  105. package/dist/utils/escape-regexp.js.map +1 -0
  106. package/dist/utils/find-comments.d.ts +10 -0
  107. package/dist/utils/find-comments.js +62 -0
  108. package/dist/utils/find-comments.js.map +1 -0
  109. package/dist/utils/find-package-dir.d.ts +2 -0
  110. package/dist/utils/find-package-dir.js +15 -0
  111. package/dist/utils/find-package-dir.js.map +1 -0
  112. package/dist/utils/line-of.d.ts +2 -0
  113. package/dist/utils/line-of.js +12 -0
  114. package/dist/utils/line-of.js.map +1 -0
  115. package/dist/utils/load-tsconfig.d.ts +20 -0
  116. package/dist/utils/load-tsconfig.js +33 -0
  117. package/dist/utils/load-tsconfig.js.map +1 -0
  118. package/dist/utils/parse-module.d.ts +32 -0
  119. package/dist/utils/parse-module.js +178 -0
  120. package/dist/utils/parse-module.js.map +1 -0
  121. package/dist/utils/resolve-specifier.d.ts +15 -0
  122. package/dist/utils/resolve-specifier.js +63 -0
  123. package/dist/utils/resolve-specifier.js.map +1 -0
  124. package/dist/utils/walk.js +20 -1
  125. package/dist/utils/walk.js.map +1 -1
  126. package/dist/utils/workspace.d.ts +14 -0
  127. package/dist/utils/workspace.js +101 -0
  128. package/dist/utils/workspace.js.map +1 -0
  129. package/package.json +1 -1
@@ -0,0 +1,30 @@
1
+ import { banner, cleanCelebration } from '../../format/vibes.js';
2
+ import { formatFindingsRows } from '../../format/findings-list.js';
3
+ export function renderOrphanTestsReport(report, options = {}) {
4
+ if (report.error) {
5
+ const lines = [];
6
+ if (!options.quiet && !options.plain)
7
+ lines.push(banner(), '');
8
+ lines.push(`Could not run orphan-tests: ${report.error}`);
9
+ return lines.join('\n');
10
+ }
11
+ const isClean = report.findings.length === 0;
12
+ if (options.quiet && isClean)
13
+ return '';
14
+ const lines = [];
15
+ if (!options.quiet && !options.plain)
16
+ lines.push(banner(), '');
17
+ lines.push(`Scanned ${report.filesScanned} file${report.filesScanned === 1 ? '' : 's'}.`, '');
18
+ if (isClean) {
19
+ lines.push(cleanCelebration(options));
20
+ return lines.join('\n');
21
+ }
22
+ lines.push(`${report.findings.length} orphan test${report.findings.length === 1 ? '' : 's'} found:`);
23
+ lines.push(...formatFindingsRows(report.findings.map((f) => ({
24
+ location: f.file,
25
+ name: 'orphan',
26
+ tag: `no matching source found (tried ${f.triedExtensions.join(', ')})`,
27
+ })), options));
28
+ return lines.join('\n');
29
+ }
30
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/orphan-tests/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAGlE,MAAM,UAAU,uBAAuB,CACrC,MAAyB,EACzB,UAAwB,EAAE;IAE1B,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9D,KAAK,CAAC,IAAI,CAAC,+BAA+B,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QACzD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;IAC5C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IAE9D,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,YAAY,QAAQ,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,EAAE,CAAC,CAAA;IAE7F,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CACR,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,eAAe,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CACzF,CAAA;IACD,KAAK,CAAC,IAAI,CACR,GAAG,kBAAkB,CACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,CAAC,CAAC,IAAI;QAChB,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,mCAAmC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;KACxE,CAAC,CAAC,EACH,OAAO,CACR,CACF,CAAA;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type OrphanTestFinding } from './core.js';
2
+ export interface OrphanTestsRunOptions {
3
+ paths: string[];
4
+ cwd: string;
5
+ /** which files to consider as POSSIBLE test files while walking — default: .ts,.tsx,.js,.jsx,.mjs,.cjs */
6
+ extensions?: string[];
7
+ ignoreGlobs?: string[];
8
+ respectGitignore?: boolean;
9
+ /** suffix(es) that mark a file as a test file — default: ['.test', '.spec'] */
10
+ testSuffixes?: string[];
11
+ /** extensions tried for a matching source file — default: .ts,.tsx,.js,.jsx,.mjs,.cjs,.vue */
12
+ sourceExtensions?: string[];
13
+ /** mirrored layout: source root, relative to `cwd` — must be given together with `testDir` */
14
+ sourceDir?: string;
15
+ /** mirrored layout: test root, relative to `cwd` — must be given together with `sourceDir` */
16
+ testDir?: string;
17
+ }
18
+ export interface OrphanTestsReport {
19
+ filesScanned: number;
20
+ findings: OrphanTestFinding[];
21
+ /** --source-dir/--test-dir given without its pair — a different kind of problem than any single finding */
22
+ error: string | null;
23
+ exitCode: number;
24
+ }
25
+ export declare function runOrphanTests(options: OrphanTestsRunOptions): OrphanTestsReport;
@@ -0,0 +1,55 @@
1
+ import { basename, dirname, join, relative, resolve } from 'node:path';
2
+ import { walk } from '../../utils/walk.js';
3
+ import { parseTestFile, hasMatchingSource, candidateSourceDirs, } from './core.js';
4
+ const DEFAULT_TEST_SUFFIXES = ['.test', '.spec'];
5
+ const DEFAULT_SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.vue'];
6
+ const DEFAULT_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
7
+ export function runOrphanTests(options) {
8
+ const cwd = resolve(options.cwd);
9
+ const testSuffixes = options.testSuffixes ?? DEFAULT_TEST_SUFFIXES;
10
+ const sourceExtensions = options.sourceExtensions ?? DEFAULT_SOURCE_EXTENSIONS;
11
+ const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
12
+ if (Boolean(options.sourceDir) !== Boolean(options.testDir)) {
13
+ return {
14
+ filesScanned: 0,
15
+ findings: [],
16
+ error: '--source-dir and --test-dir must be given together',
17
+ exitCode: 1,
18
+ };
19
+ }
20
+ const mirrored = Boolean(options.sourceDir && options.testDir);
21
+ const walkRoots = mirrored ? [options.testDir] : options.paths;
22
+ const testFiles = walk(walkRoots, {
23
+ cwd,
24
+ extensions,
25
+ ignoreGlobs: options.ignoreGlobs ?? [],
26
+ ...(options.respectGitignore !== undefined
27
+ ? { respectGitignore: options.respectGitignore }
28
+ : {}),
29
+ });
30
+ const testDirAbs = mirrored ? resolve(cwd, options.testDir) : null;
31
+ const sourceDirAbs = mirrored ? resolve(cwd, options.sourceDir) : null;
32
+ const findings = [];
33
+ for (const absFile of testFiles) {
34
+ const parsed = parseTestFile(basename(absFile), testSuffixes);
35
+ if (!parsed)
36
+ continue;
37
+ const found = mirrored && testDirAbs && sourceDirAbs
38
+ ? hasMatchingSource(join(sourceDirAbs, relative(testDirAbs, dirname(absFile)), parsed.base), sourceExtensions)
39
+ : candidateSourceDirs(dirname(absFile)).some((dir) => hasMatchingSource(join(dir, parsed.base), sourceExtensions));
40
+ if (found)
41
+ continue;
42
+ findings.push({
43
+ file: relative(cwd, absFile).split('\\').join('/'),
44
+ triedExtensions: sourceExtensions,
45
+ });
46
+ }
47
+ findings.sort((a, b) => a.file.localeCompare(b.file));
48
+ return {
49
+ filesScanned: testFiles.length,
50
+ findings,
51
+ error: null,
52
+ exitCode: findings.length > 0 ? 1 : 0,
53
+ };
54
+ }
55
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/orphan-tests/run.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,20 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
3
  import { checkMarkdownFile } from './core.js';
4
- import { loadCompilerOptions } from './tsconfig.js';
4
+ import { loadTsconfig } from '../../utils/load-tsconfig.js';
5
5
  import { DEFAULT_LANGS } from './lang.js';
6
6
  export function runReadmeCheck(options) {
7
7
  const packageDir = resolve(options.dir);
8
8
  const targetFiles = options.files && options.files.length > 0 ? options.files : ['README.md'];
9
9
  const langs = options.langs && options.langs.length > 0 ? options.langs : DEFAULT_LANGS;
10
- const loaded = loadCompilerOptions(packageDir, options.tsconfig);
10
+ const loaded = loadTsconfig(packageDir, options.tsconfig);
11
11
  if ('error' in loaded) {
12
- return { fileResults: [], findings: [], error: loaded.error, exitCode: 1 };
12
+ return {
13
+ fileResults: [],
14
+ findings: [],
15
+ error: `${loaded.error} — nothing to typecheck README code blocks against`,
16
+ exitCode: 1,
17
+ };
13
18
  }
14
19
  const fileResults = [];
15
20
  for (const relFile of targetFiles) {
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/readme-check/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,iBAAiB,EAAuD,MAAM,WAAW,CAAA;AAClG,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAqBzC,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACvC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IAC7F,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAA;IAEvF,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IAChE,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;IAC5E,CAAC;IAED,MAAM,WAAW,GAA4B,EAAE,CAAA;IAC/C,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAC5C,IAAI,QAAgB,CAAA;QACpB,IAAI,CAAC;YACH,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,WAAW,EAAE,EAAE;gBACf,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,kBAAkB,OAAO,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBACvF,QAAQ,EAAE,CAAC;aACZ,CAAA;QACH,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;IAC3F,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACvD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACtF,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/readme-check/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,iBAAiB,EAAuD,MAAM,WAAW,CAAA;AAClG,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAqBzC,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACvC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IAC7F,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAA;IAEvF,MAAM,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IACzD,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;QACtB,OAAO;YACL,WAAW,EAAE,EAAE;YACf,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,oDAAoD;YAC1E,QAAQ,EAAE,CAAC;SACZ,CAAA;IACH,CAAC;IAED,MAAM,WAAW,GAA4B,EAAE,CAAA;IAC/C,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAC5C,IAAI,QAAgB,CAAA;QACpB,IAAI,CAAC;YACH,QAAQ,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,WAAW,EAAE,EAAE;gBACf,QAAQ,EAAE,EAAE;gBACZ,KAAK,EAAE,kBAAkB,OAAO,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBACvF,QAAQ,EAAE,CAAC;aACZ,CAAA;QACH,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;IAC3F,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACvD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACtF,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface ScriptsCheckFinding {
2
+ kind: 'missing' | 'undocumented';
3
+ name: string;
4
+ file: string;
5
+ line: number;
6
+ }
7
+ export interface ScriptSource {
8
+ file: string;
9
+ text: string;
10
+ }
11
+ export declare function maskOutOfScopeCiSteps(text: string): string;
12
+ export declare function extractMentionedScripts(text: string): {
13
+ name: string;
14
+ index: number;
15
+ }[];
16
+ export declare function isScriptMentioned(name: string, text: string): boolean;
17
+ export declare function isReservedLifecycleScript(name: string, allNames: Set<string>): boolean;
18
+ export declare function analyzeScriptsCheck(scripts: Record<string, string>, packageJsonFile: string, packageJsonText: string, sources: ScriptSource[]): ScriptsCheckFinding[];
@@ -0,0 +1,121 @@
1
+ import { escapeRegExp } from '../../utils/escape-regexp.js';
2
+ import { lineOf } from '../../utils/line-of.js';
3
+ // npm's own no-`run`-needed aliases — the ONLY bare `npm <word>` forms
4
+ // that unambiguously mean "run this script". Any other bare word after
5
+ // `npm` is a real npm subcommand (`npm install`, `npm publish`, ...), not
6
+ // a script invocation.
7
+ const NPM_BARE_ALIASES = new Set(['test', 'start']);
8
+ // Forms unambiguous enough to EXTRACT an arbitrary script name from —
9
+ // each requires an explicit `run`/`run-script`, or is one of npm's own
10
+ // bare aliases above, so there's no risk of misreading an unrelated
11
+ // subcommand (`yarn add`, `pnpm install`) as a script name. Used for
12
+ // direction 1 (finding a mention of a script that doesn't exist).
13
+ const EXTRACT_PATTERNS = [
14
+ /\bnpm\s+run(?:-script)?\s+([\w:./@-]+)/g,
15
+ /\byarn\s+run\s+([\w:./@-]+)/g,
16
+ /\bpnpm\s+run\s+([\w:./@-]+)/g,
17
+ /\b(?:npm|yarn|pnpm)\s+(test|start)\b/g,
18
+ ];
19
+ // A GitHub Actions step with its own `working-directory:` runs against a
20
+ // DIFFERENT package.json (a `demo/` subproject, a workspace package) —
21
+ // found for real while dogfooding against vue-virtual-scroller-kit: its
22
+ // `e2e` job runs `npm run test:e2e` under `working-directory: demo`,
23
+ // where that script genuinely exists in `demo/package.json`, but not in
24
+ // the root one this command checks. No real YAML parsing here (same
25
+ // text-scan-not-AST spirit as everything else in this command) — a step
26
+ // boundary is approximated as everything within a few lines of a
27
+ // `working-directory:` line, which is blanked out (same length, so line
28
+ // numbers for anything NOT blanked stay correct) before either direction
29
+ // gets to look at it.
30
+ const WORKING_DIRECTORY_RE = /^\s*working-directory\s*:/;
31
+ const STEP_SCOPE_WINDOW = 3;
32
+ export function maskOutOfScopeCiSteps(text) {
33
+ const lines = text.split('\n');
34
+ const hasWorkingDir = lines.map((l) => WORKING_DIRECTORY_RE.test(l));
35
+ if (!hasWorkingDir.some(Boolean))
36
+ return text;
37
+ return lines
38
+ .map((line, i) => {
39
+ const start = Math.max(0, i - STEP_SCOPE_WINDOW);
40
+ const end = Math.min(lines.length - 1, i + STEP_SCOPE_WINDOW);
41
+ for (let j = start; j <= end; j++) {
42
+ if (hasWorkingDir[j])
43
+ return line.replace(/./g, 'x');
44
+ }
45
+ return line;
46
+ })
47
+ .join('\n');
48
+ }
49
+ export function extractMentionedScripts(text) {
50
+ const mentions = [];
51
+ for (const pattern of EXTRACT_PATTERNS) {
52
+ pattern.lastIndex = 0;
53
+ let match;
54
+ while ((match = pattern.exec(text))) {
55
+ mentions.push({ name: match[1], index: match.index });
56
+ }
57
+ }
58
+ return mentions;
59
+ }
60
+ // Direction 2 (is an ALREADY-KNOWN script name mentioned anywhere) can
61
+ // afford to also accept yarn/pnpm's own bare `<manager> <name>` form —
62
+ // real for those two package managers, unlike plain npm — since we're
63
+ // testing one specific known name, not extracting an arbitrary one out
64
+ // of free text, so a stray `yarn add`/`pnpm install` can't be misread as
65
+ // a match for a script actually named "add"/"install" (vanishingly rare
66
+ // in practice, and a false NEGATIVE here — reported as undocumented when
67
+ // it technically isn't — is the safe direction for a weak signal).
68
+ export function isScriptMentioned(name, text) {
69
+ const n = escapeRegExp(name);
70
+ const pattern = NPM_BARE_ALIASES.has(name)
71
+ ? new RegExp(`\\b(?:npm|yarn|pnpm)(?:\\s+run(?:-script)?)?\\s+${n}\\b`)
72
+ : new RegExp(`\\b(?:npm\\s+run(?:-script)?|yarn(?:\\s+run)?|pnpm(?:\\s+run)?)\\s+${n}\\b`);
73
+ return pattern.test(text);
74
+ }
75
+ // npm auto-runs `pre<X>`/`post<X>` around either another declared script
76
+ // or one of npm's own built-in lifecycle events — documenting them "for
77
+ // a human" is pointless, npm calls them itself. `prepublishOnly`,
78
+ // `preinstall`, `postinstall`, `prepare` are npm's own implicit events
79
+ // (no peer script named `install`/`publishOnly` need exist for these to
80
+ // fire), so they're a fixed exemption; any other `pre*`/`post*` is only
81
+ // exempt when its own peer script is actually declared.
82
+ const RESERVED_LIFECYCLE_NAMES = new Set(['prepublishOnly', 'preinstall', 'postinstall', 'prepare']);
83
+ export function isReservedLifecycleScript(name, allNames) {
84
+ if (RESERVED_LIFECYCLE_NAMES.has(name))
85
+ return true;
86
+ const pre = /^pre(.+)/.exec(name);
87
+ if (pre && allNames.has(pre[1]))
88
+ return true;
89
+ const post = /^post(.+)/.exec(name);
90
+ if (post && allNames.has(post[1]))
91
+ return true;
92
+ return false;
93
+ }
94
+ export function analyzeScriptsCheck(scripts, packageJsonFile, packageJsonText, sources) {
95
+ const scriptNames = new Set(Object.keys(scripts));
96
+ const findings = [];
97
+ const reportedMissing = new Set();
98
+ for (const source of sources) {
99
+ for (const { name, index } of extractMentionedScripts(source.text)) {
100
+ if (scriptNames.has(name))
101
+ continue;
102
+ const key = `${source.file}:${name}`;
103
+ if (reportedMissing.has(key))
104
+ continue;
105
+ reportedMissing.add(key);
106
+ findings.push({ kind: 'missing', name, file: source.file, line: lineOf(source.text, index) });
107
+ }
108
+ }
109
+ for (const name of scriptNames) {
110
+ if (isReservedLifecycleScript(name, scriptNames))
111
+ continue;
112
+ const mentioned = sources.some((s) => isScriptMentioned(name, s.text));
113
+ if (mentioned)
114
+ continue;
115
+ const keyMatch = new RegExp(`"${escapeRegExp(name)}"\\s*:`).exec(packageJsonText);
116
+ const line = keyMatch ? lineOf(packageJsonText, keyMatch.index) : 1;
117
+ findings.push({ kind: 'undocumented', name, file: packageJsonFile, line });
118
+ }
119
+ return findings;
120
+ }
121
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/scripts-check/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type VibesOptions } from '../../format/vibes.js';
2
+ import type { ScriptsCheckReport } from './run.js';
3
+ export declare function renderScriptsCheckReport(report: ScriptsCheckReport, options?: VibesOptions): string;
@@ -0,0 +1,34 @@
1
+ import { banner, cleanCelebration } from '../../format/vibes.js';
2
+ import { formatFindingsRows } from '../../format/findings-list.js';
3
+ const KIND_TAG = {
4
+ missing: 'mentioned here, but not in package.json scripts',
5
+ undocumented: 'in package.json scripts, but not mentioned anywhere checked',
6
+ };
7
+ export function renderScriptsCheckReport(report, options = {}) {
8
+ if (report.error) {
9
+ const lines = [];
10
+ if (!options.quiet && !options.plain)
11
+ lines.push(banner(), '');
12
+ lines.push(`Could not run scripts-check: ${report.error}`);
13
+ return lines.join('\n');
14
+ }
15
+ const isClean = report.findings.length === 0;
16
+ if (options.quiet && isClean)
17
+ return '';
18
+ const lines = [];
19
+ if (!options.quiet && !options.plain)
20
+ lines.push(banner(), '');
21
+ lines.push(`Checked ${report.sourcesScanned.length} source${report.sourcesScanned.length === 1 ? '' : 's'} against package.json's scripts.`, '');
22
+ if (isClean) {
23
+ lines.push(cleanCelebration(options));
24
+ return lines.join('\n');
25
+ }
26
+ lines.push(`${report.findings.length} problem${report.findings.length === 1 ? '' : 's'} found:`);
27
+ lines.push(...formatFindingsRows(report.findings.map((f) => ({
28
+ location: `${f.file}:${f.line}`,
29
+ name: f.name,
30
+ tag: KIND_TAG[f.kind] ?? f.kind,
31
+ })), options));
32
+ return lines.join('\n');
33
+ }
34
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/scripts-check/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAqB,MAAM,uBAAuB,CAAA;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAGlE,MAAM,QAAQ,GAA2B;IACvC,OAAO,EAAE,iDAAiD;IAC1D,YAAY,EAAE,6DAA6D;CAC5E,CAAA;AAED,MAAM,UAAU,wBAAwB,CACtC,MAA0B,EAC1B,UAAwB,EAAE;IAE1B,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;QAC9D,KAAK,CAAC,IAAI,CAAC,gCAAgC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;IAC5C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO;QAAE,OAAO,EAAE,CAAA;IAEvC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IAE9D,KAAK,CAAC,IAAI,CACR,WAAW,MAAM,CAAC,cAAc,CAAC,MAAM,UAAU,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,kCAAkC,EAChI,EAAE,CACH,CAAA;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAA;QACrC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,WAAW,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;IAChG,KAAK,CAAC,IAAI,CACR,GAAG,kBAAkB,CACnB,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1B,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE;QAC/B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI;KAChC,CAAC,CAAC,EACH,OAAO,CACR,CACF,CAAA;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type ScriptsCheckFinding } from './core.js';
2
+ export interface ScriptsCheckRunOptions {
3
+ /** package directory to check — package.json, --file docs, and .github/workflows are all resolved from here */
4
+ dir: string;
5
+ /** markdown/doc files to check, relative to `dir` — default: ['README.md'] */
6
+ files?: string[];
7
+ }
8
+ export interface ScriptsCheckReport {
9
+ findings: ScriptsCheckFinding[];
10
+ sourcesScanned: string[];
11
+ /** package.json or an explicitly-requested doc file couldn't be read at all — a different kind of problem than any single finding */
12
+ error: string | null;
13
+ exitCode: number;
14
+ }
15
+ export declare function runScriptsCheck(options: ScriptsCheckRunOptions): ScriptsCheckReport;
@@ -0,0 +1,81 @@
1
+ import { readFileSync, readdirSync } from 'node:fs';
2
+ import { resolve, join } from 'node:path';
3
+ import { analyzeScriptsCheck, maskOutOfScopeCiSteps, } from './core.js';
4
+ function readWorkflowSources(packageDir) {
5
+ let entries;
6
+ try {
7
+ entries = readdirSync(join(packageDir, '.github', 'workflows'));
8
+ }
9
+ catch {
10
+ return [];
11
+ }
12
+ const sources = [];
13
+ for (const entry of entries) {
14
+ if (!/\.ya?ml$/.test(entry))
15
+ continue;
16
+ const relFile = `.github/workflows/${entry}`;
17
+ try {
18
+ const text = maskOutOfScopeCiSteps(readFileSync(join(packageDir, relFile), 'utf8'));
19
+ sources.push({ file: relFile, text });
20
+ }
21
+ catch {
22
+ // unreadable — skip rather than fail the whole command over one file
23
+ }
24
+ }
25
+ return sources;
26
+ }
27
+ export function runScriptsCheck(options) {
28
+ const packageDir = resolve(options.dir);
29
+ let packageJsonText;
30
+ try {
31
+ packageJsonText = readFileSync(join(packageDir, 'package.json'), 'utf8');
32
+ }
33
+ catch (err) {
34
+ return {
35
+ findings: [],
36
+ sourcesScanned: [],
37
+ error: `could not read package.json: ${err instanceof Error ? err.message : String(err)}`,
38
+ exitCode: 1,
39
+ };
40
+ }
41
+ let pkg;
42
+ try {
43
+ pkg = JSON.parse(packageJsonText);
44
+ }
45
+ catch (err) {
46
+ return {
47
+ findings: [],
48
+ sourcesScanned: [],
49
+ error: `could not parse package.json: ${err instanceof Error ? err.message : String(err)}`,
50
+ exitCode: 1,
51
+ };
52
+ }
53
+ const scripts = pkg.scripts ?? {};
54
+ const docFiles = options.files && options.files.length > 0 ? options.files : ['README.md'];
55
+ const sources = [];
56
+ for (const relFile of docFiles) {
57
+ let text;
58
+ try {
59
+ text = readFileSync(join(packageDir, relFile), 'utf8');
60
+ }
61
+ catch (err) {
62
+ return {
63
+ findings: [],
64
+ sourcesScanned: [],
65
+ error: `could not read ${relFile}: ${err instanceof Error ? err.message : String(err)}`,
66
+ exitCode: 1,
67
+ };
68
+ }
69
+ sources.push({ file: relFile, text });
70
+ }
71
+ sources.push(...readWorkflowSources(packageDir));
72
+ const findings = analyzeScriptsCheck(scripts, 'package.json', packageJsonText, sources);
73
+ findings.sort((a, b) => a.kind.localeCompare(b.kind) || a.name.localeCompare(b.name));
74
+ return {
75
+ findings,
76
+ sourcesScanned: sources.map((s) => s.file),
77
+ error: null,
78
+ exitCode: findings.length > 0 ? 1 : 0,
79
+ };
80
+ }
81
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/scripts-check/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import ts from 'typescript';
2
+ export declare function normalize(fileName: string): string;
3
+ /**
4
+ * One real `ts.createProgram` run over `rootNames`, with `overrides`
5
+ * (absolute path → replacement source text) substituted in for whichever
6
+ * of those files it names — every other file resolves against the real
7
+ * filesystem via `ts.createCompilerHost`. Returns every diagnostic
8
+ * grouped by file and 1-based line, which is all `run.ts` ever needs:
9
+ * whether SOME diagnostic landed on a specific line, not its message.
10
+ */
11
+ export declare function runProjectTypecheck(rootNames: string[], options: ts.CompilerOptions, overrides?: Map<string, string>): Map<string, Set<number>>;
12
+ /**
13
+ * Typechecks a single piece of source IN ISOLATION, against the real
14
+ * package's real types on disk (relative/self-referencing imports both
15
+ * resolve normally) — same virtual-single-file technique as
16
+ * `readme-check`'s `typecheckBlock`, reused here for `.vue` files, which
17
+ * a plain `ts.Program` can't include in a whole-project run at all (no
18
+ * SFC support without pulling in `vue-tsc`'s own machinery). This misses
19
+ * diagnostics that would only appear from OTHER files' real usage of
20
+ * this one — an accepted, documented gap, same class as `readme-check`'s
21
+ * own isolated-block limitation.
22
+ */
23
+ export declare function checkIsolatedFile(virtualFileName: string, code: string, baseOptions: ts.CompilerOptions): Set<number>;
@@ -0,0 +1,104 @@
1
+ import ts from 'typescript';
2
+ // TypeScript normalizes every file path it hands to a `CompilerHost` to
3
+ // forward slashes internally, even on Windows — matching against a
4
+ // `path`-built key (backslashes on win32) would silently never hit these
5
+ // overrides. Same gotcha `readme-check`'s own `typecheck.ts` documents.
6
+ export function normalize(fileName) {
7
+ return fileName.replace(/\\/g, '/');
8
+ }
9
+ /**
10
+ * One real `ts.createProgram` run over `rootNames`, with `overrides`
11
+ * (absolute path → replacement source text) substituted in for whichever
12
+ * of those files it names — every other file resolves against the real
13
+ * filesystem via `ts.createCompilerHost`. Returns every diagnostic
14
+ * grouped by file and 1-based line, which is all `run.ts` ever needs:
15
+ * whether SOME diagnostic landed on a specific line, not its message.
16
+ */
17
+ export function runProjectTypecheck(rootNames, options, overrides) {
18
+ const checkOptions = { ...options, noEmit: true, skipLibCheck: true };
19
+ const baseHost = ts.createCompilerHost(checkOptions);
20
+ const host = overrides
21
+ ? {
22
+ ...baseHost,
23
+ getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) {
24
+ const override = overrides.get(normalize(fileName));
25
+ if (override !== undefined) {
26
+ const version = typeof languageVersionOrOptions === 'object'
27
+ ? languageVersionOrOptions.languageVersion
28
+ : languageVersionOrOptions;
29
+ return ts.createSourceFile(fileName, override, version, true);
30
+ }
31
+ return baseHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
32
+ },
33
+ readFile(fileName) {
34
+ const override = overrides.get(normalize(fileName));
35
+ if (override !== undefined)
36
+ return override;
37
+ return baseHost.readFile(fileName);
38
+ },
39
+ }
40
+ : baseHost;
41
+ const program = ts.createProgram({ rootNames, options: checkOptions, host });
42
+ const diagnostics = ts.getPreEmitDiagnostics(program);
43
+ const byFile = new Map();
44
+ for (const d of diagnostics) {
45
+ if (!d.file || d.start === undefined)
46
+ continue;
47
+ const line = d.file.getLineAndCharacterOfPosition(d.start).line + 1;
48
+ const key = normalize(d.file.fileName);
49
+ let lines = byFile.get(key);
50
+ if (!lines) {
51
+ lines = new Set();
52
+ byFile.set(key, lines);
53
+ }
54
+ lines.add(line);
55
+ }
56
+ return byFile;
57
+ }
58
+ /**
59
+ * Typechecks a single piece of source IN ISOLATION, against the real
60
+ * package's real types on disk (relative/self-referencing imports both
61
+ * resolve normally) — same virtual-single-file technique as
62
+ * `readme-check`'s `typecheckBlock`, reused here for `.vue` files, which
63
+ * a plain `ts.Program` can't include in a whole-project run at all (no
64
+ * SFC support without pulling in `vue-tsc`'s own machinery). This misses
65
+ * diagnostics that would only appear from OTHER files' real usage of
66
+ * this one — an accepted, documented gap, same class as `readme-check`'s
67
+ * own isolated-block limitation.
68
+ */
69
+ export function checkIsolatedFile(virtualFileName, code, baseOptions) {
70
+ const options = { ...baseOptions, noEmit: true, skipLibCheck: true };
71
+ const baseHost = ts.createCompilerHost(options);
72
+ const virtualSourceFile = ts.createSourceFile(virtualFileName, code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
73
+ const host = {
74
+ ...baseHost,
75
+ getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) {
76
+ if (fileName === virtualFileName)
77
+ return virtualSourceFile;
78
+ return baseHost.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
79
+ },
80
+ fileExists(fileName) {
81
+ if (fileName === virtualFileName)
82
+ return true;
83
+ return baseHost.fileExists(fileName);
84
+ },
85
+ readFile(fileName) {
86
+ if (fileName === virtualFileName)
87
+ return code;
88
+ return baseHost.readFile(fileName);
89
+ },
90
+ writeFile() { },
91
+ };
92
+ const program = ts.createProgram({ rootNames: [virtualFileName], options, host });
93
+ const diagnostics = ts
94
+ .getPreEmitDiagnostics(program)
95
+ .filter((d) => d.file?.fileName === virtualFileName);
96
+ const lines = new Set();
97
+ for (const d of diagnostics) {
98
+ if (d.start === undefined || !d.file)
99
+ continue;
100
+ lines.add(d.file.getLineAndCharacterOfPosition(d.start).line + 1);
101
+ }
102
+ return lines;
103
+ }
104
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/commands/stale-ts-ignore/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import ts from 'typescript';
2
+ import { type Range } from '../../utils/find-comments.js';
3
+ export interface TsIgnoreDirective {
4
+ /** 1-based line the `// @ts-ignore` comment itself sits on */
5
+ line: number;
6
+ /** 1-based line it's meant to suppress a diagnostic on — line + 1, unconditionally */
7
+ targetLine: number;
8
+ range: Range;
9
+ }
10
+ export declare function findTsIgnoreDirectives(text: string, sf: ts.SourceFile): TsIgnoreDirective[];
11
+ export declare function blankDirectives(text: string, directives: TsIgnoreDirective[]): string;