@xylabs/ts-scripts-yarn3 7.4.2 → 7.4.3

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 (35) hide show
  1. package/dist/actions/deplint/checkPackage/checkPackage.mjs +82 -89
  2. package/dist/actions/deplint/checkPackage/checkPackage.mjs.map +1 -1
  3. package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs +5 -5
  4. package/dist/actions/deplint/checkPackage/getUnlistedDevDependencies.mjs.map +1 -1
  5. package/dist/actions/deplint/checkPackage/getUnusedDependencies.mjs +2 -2
  6. package/dist/actions/deplint/checkPackage/getUnusedDependencies.mjs.map +1 -1
  7. package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs +7 -10
  8. package/dist/actions/deplint/checkPackage/getUnusedDevDependencies.mjs.map +1 -1
  9. package/dist/actions/deplint/checkPackage/index.mjs +82 -89
  10. package/dist/actions/deplint/checkPackage/index.mjs.map +1 -1
  11. package/dist/actions/deplint/deplint.mjs +82 -89
  12. package/dist/actions/deplint/deplint.mjs.map +1 -1
  13. package/dist/actions/deplint/findFiles.mjs +29 -14
  14. package/dist/actions/deplint/findFiles.mjs.map +1 -1
  15. package/dist/actions/deplint/findFilesByGlob.mjs +7 -2
  16. package/dist/actions/deplint/findFilesByGlob.mjs.map +1 -1
  17. package/dist/actions/deplint/getExternalImportsFromFiles.mjs +16 -23
  18. package/dist/actions/deplint/getExternalImportsFromFiles.mjs.map +1 -1
  19. package/dist/actions/deplint/implicitDevDependencies.mjs +2 -2
  20. package/dist/actions/deplint/implicitDevDependencies.mjs.map +1 -1
  21. package/dist/actions/deplint/index.mjs +82 -89
  22. package/dist/actions/deplint/index.mjs.map +1 -1
  23. package/dist/actions/index.mjs +86 -93
  24. package/dist/actions/index.mjs.map +1 -1
  25. package/dist/bin/xy.mjs +82 -89
  26. package/dist/bin/xy.mjs.map +1 -1
  27. package/dist/index.mjs +86 -93
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/xy/index.mjs +82 -89
  30. package/dist/xy/index.mjs.map +1 -1
  31. package/dist/xy/xy.mjs +82 -89
  32. package/dist/xy/xy.mjs.map +1 -1
  33. package/dist/xy/xyLintCommands.mjs +82 -89
  34. package/dist/xy/xyLintCommands.mjs.map +1 -1
  35. package/package.json +4 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnusedDependencies.ts"],"sourcesContent":["import chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nexport function getUnusedDependencies(\n { name, location }: Workspace,\n { dependencies }: CheckPackageParams,\n {\n externalDistImports,\n externalDistTypeImports,\n externalSrcImports,\n }: CheckSourceParams,\n) {\n let unusedDependencies = 0\n for (const dep of dependencies) {\n if (!externalDistImports.includes(dep)\n && !externalDistImports.includes(dep.replace(/^@types\\//, ''))\n && !externalDistTypeImports.includes(dep)\n && !externalDistTypeImports.includes(dep.replace(/^@types\\//, ''))) {\n unusedDependencies++\n if (externalSrcImports.includes(dep)) {\n console.log(`[${chalk.blue(name)}] dependency should be devDependency in package.json: ${chalk.red(dep)}`)\n } else {\n console.log(`[${chalk.blue(name)}] Unused dependency in package.json: ${chalk.red(dep)}`)\n }\n }\n }\n if (unusedDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unusedDependencies\n}\n"],"mappings":";AAAA,OAAO,WAAW;AAKX,SAAS,sBACd,EAAE,MAAM,SAAS,GACjB,EAAE,aAAa,GACf;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF,GACA;AACA,MAAI,qBAAqB;AACzB,aAAW,OAAO,cAAc;AAC9B,QAAI,CAAC,oBAAoB,SAAS,GAAG,KAChC,CAAC,oBAAoB,SAAS,IAAI,QAAQ,aAAa,EAAE,CAAC,KAC1D,CAAC,wBAAwB,SAAS,GAAG,KACrC,CAAC,wBAAwB,SAAS,IAAI,QAAQ,aAAa,EAAE,CAAC,GAAG;AACpE;AACA,UAAI,mBAAmB,SAAS,GAAG,GAAG;AACpC,gBAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,yDAAyD,MAAM,IAAI,GAAG,CAAC,EAAE;AAAA,MAC3G,OAAO;AACL,gBAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,wCAAwC,MAAM,IAAI,GAAG,CAAC,EAAE;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AACA,MAAI,qBAAqB,GAAG;AAC1B,UAAM,kBAAkB,GAAG,QAAQ;AACnC,YAAQ,IAAI,KAAK,MAAM,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACpD;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnusedDependencies.ts"],"sourcesContent":["import chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nexport function getUnusedDependencies(\n { name, location }: Workspace,\n { dependencies }: CheckPackageParams,\n {\n externalDistImports,\n externalDistTypeImports,\n externalAllImports,\n }: CheckSourceParams,\n) {\n let unusedDependencies = 0\n for (const dep of dependencies) {\n if (!externalDistImports.includes(dep)\n && !externalDistImports.includes(dep.replace(/^@types\\//, ''))\n && !externalDistTypeImports.includes(dep)\n && !externalDistTypeImports.includes(dep.replace(/^@types\\//, ''))) {\n unusedDependencies++\n if (externalAllImports.includes(dep)) {\n console.log(`[${chalk.blue(name)}] dependency should be devDependency in package.json: ${chalk.red(dep)}`)\n } else {\n console.log(`[${chalk.blue(name)}] Unused dependency in package.json: ${chalk.red(dep)}`)\n }\n }\n }\n if (unusedDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unusedDependencies\n}\n"],"mappings":";AAAA,OAAO,WAAW;AAKX,SAAS,sBACd,EAAE,MAAM,SAAS,GACjB,EAAE,aAAa,GACf;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF,GACA;AACA,MAAI,qBAAqB;AACzB,aAAW,OAAO,cAAc;AAC9B,QAAI,CAAC,oBAAoB,SAAS,GAAG,KAChC,CAAC,oBAAoB,SAAS,IAAI,QAAQ,aAAa,EAAE,CAAC,KAC1D,CAAC,wBAAwB,SAAS,GAAG,KACrC,CAAC,wBAAwB,SAAS,IAAI,QAAQ,aAAa,EAAE,CAAC,GAAG;AACpE;AACA,UAAI,mBAAmB,SAAS,GAAG,GAAG;AACpC,gBAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,yDAAyD,MAAM,IAAI,GAAG,CAAC,EAAE;AAAA,MAC3G,OAAO;AACL,gBAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,wCAAwC,MAAM,IAAI,GAAG,CAAC,EAAE;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AACA,MAAI,qBAAqB,GAAG;AAC1B,UAAM,kBAAkB,GAAG,QAAQ;AACnC,YAAQ,IAAI,KAAK,MAAM,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACpD;AACA,SAAO;AACT;","names":[]}
@@ -101,9 +101,9 @@ function getScriptReferencedPackages(location, allDeps) {
101
101
  import fs3 from "fs";
102
102
  var hasFileWithExtension = (files, extensions) => files.some((f) => extensions.some((ext) => f.endsWith(ext)));
103
103
  var tsExtensions = [".ts", ".tsx", ".mts", ".cts"];
104
- var hasTypescriptFiles = ({ srcFiles, configFiles }) => hasFileWithExtension([...srcFiles, ...configFiles], tsExtensions);
104
+ var hasTypescriptFiles = ({ allFiles }) => hasFileWithExtension(allFiles, tsExtensions);
105
105
  var decoratorPattern = /^\s*@[a-zA-Z]\w*/m;
106
- var hasDecorators = ({ srcFiles }) => srcFiles.filter((f) => tsExtensions.some((ext) => f.endsWith(ext))).some((file) => {
106
+ var hasDecorators = ({ allFiles }) => allFiles.filter((f) => tsExtensions.some((ext) => f.endsWith(ext))).some((file) => {
107
107
  try {
108
108
  const content = fs3.readFileSync(file, "utf8");
109
109
  return decoratorPattern.test(content);
@@ -155,18 +155,15 @@ function getImplicitDevDependencies(context) {
155
155
 
156
156
  // src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
157
157
  var allExternalImports = ({
158
- externalSrcImports,
158
+ externalAllImports,
159
159
  externalDistImports,
160
- externalDistTypeImports,
161
- externalConfigImports
160
+ externalDistTypeImports
162
161
  }) => {
163
- const all = /* @__PURE__ */ new Set([
164
- ...externalSrcImports,
162
+ return /* @__PURE__ */ new Set([
163
+ ...externalAllImports,
165
164
  ...externalDistImports,
166
- ...externalDistTypeImports,
167
- ...externalConfigImports
165
+ ...externalDistTypeImports
168
166
  ]);
169
- return all;
170
167
  };
171
168
  function isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs) {
172
169
  if (implicitDeps.has(dep)) return true;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnusedDevDependencies.ts","../../../../src/actions/deplint/getRequiredPeerDependencies.ts","../../../../src/actions/deplint/getScriptReferencedPackages.ts","../../../../src/actions/deplint/getBasePackageName.ts","../../../../src/actions/deplint/implicitDevDependencies.ts"],"sourcesContent":["import chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport { getRequiredPeerDependencies } from '../getRequiredPeerDependencies.ts'\nimport { getScriptReferencedPackages } from '../getScriptReferencedPackages.ts'\nimport type { FileContext } from '../implicitDevDependencies.ts'\nimport { getImplicitDevDependencies } from '../implicitDevDependencies.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nconst allExternalImports = ({\n externalSrcImports,\n externalDistImports,\n externalDistTypeImports,\n externalConfigImports,\n}: CheckSourceParams) => {\n const all = new Set<string>([\n ...externalSrcImports,\n ...externalDistImports,\n ...externalDistTypeImports,\n ...externalConfigImports,\n ])\n return all\n}\n\nfunction isDevDepUsed(\n dep: string,\n allImports: Set<string>,\n implicitDeps: Set<string>,\n requiredPeers: Set<string>,\n scriptRefs: Set<string>,\n) {\n if (implicitDeps.has(dep)) return true\n if (requiredPeers.has(dep)) return true\n if (scriptRefs.has(dep)) return true\n\n if (dep.startsWith('@types/')) {\n const baseName = dep.replace(/^@types\\//, '')\n return allImports.has(baseName) || allImports.has(dep) || implicitDeps.has(baseName)\n }\n\n return allImports.has(dep)\n}\n\nexport function getUnusedDevDependencies(\n { name, location }: Workspace,\n {\n devDependencies, dependencies, peerDependencies,\n }: CheckPackageParams,\n sourceParams: CheckSourceParams,\n fileContext: FileContext,\n) {\n const allImports = allExternalImports(sourceParams)\n const allDeps = [...dependencies, ...devDependencies, ...peerDependencies]\n const implicitDeps = getImplicitDevDependencies({\n ...fileContext, allDependencies: allDeps, location,\n })\n const requiredPeers = getRequiredPeerDependencies(location, allDeps)\n const scriptRefs = getScriptReferencedPackages(location, allDeps)\n let unusedDevDependencies = 0\n for (const dep of devDependencies) {\n // Skip devDeps that are also declared as dependencies or peerDependencies\n if (dependencies.includes(dep) || peerDependencies.includes(dep)) continue\n\n if (!isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs)) {\n unusedDevDependencies++\n console.log(`[${chalk.blue(name)}] Unused devDependency in package.json: ${chalk.red(dep)}`)\n }\n }\n if (unusedDevDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unusedDevDependencies\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function findDepPackageJson(location: string, dep: string): string | undefined {\n let dir = location\n while (true) {\n const candidate = path.join(dir, 'node_modules', dep, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n const parent = path.dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\n/**\n * Collects the peerDependencies declared by all of a package's\n * dependencies and devDependencies. A devDependency that satisfies\n * one of these peer requirements should not be flagged as unused.\n */\nexport function getRequiredPeerDependencies(\n location: string,\n allDeps: string[],\n): Set<string> {\n const required = new Set<string>()\n for (const dep of allDeps) {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) continue\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (pkg.peerDependencies) {\n for (const peer of Object.keys(pkg.peerDependencies)) {\n required.add(peer)\n }\n }\n } catch {\n // Package not readable — skip\n }\n }\n return required\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nimport { getBasePackageName } from './getBasePackageName.ts'\nimport { findDepPackageJson } from './getRequiredPeerDependencies.ts'\n\nfunction getBinNames(location: string, dep: string): string[] {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) return []\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (!pkg.bin) return []\n if (typeof pkg.bin === 'string') return [pkg.name?.split('/').pop() ?? dep]\n return Object.keys(pkg.bin)\n } catch {\n return []\n }\n}\n\nfunction tokenizeScript(script: string): string[] {\n // Split on shell operators and whitespace to get command tokens\n return script\n .split(/[&|;$()\"`\\s]+/)\n .map(t => t.trim())\n .filter(Boolean)\n}\n\n/**\n * Scans package.json scripts for references to installed packages,\n * either by package name or by binary name they provide.\n */\nexport function getScriptReferencedPackages(\n location: string,\n allDeps: string[],\n): Set<string> {\n const pkgPath = path.join(location, 'package.json')\n let scripts: Record<string, string> = {}\n try {\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n scripts = pkg.scripts ?? {}\n } catch {\n return new Set()\n }\n\n const scriptText = Object.values(scripts).join(' ')\n const tokens = new Set(tokenizeScript(scriptText))\n\n // Build a map from bin name -> package name\n const binToPackage = new Map<string, string>()\n for (const dep of allDeps) {\n const bins = getBinNames(location, dep)\n for (const bin of bins) {\n binToPackage.set(bin, dep)\n }\n }\n\n const referenced = new Set<string>()\n for (const token of tokens) {\n // Direct package name match (e.g. \"yarn rimraf\" -> token \"rimraf\")\n const baseName = getBasePackageName(token)\n if (allDeps.includes(baseName)) {\n referenced.add(baseName)\n }\n // Binary name match (e.g. \"tsup\" -> @xylabs/ts-scripts-yarn3 provides \"tsup\"? no, tsup provides \"tsup\")\n const pkg = binToPackage.get(token)\n if (pkg) {\n referenced.add(pkg)\n }\n }\n\n return referenced\n}\n","export function getBasePackageName(importName: string) {\n const importNameScrubbed = importName.replaceAll('\"', '').trim()\n if (importNameScrubbed.startsWith('@')) {\n const parts = importNameScrubbed.split('/')\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importNameScrubbed\n }\n return importNameScrubbed.split('/')[0]\n}\n","import fs from 'node:fs'\n\nimport { findDepPackageJson } from './getRequiredPeerDependencies.ts'\n\nexport interface ImplicitDevDependencyRule {\n isNeeded: (context: ImplicitDepContext) => boolean\n package: string\n}\n\nexport interface FileContext {\n configFiles: string[]\n distFiles: string[]\n srcFiles: string[]\n}\n\nexport interface ImplicitDepContext extends FileContext {\n allDependencies: string[]\n location: string\n}\n\nconst hasFileWithExtension = (files: string[], extensions: string[]) =>\n files.some(f => extensions.some(ext => f.endsWith(ext)))\n\nconst tsExtensions = ['.ts', '.tsx', '.mts', '.cts']\n\nconst hasTypescriptFiles = ({ srcFiles, configFiles }: ImplicitDepContext) =>\n hasFileWithExtension([...srcFiles, ...configFiles], tsExtensions)\n\n// Matches decorator usage: @something at the start of a line (after optional whitespace).\n// Safe from JSDoc false positives since those appear after * in comment blocks.\nconst decoratorPattern = /^\\s*@[a-zA-Z]\\w*/m\n\nconst hasDecorators = ({ srcFiles }: ImplicitDepContext) =>\n srcFiles\n .filter(f => tsExtensions.some(ext => f.endsWith(ext)))\n .some((file) => {\n try {\n const content = fs.readFileSync(file, 'utf8')\n return decoratorPattern.test(content)\n } catch {\n return false\n }\n })\n\nconst importPlugins = new Set(['eslint-plugin-import-x', 'eslint-plugin-import'])\n\n/**\n * Checks whether any dependency (direct or transitive) pulls in\n * one of the eslint import plugins that require a resolver.\n */\nfunction hasImportPlugin({ location, allDependencies }: ImplicitDepContext): boolean {\n // Direct dependency on the plugin\n if (allDependencies.some(d => importPlugins.has(d))) return true\n\n // Transitive: a dependency bundles the plugin as a dep or peer\n for (const dep of allDependencies) {\n const pkgPath = findDepPackageJson(location, dep)\n if (!pkgPath) continue\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))\n const transitiveDeps = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]\n if (transitiveDeps.some(d => importPlugins.has(d))) return true\n } catch {\n // skip unreadable packages\n }\n }\n return false\n}\n\nconst rules: ImplicitDevDependencyRule[] = [\n {\n package: 'typescript',\n isNeeded: hasTypescriptFiles,\n },\n {\n package: 'eslint-import-resolver-typescript',\n isNeeded: context =>\n hasTypescriptFiles(context)\n && context.allDependencies.includes('eslint')\n && hasImportPlugin(context),\n },\n {\n package: 'tslib',\n isNeeded: hasDecorators,\n },\n]\n\nexport function getImplicitDevDependencies(context: ImplicitDepContext): Set<string> {\n const implicit = new Set<string>()\n for (const rule of rules) {\n if (rule.isNeeded(context)) {\n implicit.add(rule.package)\n }\n }\n return implicit\n}\n"],"mappings":";AAAA,OAAO,WAAW;;;ACAlB,OAAO,QAAQ;AACf,OAAO,UAAU;AAEV,SAAS,mBAAmB,UAAkB,KAAiC;AACpF,MAAI,MAAM;AACV,SAAO,MAAM;AACX,UAAM,YAAY,KAAK,KAAK,KAAK,gBAAgB,KAAK,cAAc;AACpE,QAAI,GAAG,WAAW,SAAS,EAAG,QAAO;AACrC,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAOO,SAAS,4BACd,UACA,SACa;AACb,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,OAAO,SAAS;AACzB,UAAM,aAAa,mBAAmB,UAAU,GAAG;AACnD,QAAI,CAAC,WAAY;AACjB,QAAI;AACF,YAAM,MAAM,GAAG,aAAa,YAAY,MAAM;AAC9C,YAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,UAAI,IAAI,kBAAkB;AACxB,mBAAW,QAAQ,OAAO,KAAK,IAAI,gBAAgB,GAAG;AACpD,mBAAS,IAAI,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;;;ACxCA,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACDV,SAAS,mBAAmB,YAAoB;AACrD,QAAM,qBAAqB,WAAW,WAAW,KAAK,EAAE,EAAE,KAAK;AAC/D,MAAI,mBAAmB,WAAW,GAAG,GAAG;AACtC,UAAM,QAAQ,mBAAmB,MAAM,GAAG;AAC1C,WAAO,MAAM,UAAU,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK;AAAA,EACzD;AACA,SAAO,mBAAmB,MAAM,GAAG,EAAE,CAAC;AACxC;;;ADDA,SAAS,YAAY,UAAkB,KAAuB;AAC5D,QAAM,aAAa,mBAAmB,UAAU,GAAG;AACnD,MAAI,CAAC,WAAY,QAAO,CAAC;AACzB,MAAI;AACF,UAAM,MAAMC,IAAG,aAAa,YAAY,MAAM;AAC9C,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,QAAI,CAAC,IAAI,IAAK,QAAO,CAAC;AACtB,QAAI,OAAO,IAAI,QAAQ,SAAU,QAAO,CAAC,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,KAAK,GAAG;AAC1E,WAAO,OAAO,KAAK,IAAI,GAAG;AAAA,EAC5B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,eAAe,QAA0B;AAEhD,SAAO,OACJ,MAAM,eAAe,EACrB,IAAI,OAAK,EAAE,KAAK,CAAC,EACjB,OAAO,OAAO;AACnB;AAMO,SAAS,4BACd,UACA,SACa;AACb,QAAM,UAAUC,MAAK,KAAK,UAAU,cAAc;AAClD,MAAI,UAAkC,CAAC;AACvC,MAAI;AACF,UAAM,MAAMD,IAAG,aAAa,SAAS,MAAM;AAC3C,UAAM,MAAM,KAAK,MAAM,GAAG;AAC1B,cAAU,IAAI,WAAW,CAAC;AAAA,EAC5B,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AAEA,QAAM,aAAa,OAAO,OAAO,OAAO,EAAE,KAAK,GAAG;AAClD,QAAM,SAAS,IAAI,IAAI,eAAe,UAAU,CAAC;AAGjD,QAAM,eAAe,oBAAI,IAAoB;AAC7C,aAAW,OAAO,SAAS;AACzB,UAAM,OAAO,YAAY,UAAU,GAAG;AACtC,eAAW,OAAO,MAAM;AACtB,mBAAa,IAAI,KAAK,GAAG;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,SAAS,QAAQ;AAE1B,UAAM,WAAW,mBAAmB,KAAK;AACzC,QAAI,QAAQ,SAAS,QAAQ,GAAG;AAC9B,iBAAW,IAAI,QAAQ;AAAA,IACzB;AAEA,UAAM,MAAM,aAAa,IAAI,KAAK;AAClC,QAAI,KAAK;AACP,iBAAW,IAAI,GAAG;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;;;AEzEA,OAAOE,SAAQ;AAoBf,IAAM,uBAAuB,CAAC,OAAiB,eAC7C,MAAM,KAAK,OAAK,WAAW,KAAK,SAAO,EAAE,SAAS,GAAG,CAAC,CAAC;AAEzD,IAAM,eAAe,CAAC,OAAO,QAAQ,QAAQ,MAAM;AAEnD,IAAM,qBAAqB,CAAC,EAAE,UAAU,YAAY,MAClD,qBAAqB,CAAC,GAAG,UAAU,GAAG,WAAW,GAAG,YAAY;AAIlE,IAAM,mBAAmB;AAEzB,IAAM,gBAAgB,CAAC,EAAE,SAAS,MAChC,SACG,OAAO,OAAK,aAAa,KAAK,SAAO,EAAE,SAAS,GAAG,CAAC,CAAC,EACrD,KAAK,CAAC,SAAS;AACd,MAAI;AACF,UAAM,UAAUC,IAAG,aAAa,MAAM,MAAM;AAC5C,WAAO,iBAAiB,KAAK,OAAO;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AACF,CAAC;AAEL,IAAM,gBAAgB,oBAAI,IAAI,CAAC,0BAA0B,sBAAsB,CAAC;AAMhF,SAAS,gBAAgB,EAAE,UAAU,gBAAgB,GAAgC;AAEnF,MAAI,gBAAgB,KAAK,OAAK,cAAc,IAAI,CAAC,CAAC,EAAG,QAAO;AAG5D,aAAW,OAAO,iBAAiB;AACjC,UAAM,UAAU,mBAAmB,UAAU,GAAG;AAChD,QAAI,CAAC,QAAS;AACd,QAAI;AACF,YAAM,MAAM,KAAK,MAAMA,IAAG,aAAa,SAAS,MAAM,CAAC;AACvD,YAAM,iBAAiB;AAAA,QACrB,GAAG,OAAO,KAAK,IAAI,gBAAgB,CAAC,CAAC;AAAA,QACrC,GAAG,OAAO,KAAK,IAAI,oBAAoB,CAAC,CAAC;AAAA,MAC3C;AACA,UAAI,eAAe,KAAK,OAAK,cAAc,IAAI,CAAC,CAAC,EAAG,QAAO;AAAA,IAC7D,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,QAAqC;AAAA,EACzC;AAAA,IACE,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,UAAU,aACR,mBAAmB,OAAO,KACvB,QAAQ,gBAAgB,SAAS,QAAQ,KACzC,gBAAgB,OAAO;AAAA,EAC9B;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,2BAA2B,SAA0C;AACnF,QAAM,WAAW,oBAAI,IAAY;AACjC,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,eAAS,IAAI,KAAK,OAAO;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;;;AJzFA,IAAM,qBAAqB,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAyB;AACvB,QAAM,MAAM,oBAAI,IAAY;AAAA,IAC1B,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACD,SAAO;AACT;AAEA,SAAS,aACP,KACA,YACA,cACA,eACA,YACA;AACA,MAAI,aAAa,IAAI,GAAG,EAAG,QAAO;AAClC,MAAI,cAAc,IAAI,GAAG,EAAG,QAAO;AACnC,MAAI,WAAW,IAAI,GAAG,EAAG,QAAO;AAEhC,MAAI,IAAI,WAAW,SAAS,GAAG;AAC7B,UAAM,WAAW,IAAI,QAAQ,aAAa,EAAE;AAC5C,WAAO,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,GAAG,KAAK,aAAa,IAAI,QAAQ;AAAA,EACrF;AAEA,SAAO,WAAW,IAAI,GAAG;AAC3B;AAEO,SAAS,yBACd,EAAE,MAAM,SAAS,GACjB;AAAA,EACE;AAAA,EAAiB;AAAA,EAAc;AACjC,GACA,cACA,aACA;AACA,QAAM,aAAa,mBAAmB,YAAY;AAClD,QAAM,UAAU,CAAC,GAAG,cAAc,GAAG,iBAAiB,GAAG,gBAAgB;AACzE,QAAM,eAAe,2BAA2B;AAAA,IAC9C,GAAG;AAAA,IAAa,iBAAiB;AAAA,IAAS;AAAA,EAC5C,CAAC;AACD,QAAM,gBAAgB,4BAA4B,UAAU,OAAO;AACnE,QAAM,aAAa,4BAA4B,UAAU,OAAO;AAChE,MAAI,wBAAwB;AAC5B,aAAW,OAAO,iBAAiB;AAEjC,QAAI,aAAa,SAAS,GAAG,KAAK,iBAAiB,SAAS,GAAG,EAAG;AAElE,QAAI,CAAC,aAAa,KAAK,YAAY,cAAc,eAAe,UAAU,GAAG;AAC3E;AACA,cAAQ,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,2CAA2C,MAAM,IAAI,GAAG,CAAC,EAAE;AAAA,IAC7F;AAAA,EACF;AACA,MAAI,wBAAwB,GAAG;AAC7B,UAAM,kBAAkB,GAAG,QAAQ;AACnC,YAAQ,IAAI,KAAK,MAAM,OAAO,eAAe,CAAC;AAAA,CAAI;AAAA,EACpD;AACA,SAAO;AACT;","names":["fs","path","fs","path","fs","fs"]}
1
+ {"version":3,"sources":["../../../../src/actions/deplint/checkPackage/getUnusedDevDependencies.ts","../../../../src/actions/deplint/getRequiredPeerDependencies.ts","../../../../src/actions/deplint/getScriptReferencedPackages.ts","../../../../src/actions/deplint/getBasePackageName.ts","../../../../src/actions/deplint/implicitDevDependencies.ts"],"sourcesContent":["import chalk from 'chalk'\n\nimport type { Workspace } from '../../../lib/index.ts'\nimport { getRequiredPeerDependencies } from '../getRequiredPeerDependencies.ts'\nimport { getScriptReferencedPackages } from '../getScriptReferencedPackages.ts'\nimport type { FileContext } from '../implicitDevDependencies.ts'\nimport { getImplicitDevDependencies } from '../implicitDevDependencies.ts'\nimport type { CheckPackageParams, CheckSourceParams } from './checkPackageTypes.ts'\n\nconst allExternalImports = ({\n externalAllImports,\n externalDistImports,\n externalDistTypeImports,\n}: CheckSourceParams) => {\n return new Set<string>([\n ...externalAllImports,\n ...externalDistImports,\n ...externalDistTypeImports,\n ])\n}\n\nfunction isDevDepUsed(\n dep: string,\n allImports: Set<string>,\n implicitDeps: Set<string>,\n requiredPeers: Set<string>,\n scriptRefs: Set<string>,\n) {\n if (implicitDeps.has(dep)) return true\n if (requiredPeers.has(dep)) return true\n if (scriptRefs.has(dep)) return true\n\n if (dep.startsWith('@types/')) {\n const baseName = dep.replace(/^@types\\//, '')\n return allImports.has(baseName) || allImports.has(dep) || implicitDeps.has(baseName)\n }\n\n return allImports.has(dep)\n}\n\nexport function getUnusedDevDependencies(\n { name, location }: Workspace,\n {\n devDependencies, dependencies, peerDependencies,\n }: CheckPackageParams,\n sourceParams: CheckSourceParams,\n fileContext: FileContext,\n) {\n const allImports = allExternalImports(sourceParams)\n const allDeps = [...dependencies, ...devDependencies, ...peerDependencies]\n const implicitDeps = getImplicitDevDependencies({\n ...fileContext, allDependencies: allDeps, location,\n })\n const requiredPeers = getRequiredPeerDependencies(location, allDeps)\n const scriptRefs = getScriptReferencedPackages(location, allDeps)\n let unusedDevDependencies = 0\n for (const dep of devDependencies) {\n // Skip devDeps that are also declared as dependencies or peerDependencies\n if (dependencies.includes(dep) || peerDependencies.includes(dep)) continue\n\n if (!isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs)) {\n unusedDevDependencies++\n console.log(`[${chalk.blue(name)}] Unused devDependency in package.json: ${chalk.red(dep)}`)\n }\n }\n if (unusedDevDependencies > 0) {\n const packageLocation = `${location}/package.json`\n console.log(` ${chalk.yellow(packageLocation)}\\n`)\n }\n return unusedDevDependencies\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nexport function findDepPackageJson(location: string, dep: string): string | undefined {\n let dir = location\n while (true) {\n const candidate = path.join(dir, 'node_modules', dep, 'package.json')\n if (fs.existsSync(candidate)) return candidate\n const parent = path.dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\n/**\n * Collects the peerDependencies declared by all of a package's\n * dependencies and devDependencies. A devDependency that satisfies\n * one of these peer requirements should not be flagged as unused.\n */\nexport function getRequiredPeerDependencies(\n location: string,\n allDeps: string[],\n): Set<string> {\n const required = new Set<string>()\n for (const dep of allDeps) {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) continue\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (pkg.peerDependencies) {\n for (const peer of Object.keys(pkg.peerDependencies)) {\n required.add(peer)\n }\n }\n } catch {\n // Package not readable — skip\n }\n }\n return required\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\nimport { getBasePackageName } from './getBasePackageName.ts'\nimport { findDepPackageJson } from './getRequiredPeerDependencies.ts'\n\nfunction getBinNames(location: string, dep: string): string[] {\n const depPkgPath = findDepPackageJson(location, dep)\n if (!depPkgPath) return []\n try {\n const raw = fs.readFileSync(depPkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n if (!pkg.bin) return []\n if (typeof pkg.bin === 'string') return [pkg.name?.split('/').pop() ?? dep]\n return Object.keys(pkg.bin)\n } catch {\n return []\n }\n}\n\nfunction tokenizeScript(script: string): string[] {\n // Split on shell operators and whitespace to get command tokens\n return script\n .split(/[&|;$()\"`\\s]+/)\n .map(t => t.trim())\n .filter(Boolean)\n}\n\n/**\n * Scans package.json scripts for references to installed packages,\n * either by package name or by binary name they provide.\n */\nexport function getScriptReferencedPackages(\n location: string,\n allDeps: string[],\n): Set<string> {\n const pkgPath = path.join(location, 'package.json')\n let scripts: Record<string, string> = {}\n try {\n const raw = fs.readFileSync(pkgPath, 'utf8')\n const pkg = JSON.parse(raw)\n scripts = pkg.scripts ?? {}\n } catch {\n return new Set()\n }\n\n const scriptText = Object.values(scripts).join(' ')\n const tokens = new Set(tokenizeScript(scriptText))\n\n // Build a map from bin name -> package name\n const binToPackage = new Map<string, string>()\n for (const dep of allDeps) {\n const bins = getBinNames(location, dep)\n for (const bin of bins) {\n binToPackage.set(bin, dep)\n }\n }\n\n const referenced = new Set<string>()\n for (const token of tokens) {\n // Direct package name match (e.g. \"yarn rimraf\" -> token \"rimraf\")\n const baseName = getBasePackageName(token)\n if (allDeps.includes(baseName)) {\n referenced.add(baseName)\n }\n // Binary name match (e.g. \"tsup\" -> @xylabs/ts-scripts-yarn3 provides \"tsup\"? no, tsup provides \"tsup\")\n const pkg = binToPackage.get(token)\n if (pkg) {\n referenced.add(pkg)\n }\n }\n\n return referenced\n}\n","export function getBasePackageName(importName: string) {\n const importNameScrubbed = importName.replaceAll('\"', '').trim()\n if (importNameScrubbed.startsWith('@')) {\n const parts = importNameScrubbed.split('/')\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importNameScrubbed\n }\n return importNameScrubbed.split('/')[0]\n}\n","import fs from 'node:fs'\n\nimport { findDepPackageJson } from './getRequiredPeerDependencies.ts'\n\nexport interface ImplicitDevDependencyRule {\n isNeeded: (context: ImplicitDepContext) => boolean\n package: string\n}\n\nexport interface FileContext {\n allFiles: string[]\n distFiles: string[]\n}\n\nexport interface ImplicitDepContext extends FileContext {\n allDependencies: string[]\n location: string\n}\n\nconst hasFileWithExtension = (files: string[], extensions: string[]) =>\n files.some(f => extensions.some(ext => f.endsWith(ext)))\n\nconst tsExtensions = ['.ts', '.tsx', '.mts', '.cts']\n\nconst hasTypescriptFiles = ({ allFiles }: ImplicitDepContext) =>\n hasFileWithExtension(allFiles, tsExtensions)\n\n// Matches decorator usage: @something at the start of a line (after optional whitespace).\n// Safe from JSDoc false positives since those appear after * in comment blocks.\nconst decoratorPattern = /^\\s*@[a-zA-Z]\\w*/m\n\nconst hasDecorators = ({ allFiles }: ImplicitDepContext) =>\n allFiles\n .filter(f => tsExtensions.some(ext => f.endsWith(ext)))\n .some((file) => {\n try {\n const content = fs.readFileSync(file, 'utf8')\n return decoratorPattern.test(content)\n } catch {\n return false\n }\n })\n\nconst importPlugins = new Set(['eslint-plugin-import-x', 'eslint-plugin-import'])\n\n/**\n * Checks whether any dependency (direct or transitive) pulls in\n * one of the eslint import plugins that require a resolver.\n */\nfunction hasImportPlugin({ location, allDependencies }: ImplicitDepContext): boolean {\n // Direct dependency on the plugin\n if (allDependencies.some(d => importPlugins.has(d))) return true\n\n // Transitive: a dependency bundles the plugin as a dep or peer\n for (const dep of allDependencies) {\n const pkgPath = findDepPackageJson(location, dep)\n if (!pkgPath) continue\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))\n const transitiveDeps = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]\n if (transitiveDeps.some(d => importPlugins.has(d))) return true\n } catch {\n // skip unreadable packages\n }\n }\n return false\n}\n\nconst rules: ImplicitDevDependencyRule[] = [\n {\n package: 'typescript',\n isNeeded: hasTypescriptFiles,\n },\n {\n package: 'eslint-import-resolver-typescript',\n isNeeded: context =>\n hasTypescriptFiles(context)\n && context.allDependencies.includes('eslint')\n && hasImportPlugin(context),\n },\n {\n package: 'tslib',\n isNeeded: hasDecorators,\n },\n]\n\nexport function getImplicitDevDependencies(context: ImplicitDepContext): Set<string> {\n const implicit = new Set<string>()\n for (const rule of rules) {\n if (rule.isNeeded(context)) {\n implicit.add(rule.package)\n }\n }\n return implicit\n}\n"],"mappings":"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","names":["fs","path","fs","path","fs","fs"]}
@@ -1,30 +1,45 @@
1
+ // src/actions/deplint/findFiles.ts
2
+ import fs from "fs";
3
+
1
4
  // src/actions/deplint/findFilesByGlob.ts
2
5
  import { globSync } from "glob";
3
- function findFilesByGlob(cwd, pattern) {
4
- return globSync(pattern, { cwd, absolute: true });
6
+ function findFilesByGlob(cwd, pattern, ignore) {
7
+ return globSync(pattern, {
8
+ cwd,
9
+ absolute: true,
10
+ ignore,
11
+ nodir: true
12
+ });
5
13
  }
6
14
 
7
15
  // src/actions/deplint/findFiles.ts
8
- function findFiles(path5) {
9
- const allSourceInclude = ["./src/**/*.{ts,tsx,mts,cts,js,mjs,cjs}"];
10
- const allDistInclude = ["./dist/**/*.d.ts", "./dist/**/*.{mjs,js,cjs}"];
11
- const allConfigInclude = ["./*.config.{ts,mts,mjs,js}"];
12
- const srcFiles = allSourceInclude.flatMap((pattern) => findFilesByGlob(path5, pattern));
13
- const distFiles = allDistInclude.flatMap((pattern) => findFilesByGlob(path5, pattern));
14
- const configFiles = allConfigInclude.flatMap((pattern) => findFilesByGlob(path5, pattern));
15
- return {
16
- srcFiles,
17
- distFiles,
18
- configFiles
19
- };
16
+ var codeExtensions = "*.{ts,tsx,mts,cts,js,mjs,cjs}";
17
+ function getWorkspaceIgnores(location) {
18
+ try {
19
+ const raw = fs.readFileSync(`${location}/package.json`, "utf8");
20
+ const pkg = JSON.parse(raw);
21
+ return pkg.workspaces ?? [];
22
+ } catch {
23
+ return [];
24
+ }
25
+ }
26
+ function findFiles(location) {
27
+ const workspaceIgnores = getWorkspaceIgnores(location).map((w) => `${w}/**`);
28
+ const ignore = ["**/node_modules/**", "dist/**", ...workspaceIgnores];
29
+ const allFiles = findFilesByGlob(location, `./**/${codeExtensions}`, ignore);
30
+ const distFiles = [
31
+ ...findFilesByGlob(location, "./dist/**/*.d.ts"),
32
+ ...findFilesByGlob(location, `./dist/**/${codeExtensions}`)
33
+ ];
34
+ return { allFiles, distFiles };
20
35
  }
21
36
 
22
37
  // src/actions/deplint/getDependenciesFromPackageJson.ts
23
- import fs from "fs";
38
+ import fs2 from "fs";
24
39
  import path from "path";
25
40
  function getDependenciesFromPackageJson(packageJsonPath) {
26
41
  const packageJsonFullPath = path.resolve(packageJsonPath);
27
- const rawContent = fs.readFileSync(packageJsonFullPath, "utf8");
42
+ const rawContent = fs2.readFileSync(packageJsonFullPath, "utf8");
28
43
  const packageJson = JSON.parse(rawContent);
29
44
  const dependencies = packageJson.dependencies ? Object.keys(packageJson.dependencies) : [];
30
45
  const devDependencies = packageJson.devDependencies ? Object.keys(packageJson.devDependencies) : [];
@@ -37,7 +52,7 @@ function getDependenciesFromPackageJson(packageJsonPath) {
37
52
  }
38
53
 
39
54
  // src/actions/deplint/getExtendsFromTsconfigs.ts
40
- import fs2 from "fs";
55
+ import fs3 from "fs";
41
56
  import { globSync as globSync2 } from "glob";
42
57
 
43
58
  // src/actions/deplint/getBasePackageName.ts
@@ -62,7 +77,7 @@ function getExtendsFromTsconfigs(location) {
62
77
  const packages = /* @__PURE__ */ new Set();
63
78
  for (const file of tsconfigFiles) {
64
79
  try {
65
- const content = fs2.readFileSync(file, "utf8");
80
+ const content = fs3.readFileSync(file, "utf8");
66
81
  const cleaned = content.replaceAll(/\/\/.*/g, "").replaceAll(/,\s*([}\]])/g, "$1");
67
82
  const parsed = JSON.parse(cleaned);
68
83
  const refs = parseExtendsField(parsed.extends);
@@ -78,7 +93,7 @@ function getExtendsFromTsconfigs(location) {
78
93
  }
79
94
 
80
95
  // src/actions/deplint/getImportsFromFile.ts
81
- import fs3 from "fs";
96
+ import fs4 from "fs";
82
97
  import path2 from "path";
83
98
  import ts from "typescript";
84
99
  function isTypeOnlyImportClause(clause) {
@@ -93,7 +108,7 @@ function isTypeOnlyImportClause(clause) {
93
108
  return clause.isTypeOnly;
94
109
  }
95
110
  function getImportsFromFile(filePath, importPaths, typeImportPaths) {
96
- const sourceCode = fs3.readFileSync(filePath, "utf8");
111
+ const sourceCode = fs4.readFileSync(filePath, "utf8");
97
112
  const isMjsFile = filePath.endsWith(".mjs");
98
113
  const sourceFile = ts.createSourceFile(
99
114
  path2.basename(filePath),
@@ -104,14 +119,14 @@ function getImportsFromFile(filePath, importPaths, typeImportPaths) {
104
119
  );
105
120
  const imports = [];
106
121
  const typeImports = [];
107
- const isDeclarationFile = filePath.endsWith(".d.ts");
122
+ const isDeclarationFile2 = filePath.endsWith(".d.ts");
108
123
  function visit(node) {
109
124
  if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
110
125
  const moduleSpecifier = node.moduleSpecifier?.getFullText();
111
126
  const isTypeImport = ts.isImportDeclaration(node) ? isTypeOnlyImportClause(node.importClause) : false;
112
127
  if (typeof moduleSpecifier === "string") {
113
128
  const trimmed = moduleSpecifier.replaceAll("'", "").replaceAll('"', "").trim();
114
- if (isTypeImport || isDeclarationFile) {
129
+ if (isTypeImport || isDeclarationFile2) {
115
130
  typeImports.push(trimmed);
116
131
  } else {
117
132
  imports.push(trimmed);
@@ -146,41 +161,34 @@ var internalImportPrefixes = [".", "#", "node:"];
146
161
  var removeInternalImports = (imports) => {
147
162
  return imports.filter((imp) => !internalImportPrefixes.some((prefix) => imp.startsWith(prefix)));
148
163
  };
164
+ var isDeclarationFile = (file) => file.endsWith(".d.ts") || file.endsWith(".d.cts") || file.endsWith(".d.mts");
149
165
  function getExternalImportsFromFiles({
150
- srcFiles,
166
+ allFiles,
151
167
  distFiles,
152
- configFiles = [],
153
168
  tsconfigExtends = []
154
169
  }) {
155
- const srcImportPaths = {};
170
+ const allImportPaths = {};
156
171
  const distImportPaths = {};
157
172
  const distTypeImportPaths = {};
158
- const configImportPaths = {};
159
- for (const path5 of srcFiles) getImportsFromFile(path5, srcImportPaths, srcImportPaths).flat();
160
- for (const path5 of configFiles) getImportsFromFile(path5, configImportPaths, configImportPaths).flat();
161
- const distTypeFiles = distFiles.filter((file) => file.endsWith(".d.ts") || file.endsWith(".d.cts") || file.endsWith(".d.mts"));
162
- const distCodeFiles = distFiles.filter((file) => !(file.endsWith(".d.ts") || file.endsWith(".d.cts") || file.endsWith(".d.mts")));
173
+ for (const path5 of allFiles) getImportsFromFile(path5, allImportPaths, allImportPaths).flat();
174
+ const distTypeFiles = distFiles.filter(isDeclarationFile);
175
+ const distCodeFiles = distFiles.filter((file) => !isDeclarationFile(file));
163
176
  for (const path5 of distCodeFiles) getImportsFromFile(path5, distImportPaths, distImportPaths).flat();
164
177
  for (const path5 of distTypeFiles) getImportsFromFile(path5, distTypeImportPaths, distTypeImportPaths).flat();
165
- const srcImports = Object.keys(srcImportPaths);
178
+ const allImports = Object.keys(allImportPaths);
166
179
  const distImports = Object.keys(distImportPaths);
167
- const distTypeImports = Object.keys(distTypeImportPaths);
168
- const externalSrcImports = removeInternalImports(srcImports);
180
+ const externalAllImports = removeInternalImports(allImports);
169
181
  const externalDistImports = removeInternalImports(distImports);
170
- const externalDistTypeImports = removeInternalImports(distTypeImports);
171
- const externalConfigImports = removeInternalImports(Object.keys(configImportPaths));
182
+ const externalDistTypeImports = removeInternalImports(Object.keys(distTypeImportPaths));
172
183
  for (const ext of tsconfigExtends) {
173
- if (!externalSrcImports.includes(ext)) externalSrcImports.push(ext);
174
- if (!externalConfigImports.includes(ext)) externalConfigImports.push(ext);
184
+ if (!externalAllImports.includes(ext)) externalAllImports.push(ext);
175
185
  }
176
186
  return {
177
- configImportPaths,
178
- srcImports,
179
- srcImportPaths,
180
- externalConfigImports,
181
- externalSrcImports,
182
- distImports,
187
+ allImportPaths,
188
+ allImports,
183
189
  distImportPaths,
190
+ distImports,
191
+ externalAllImports,
184
192
  externalDistImports,
185
193
  externalDistTypeImports
186
194
  };
@@ -232,17 +240,17 @@ function getUnlistedDevDependencies({ name, location }, {
232
240
  dependencies,
233
241
  peerDependencies
234
242
  }, {
235
- srcImportPaths,
236
- externalSrcImports,
243
+ allImportPaths,
244
+ externalAllImports,
237
245
  distImports
238
246
  }) {
239
247
  let unlistedDevDependencies = 0;
240
- for (const imp of externalSrcImports) {
248
+ for (const imp of externalAllImports) {
241
249
  if (!distImports.includes(imp) && imp !== name && !dependencies.includes(imp) && !dependencies.includes(`@types/${imp}`) && !peerDependencies.includes(imp) && !peerDependencies.includes(`@types/${imp}`) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`) && !builtinModules2.includes(imp)) {
242
250
  unlistedDevDependencies++;
243
251
  console.log(`[${chalk2.blue(name)}] Missing devDependency in package.json: ${chalk2.red(imp)}`);
244
- if (srcImportPaths[imp]) {
245
- console.log(` ${srcImportPaths[imp].join("\n ")}`);
252
+ if (allImportPaths[imp]) {
253
+ console.log(` ${allImportPaths[imp].join("\n ")}`);
246
254
  }
247
255
  }
248
256
  }
@@ -259,13 +267,13 @@ import chalk3 from "chalk";
259
267
  function getUnusedDependencies({ name, location }, { dependencies }, {
260
268
  externalDistImports,
261
269
  externalDistTypeImports,
262
- externalSrcImports
270
+ externalAllImports
263
271
  }) {
264
272
  let unusedDependencies = 0;
265
273
  for (const dep of dependencies) {
266
274
  if (!externalDistImports.includes(dep) && !externalDistImports.includes(dep.replace(/^@types\//, "")) && !externalDistTypeImports.includes(dep) && !externalDistTypeImports.includes(dep.replace(/^@types\//, ""))) {
267
275
  unusedDependencies++;
268
- if (externalSrcImports.includes(dep)) {
276
+ if (externalAllImports.includes(dep)) {
269
277
  console.log(`[${chalk3.blue(name)}] dependency should be devDependency in package.json: ${chalk3.red(dep)}`);
270
278
  } else {
271
279
  console.log(`[${chalk3.blue(name)}] Unused dependency in package.json: ${chalk3.red(dep)}`);
@@ -284,13 +292,13 @@ function getUnusedDependencies({ name, location }, { dependencies }, {
284
292
  import chalk4 from "chalk";
285
293
 
286
294
  // src/actions/deplint/getRequiredPeerDependencies.ts
287
- import fs4 from "fs";
295
+ import fs5 from "fs";
288
296
  import path3 from "path";
289
297
  function findDepPackageJson(location, dep) {
290
298
  let dir = location;
291
299
  while (true) {
292
300
  const candidate = path3.join(dir, "node_modules", dep, "package.json");
293
- if (fs4.existsSync(candidate)) return candidate;
301
+ if (fs5.existsSync(candidate)) return candidate;
294
302
  const parent = path3.dirname(dir);
295
303
  if (parent === dir) return void 0;
296
304
  dir = parent;
@@ -302,7 +310,7 @@ function getRequiredPeerDependencies(location, allDeps) {
302
310
  const depPkgPath = findDepPackageJson(location, dep);
303
311
  if (!depPkgPath) continue;
304
312
  try {
305
- const raw = fs4.readFileSync(depPkgPath, "utf8");
313
+ const raw = fs5.readFileSync(depPkgPath, "utf8");
306
314
  const pkg = JSON.parse(raw);
307
315
  if (pkg.peerDependencies) {
308
316
  for (const peer of Object.keys(pkg.peerDependencies)) {
@@ -316,13 +324,13 @@ function getRequiredPeerDependencies(location, allDeps) {
316
324
  }
317
325
 
318
326
  // src/actions/deplint/getScriptReferencedPackages.ts
319
- import fs5 from "fs";
327
+ import fs6 from "fs";
320
328
  import path4 from "path";
321
329
  function getBinNames(location, dep) {
322
330
  const depPkgPath = findDepPackageJson(location, dep);
323
331
  if (!depPkgPath) return [];
324
332
  try {
325
- const raw = fs5.readFileSync(depPkgPath, "utf8");
333
+ const raw = fs6.readFileSync(depPkgPath, "utf8");
326
334
  const pkg = JSON.parse(raw);
327
335
  if (!pkg.bin) return [];
328
336
  if (typeof pkg.bin === "string") return [pkg.name?.split("/").pop() ?? dep];
@@ -338,7 +346,7 @@ function getScriptReferencedPackages(location, allDeps) {
338
346
  const pkgPath = path4.join(location, "package.json");
339
347
  let scripts = {};
340
348
  try {
341
- const raw = fs5.readFileSync(pkgPath, "utf8");
349
+ const raw = fs6.readFileSync(pkgPath, "utf8");
342
350
  const pkg = JSON.parse(raw);
343
351
  scripts = pkg.scripts ?? {};
344
352
  } catch {
@@ -368,14 +376,14 @@ function getScriptReferencedPackages(location, allDeps) {
368
376
  }
369
377
 
370
378
  // src/actions/deplint/implicitDevDependencies.ts
371
- import fs6 from "fs";
379
+ import fs7 from "fs";
372
380
  var hasFileWithExtension = (files, extensions) => files.some((f) => extensions.some((ext) => f.endsWith(ext)));
373
381
  var tsExtensions = [".ts", ".tsx", ".mts", ".cts"];
374
- var hasTypescriptFiles = ({ srcFiles, configFiles }) => hasFileWithExtension([...srcFiles, ...configFiles], tsExtensions);
382
+ var hasTypescriptFiles = ({ allFiles }) => hasFileWithExtension(allFiles, tsExtensions);
375
383
  var decoratorPattern = /^\s*@[a-zA-Z]\w*/m;
376
- var hasDecorators = ({ srcFiles }) => srcFiles.filter((f) => tsExtensions.some((ext) => f.endsWith(ext))).some((file) => {
384
+ var hasDecorators = ({ allFiles }) => allFiles.filter((f) => tsExtensions.some((ext) => f.endsWith(ext))).some((file) => {
377
385
  try {
378
- const content = fs6.readFileSync(file, "utf8");
386
+ const content = fs7.readFileSync(file, "utf8");
379
387
  return decoratorPattern.test(content);
380
388
  } catch {
381
389
  return false;
@@ -388,7 +396,7 @@ function hasImportPlugin({ location, allDependencies }) {
388
396
  const pkgPath = findDepPackageJson(location, dep);
389
397
  if (!pkgPath) continue;
390
398
  try {
391
- const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf8"));
399
+ const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf8"));
392
400
  const transitiveDeps = [
393
401
  ...Object.keys(pkg.dependencies ?? {}),
394
402
  ...Object.keys(pkg.peerDependencies ?? {})
@@ -425,18 +433,15 @@ function getImplicitDevDependencies(context) {
425
433
 
426
434
  // src/actions/deplint/checkPackage/getUnusedDevDependencies.ts
427
435
  var allExternalImports = ({
428
- externalSrcImports,
436
+ externalAllImports,
429
437
  externalDistImports,
430
- externalDistTypeImports,
431
- externalConfigImports
438
+ externalDistTypeImports
432
439
  }) => {
433
- const all = /* @__PURE__ */ new Set([
434
- ...externalSrcImports,
440
+ return /* @__PURE__ */ new Set([
441
+ ...externalAllImports,
435
442
  ...externalDistImports,
436
- ...externalDistTypeImports,
437
- ...externalConfigImports
443
+ ...externalDistTypeImports
438
444
  ]);
439
- return all;
440
445
  };
441
446
  function isDevDepUsed(dep, allImports, implicitDeps, requiredPeers, scriptRefs) {
442
447
  if (implicitDeps.has(dep)) return true;
@@ -501,18 +506,15 @@ function getUnusedPeerDependencies({ name, location }, { peerDependencies, depen
501
506
  }
502
507
 
503
508
  // src/actions/deplint/checkPackage/checkPackage.ts
504
- function logVerbose(name, location, srcFiles, distFiles, configFiles, tsconfigExtends) {
509
+ function logVerbose(name, location, allFiles, distFiles, tsconfigExtends) {
505
510
  console.info(`Checking package: ${name} at ${location}`);
506
- console.info(`Source files: ${srcFiles.length}, Distribution files: ${distFiles.length}, Config files: ${configFiles.length}`);
507
- for (const file of srcFiles) {
508
- console.info(`Source file: ${file}`);
511
+ console.info(`All files: ${allFiles.length}, Distribution files: ${distFiles.length}`);
512
+ for (const file of allFiles) {
513
+ console.info(`File: ${file}`);
509
514
  }
510
515
  for (const file of distFiles) {
511
516
  console.info(`Distribution file: ${file}`);
512
517
  }
513
- for (const file of configFiles) {
514
- console.info(`Config file: ${file}`);
515
- }
516
518
  for (const ext of tsconfigExtends) {
517
519
  console.info(`Tsconfig extends: ${ext}`);
518
520
  }
@@ -525,33 +527,24 @@ function checkPackage({
525
527
  peerDeps = false,
526
528
  verbose = false
527
529
  }) {
528
- const {
529
- srcFiles,
530
- distFiles,
531
- configFiles
532
- } = findFiles(location);
530
+ const { allFiles, distFiles } = findFiles(location);
533
531
  const tsconfigExtends = getExtendsFromTsconfigs(location);
534
532
  if (verbose) {
535
- logVerbose(name, location, srcFiles, distFiles, configFiles, tsconfigExtends);
533
+ logVerbose(name, location, allFiles, distFiles, tsconfigExtends);
536
534
  }
537
535
  const checkDeps = deps || !(deps || devDeps || peerDeps);
538
536
  const checkDevDeps = devDeps || !(deps || devDeps || peerDeps);
539
537
  const checkPeerDeps = peerDeps;
540
538
  const sourceParams = getExternalImportsFromFiles({
541
- srcFiles,
539
+ allFiles,
542
540
  distFiles,
543
- configFiles,
544
541
  tsconfigExtends
545
542
  });
546
543
  const packageParams = getDependenciesFromPackageJson(`${location}/package.json`);
547
544
  const unlistedDependencies = checkDeps ? getUnlistedDependencies({ name, location }, packageParams, sourceParams) : 0;
548
545
  const unusedDependencies = checkDeps ? getUnusedDependencies({ name, location }, packageParams, sourceParams) : 0;
549
546
  const unlistedDevDependencies = checkDevDeps ? getUnlistedDevDependencies({ name, location }, packageParams, sourceParams) : 0;
550
- const fileContext = {
551
- configFiles,
552
- distFiles,
553
- srcFiles
554
- };
547
+ const fileContext = { allFiles, distFiles };
555
548
  const unusedDevDependencies = checkDevDeps ? getUnusedDevDependencies({ name, location }, packageParams, sourceParams, fileContext) : 0;
556
549
  const unusedPeerDependencies = checkPeerDeps ? getUnusedPeerDependencies({ name, location }, packageParams, sourceParams) : 0;
557
550
  const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies + unusedDevDependencies + unusedPeerDependencies;