@xylabs/ts-scripts-yarn3 6.4.1 → 6.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.
@@ -45,7 +45,7 @@ function getBasePackageName(importName) {
45
45
  }
46
46
  return importName.split("/")[0];
47
47
  }
48
- function getImportsFromFile(filePath, importPaths) {
48
+ function getImportsFromFile(filePath, importPaths, typeImportPaths) {
49
49
  const sourceCode = fs.readFileSync(filePath, "utf8");
50
50
  const sourceFile = ts.createSourceFile(
51
51
  path.basename(filePath),
@@ -54,23 +54,41 @@ function getImportsFromFile(filePath, importPaths) {
54
54
  true
55
55
  );
56
56
  const imports = [];
57
+ const typeImports = [];
57
58
  function visit(node) {
58
59
  if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
59
60
  const moduleSpecifier = node.moduleSpecifier?.getFullText();
61
+ const isTypeImport = ts.isImportDeclaration(node) ? node.importClause?.isTypeOnly ?? false : false;
60
62
  if (moduleSpecifier) {
61
63
  const trimmed = moduleSpecifier.split("'").at(1) ?? moduleSpecifier;
64
+ if (isTypeImport) {
65
+ typeImports.push(trimmed);
66
+ } else {
67
+ imports.push(trimmed);
68
+ }
69
+ }
70
+ } else if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
71
+ const [arg] = node.arguments;
72
+ if (ts.isStringLiteral(arg)) {
73
+ const trimmed = arg.text;
62
74
  imports.push(trimmed);
63
75
  }
64
76
  }
65
77
  ts.forEachChild(node, visit);
66
78
  }
67
79
  visit(sourceFile);
68
- const cleanedImports = imports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:")).map(getBasePackageName);
80
+ const importsStartsWithExcludes = [".", "#", "node:"];
81
+ const cleanedImports = imports.filter((imp) => !importsStartsWithExcludes.some((exc) => imp.startsWith(exc))).map(getBasePackageName);
82
+ const cleanedTypeImports = typeImports.filter((imp) => !importsStartsWithExcludes.some((exc) => imp.startsWith(exc))).map(getBasePackageName);
69
83
  for (const imp of cleanedImports) {
70
84
  importPaths[imp] = importPaths[imp] || [];
71
85
  importPaths[imp].push(filePath);
72
86
  }
73
- return cleanedImports;
87
+ for (const imp of cleanedTypeImports) {
88
+ typeImportPaths[imp] = typeImportPaths[imp] || [];
89
+ typeImportPaths[imp].push(filePath);
90
+ }
91
+ return [cleanedImports, cleanedTypeImports];
74
92
  }
75
93
  function findFilesByGlob(cwd, pattern) {
76
94
  return globSync(pattern, { cwd, absolute: true });
@@ -90,10 +108,17 @@ function findFiles(path2) {
90
108
  }
91
109
  function getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }) {
92
110
  const prodImportPaths = {};
93
- const prodImports = prodSourceFiles.flatMap((path2) => getImportsFromFile(path2, prodImportPaths));
111
+ const prodTypeImportPaths = {};
112
+ const prodImportPairs = prodSourceFiles.map((path2) => getImportsFromFile(path2, prodImportPaths, prodTypeImportPaths));
113
+ const prodImports = prodImportPairs.flatMap((pair) => pair[0]);
114
+ const prodTypeImports = prodImportPairs.flatMap((pair) => pair[1]);
94
115
  const devImportPaths = {};
95
- const devImports = devSourceFiles.flatMap((path2) => getImportsFromFile(path2, devImportPaths));
116
+ const devTypeImportPaths = {};
117
+ const devImportPairs = devSourceFiles.map((path2) => getImportsFromFile(path2, devImportPaths, devTypeImportPaths));
118
+ const devImports = devImportPairs.flatMap((pair) => pair[0]);
119
+ const devTypeImports = devImportPairs.flatMap((pair) => pair[1]);
96
120
  const externalProdImports = prodImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
121
+ const externalProdTypeImports = prodTypeImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
97
122
  const externalDevImports = devImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
98
123
  return {
99
124
  prodImports,
@@ -101,7 +126,10 @@ function getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }) {
101
126
  prodImportPaths,
102
127
  devImportPaths,
103
128
  externalProdImports,
104
- externalDevImports
129
+ externalDevImports,
130
+ prodTypeImports,
131
+ devTypeImports,
132
+ externalProdTypeImports
105
133
  };
106
134
  }
107
135
  function check({
@@ -113,6 +141,7 @@ function check({
113
141
  const { prodSourceFiles, devSourceFiles } = findFiles(location);
114
142
  const {
115
143
  prodImportPaths,
144
+ externalProdTypeImports,
116
145
  devImportPaths,
117
146
  externalProdImports,
118
147
  externalDevImports
@@ -125,6 +154,15 @@ function check({
125
154
  let unlistedDependencies = 0;
126
155
  let unlistedDevDependencies = 0;
127
156
  let unusedDependencies = 0;
157
+ let typesInDependencies = 0;
158
+ for (const imp of externalProdTypeImports) {
159
+ if (!dependencies.includes(imp) && !peerDependencies.includes(imp) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`)) {
160
+ unlistedDependencies++;
161
+ console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`);
162
+ console.log(` ${prodImportPaths[imp].join("\n")}`);
163
+ console.log("");
164
+ }
165
+ }
128
166
  for (const imp of externalProdImports) {
129
167
  if (!dependencies.includes(imp) && !peerDependencies.includes(imp)) {
130
168
  unlistedDependencies++;
@@ -134,6 +172,13 @@ function check({
134
172
  }
135
173
  }
136
174
  for (const dep of dependencies) {
175
+ if (dep.startsWith("@types/")) {
176
+ typesInDependencies++;
177
+ console.log(`[${chalk.blue(name)}] @types in dependencies in package.json: ${chalk.red(dep)}`);
178
+ console.log(` ${location}/package.json
179
+ `);
180
+ console.log("");
181
+ }
137
182
  if (!externalProdImports.includes(dep)) {
138
183
  unusedDependencies++;
139
184
  console.log(`[${chalk.blue(name)}] Unused dependency in package.json: ${chalk.red(dep)}`);
@@ -162,7 +207,7 @@ function check({
162
207
  }
163
208
  }
164
209
  }
165
- const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies;
210
+ const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies + typesInDependencies;
166
211
  return totalErrors;
167
212
  }
168
213
  var deplint = ({ pkg }) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/actions/deplint.ts","../../src/lib/yarn/workspace/yarnWorkspaces.ts","../../src/lib/yarn/workspace/yarnWorkspace.ts"],"sourcesContent":["/* eslint-disable max-statements */\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nimport chalk from 'chalk'\nimport { globSync } from 'glob'\nimport ts from 'typescript'\n\nimport { yarnWorkspace, yarnWorkspaces } from '../lib/index.ts'\n\nfunction getDependenciesFromPackageJson(packageJsonPath: string) {\n const packageJsonFullPath = path.resolve(packageJsonPath)\n const rawContent = fs.readFileSync(packageJsonFullPath, 'utf8')\n const packageJson = JSON.parse(rawContent)\n\n const dependencies = packageJson.dependencies\n ? Object.keys(packageJson.dependencies)\n : []\n\n const devDependencies = packageJson.devDependencies\n ? Object.keys(packageJson.devDependencies)\n : []\n\n const peerDependencies = packageJson.peerDependencies\n ? Object.keys(packageJson.peerDependencies)\n : []\n\n return {\n dependencies, devDependencies, peerDependencies,\n }\n}\n\nfunction getBasePackageName(importName: string) {\n if (importName.startsWith('@')) {\n const parts = importName.split('/')\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importName\n }\n return importName.split('/')[0]\n}\n\nfunction getImportsFromFile(filePath: string, importPaths: Record<string, string[]>) {\n const sourceCode = fs.readFileSync(filePath, 'utf8')\n\n const sourceFile = ts.createSourceFile(\n path.basename(filePath),\n sourceCode,\n ts.ScriptTarget.Latest,\n true,\n )\n\n const imports: string[] = []\n\n function visit(node: ts.Node) {\n if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier)?.getFullText()\n if (moduleSpecifier) {\n const trimmed = moduleSpecifier.split(\"'\").at(1) ?? moduleSpecifier\n imports.push(trimmed)\n }\n }\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n\n const cleanedImports = imports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:')).map(getBasePackageName)\n\n for (const imp of cleanedImports) {\n importPaths[imp] = importPaths[imp] || []\n importPaths[imp].push(filePath)\n }\n\n return cleanedImports\n}\n\nfunction findFilesByGlob(cwd: string, pattern: string) {\n return globSync(pattern, { cwd, absolute: true })\n}\n\nfunction findFiles(path: string) {\n const allSourceInclude = ['./src/**/*.{ts,tsx}']\n const prodExcludeEndswith = ['.spec.ts', '.stories.tsx']\n const prodExcludeIncludes = ['/spec/', '/stories/', '/scripts/']\n const allSourceFiles = allSourceInclude.flatMap(pattern => findFilesByGlob(path, pattern))\n\n const prodSourceFiles = allSourceFiles.filter(file => !prodExcludeEndswith.some(ext => file.endsWith(ext))\n && !prodExcludeIncludes.some(excl => file.includes(excl)))\n\n const devSourceFiles = allSourceFiles.filter(file => !prodSourceFiles.includes(file))\n return {\n allSourceFiles, prodSourceFiles, devSourceFiles,\n }\n}\n\nfunction getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }: { devSourceFiles: string[]; prodSourceFiles: string[] }) {\n const prodImportPaths: Record<string, string[]> = {}\n const prodImports = prodSourceFiles.flatMap(path => getImportsFromFile(path, prodImportPaths))\n const devImportPaths: Record<string, string[]> = {}\n const devImports = devSourceFiles.flatMap(path => getImportsFromFile(path, devImportPaths))\n const externalProdImports = prodImports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:'))\n const externalDevImports = devImports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:'))\n return {\n prodImports, devImports, prodImportPaths, devImportPaths, externalProdImports, externalDevImports,\n }\n}\n\nfunction check({\n name, location, devDeps = false, peerDeps = false,\n}: { devDeps?: boolean; location: string; name: string; peerDeps?: boolean }) {\n const { prodSourceFiles, devSourceFiles } = findFiles(location)\n const {\n prodImportPaths, devImportPaths, externalProdImports, externalDevImports,\n } = getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles })\n\n const {\n dependencies, devDependencies, peerDependencies,\n } = getDependenciesFromPackageJson(`${location}/package.json`)\n\n let unlistedDependencies = 0\n let unlistedDevDependencies = 0\n let unusedDependencies = 0\n\n for (const imp of externalProdImports) {\n if (!dependencies.includes(imp) && !peerDependencies.includes(imp)) {\n unlistedDependencies++\n console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`)\n console.log(` ${prodImportPaths[imp].join('\\n')}`)\n console.log('')\n }\n }\n\n for (const dep of dependencies) {\n if (!externalProdImports.includes(dep)) {\n unusedDependencies++\n console.log(`[${chalk.blue(name)}] Unused dependency in package.json: ${chalk.red(dep)}`)\n console.log(` ${location}/package.json\\n`)\n console.log('')\n }\n }\n\n if (peerDeps) {\n for (const dep of peerDependencies) {\n if (!externalProdImports.includes(dep)) {\n unusedDependencies++\n console.log(`[${chalk.blue(name)}] Unused peerDependency in package.json: ${chalk.red(dep)}`)\n console.log(` ${location}/package.json\\n`)\n console.log('')\n }\n }\n }\n\n if (devDeps) {\n for (const imp of externalDevImports) {\n if (!devDependencies.includes(imp)) {\n unlistedDevDependencies++\n console.log(`[${chalk.blue(name)}] Missing devDependency in package.json: ${chalk.red(imp)}`)\n console.log(` Found in: ${devImportPaths[imp].join(', ')}`)\n }\n }\n }\n\n const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies\n\n return totalErrors\n}\n\nexport const deplint = ({ pkg }: { pkg: string }) => {\n if (pkg) {\n const { location, name } = yarnWorkspace(pkg)\n\n console.log(`Running Deplint for ${name}`)\n check({\n name, location, devDeps: true,\n })\n } else {\n const workspaces = yarnWorkspaces()\n\n console.log('Deplint Started...')\n\n let totalErrors = 0\n\n for (const workspace of workspaces) {\n totalErrors += check(workspace)\n }\n\n if (totalErrors > 0) {\n console.log(`Found ${chalk.red(totalErrors)} unlisted imports.`)\n } else {\n console.log(`No unlisted imports found. ${chalk.green('✔')}`)\n }\n }\n return 0\n}\n","import { spawnSync } from 'node:child_process'\n\nimport type { Workspace } from './Workspace.ts'\n\nexport const yarnWorkspaces = (): Workspace[] => {\n const result = spawnSync('yarn', ['workspaces', 'list', '--json', '--recursive'], { encoding: 'utf8', shell: true })\n if (result.error) {\n throw result.error\n }\n return (\n result.stdout\n .toString()\n // NOTE: This probably doesn't work on Windows\n // TODO: Replace /r/n with /n first\n .split('\\n')\n .slice(0, -1)\n .map((item) => {\n return JSON.parse(item)\n })\n )\n}\n","import type { Workspace } from './Workspace.ts'\nimport { yarnWorkspaces } from './yarnWorkspaces.ts'\n\nexport const yarnWorkspace = (pkg: string): Workspace => {\n const workspace = yarnWorkspaces().find(({ name }) => name === pkg)\n if (!workspace) throw new Error(`Workspace ${pkg} not found`)\n return workspace\n}\n"],"mappings":"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","names":["path"]}
1
+ {"version":3,"sources":["../../src/actions/deplint.ts","../../src/lib/yarn/workspace/yarnWorkspaces.ts","../../src/lib/yarn/workspace/yarnWorkspace.ts"],"sourcesContent":["/* eslint-disable complexity */\n/* eslint-disable max-statements */\nimport fs from 'node:fs'\nimport path from 'node:path'\n\nimport chalk from 'chalk'\nimport { globSync } from 'glob'\nimport ts from 'typescript'\n\nimport { yarnWorkspace, yarnWorkspaces } from '../lib/index.ts'\n\nfunction getDependenciesFromPackageJson(packageJsonPath: string) {\n const packageJsonFullPath = path.resolve(packageJsonPath)\n const rawContent = fs.readFileSync(packageJsonFullPath, 'utf8')\n const packageJson = JSON.parse(rawContent)\n\n const dependencies = packageJson.dependencies\n ? Object.keys(packageJson.dependencies)\n : []\n\n const devDependencies = packageJson.devDependencies\n ? Object.keys(packageJson.devDependencies)\n : []\n\n const peerDependencies = packageJson.peerDependencies\n ? Object.keys(packageJson.peerDependencies)\n : []\n\n return {\n dependencies, devDependencies, peerDependencies,\n }\n}\n\nfunction getBasePackageName(importName: string) {\n if (importName.startsWith('@')) {\n const parts = importName.split('/')\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : importName\n }\n return importName.split('/')[0]\n}\n\nfunction getImportsFromFile(filePath: string, importPaths: Record<string, string[]>, typeImportPaths: Record<string, string[]>) {\n const sourceCode = fs.readFileSync(filePath, 'utf8')\n\n const sourceFile = ts.createSourceFile(\n path.basename(filePath),\n sourceCode,\n ts.ScriptTarget.Latest,\n true,\n )\n\n const imports: string[] = []\n const typeImports: string[] = []\n\n function visit(node: ts.Node) {\n if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier)?.getFullText()\n const isTypeImport = ts.isImportDeclaration(node) ? (node.importClause?.isTypeOnly ?? false) : false\n if (moduleSpecifier) {\n const trimmed = moduleSpecifier.split(\"'\").at(1) ?? moduleSpecifier\n if (isTypeImport) {\n typeImports.push(trimmed)\n } else {\n imports.push(trimmed)\n }\n }\n } else if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {\n const [arg] = node.arguments\n if (ts.isStringLiteral(arg)) {\n const trimmed = arg.text\n imports.push(trimmed)\n }\n }\n ts.forEachChild(node, visit)\n }\n\n visit(sourceFile)\n\n const importsStartsWithExcludes = ['.', '#', 'node:']\n\n const cleanedImports = imports.filter(imp => !importsStartsWithExcludes.some(exc => imp.startsWith(exc))).map(getBasePackageName)\n const cleanedTypeImports = typeImports.filter(imp => !importsStartsWithExcludes.some(exc => imp.startsWith(exc))).map(getBasePackageName)\n\n for (const imp of cleanedImports) {\n importPaths[imp] = importPaths[imp] || []\n importPaths[imp].push(filePath)\n }\n\n for (const imp of cleanedTypeImports) {\n typeImportPaths[imp] = typeImportPaths[imp] || []\n typeImportPaths[imp].push(filePath)\n }\n\n return [cleanedImports, cleanedTypeImports]\n}\n\nfunction findFilesByGlob(cwd: string, pattern: string) {\n return globSync(pattern, { cwd, absolute: true })\n}\n\nfunction findFiles(path: string) {\n const allSourceInclude = ['./src/**/*.{ts,tsx}']\n const prodExcludeEndswith = ['.spec.ts', '.stories.tsx']\n const prodExcludeIncludes = ['/spec/', '/stories/', '/scripts/']\n const allSourceFiles = allSourceInclude.flatMap(pattern => findFilesByGlob(path, pattern))\n\n const prodSourceFiles = allSourceFiles.filter(file => !prodExcludeEndswith.some(ext => file.endsWith(ext))\n && !prodExcludeIncludes.some(excl => file.includes(excl)))\n\n const devSourceFiles = allSourceFiles.filter(file => !prodSourceFiles.includes(file))\n return {\n allSourceFiles, prodSourceFiles, devSourceFiles,\n }\n}\n\nfunction getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }: { devSourceFiles: string[]; prodSourceFiles: string[] }) {\n const prodImportPaths: Record<string, string[]> = {}\n const prodTypeImportPaths: Record<string, string[]> = {}\n const prodImportPairs = prodSourceFiles.map(path => getImportsFromFile(path, prodImportPaths, prodTypeImportPaths))\n const prodImports = prodImportPairs.flatMap(pair => pair[0])\n const prodTypeImports = prodImportPairs.flatMap(pair => pair[1])\n\n const devImportPaths: Record<string, string[]> = {}\n const devTypeImportPaths: Record<string, string[]> = {}\n const devImportPairs = devSourceFiles.map(path => getImportsFromFile(path, devImportPaths, devTypeImportPaths))\n const devImports = devImportPairs.flatMap(pair => pair[0])\n const devTypeImports = devImportPairs.flatMap(pair => pair[1])\n\n const externalProdImports = prodImports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:'))\n const externalProdTypeImports = prodTypeImports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:'))\n const externalDevImports = devImports.filter(imp => !imp.startsWith('.') && !imp.startsWith('#') && !imp.startsWith('node:'))\n return {\n prodImports, devImports, prodImportPaths, devImportPaths, externalProdImports, externalDevImports, prodTypeImports, devTypeImports, externalProdTypeImports,\n }\n}\n\nfunction check({\n name, location, devDeps = false, peerDeps = false,\n}: { devDeps?: boolean; location: string; name: string; peerDeps?: boolean }) {\n const { prodSourceFiles, devSourceFiles } = findFiles(location)\n const {\n prodImportPaths, externalProdTypeImports, devImportPaths, externalProdImports, externalDevImports,\n } = getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles })\n\n const {\n dependencies, devDependencies, peerDependencies,\n } = getDependenciesFromPackageJson(`${location}/package.json`)\n\n let unlistedDependencies = 0\n let unlistedDevDependencies = 0\n let unusedDependencies = 0\n let typesInDependencies = 0\n\n for (const imp of externalProdTypeImports) {\n if (!dependencies.includes(imp) && !peerDependencies.includes(imp) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`)) {\n unlistedDependencies++\n console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`)\n console.log(` ${prodImportPaths[imp].join('\\n')}`)\n console.log('')\n }\n }\n\n for (const imp of externalProdImports) {\n if (!dependencies.includes(imp) && !peerDependencies.includes(imp)) {\n unlistedDependencies++\n console.log(`[${chalk.blue(name)}] Missing dependency in package.json: ${chalk.red(imp)}`)\n console.log(` ${prodImportPaths[imp].join('\\n')}`)\n console.log('')\n }\n }\n\n for (const dep of dependencies) {\n if (dep.startsWith('@types/')) {\n typesInDependencies++\n console.log(`[${chalk.blue(name)}] @types in dependencies in package.json: ${chalk.red(dep)}`)\n console.log(` ${location}/package.json\\n`)\n console.log('')\n }\n if (!externalProdImports.includes(dep)) {\n unusedDependencies++\n console.log(`[${chalk.blue(name)}] Unused dependency in package.json: ${chalk.red(dep)}`)\n console.log(` ${location}/package.json\\n`)\n console.log('')\n }\n }\n\n if (peerDeps) {\n for (const dep of peerDependencies) {\n if (!externalProdImports.includes(dep)) {\n unusedDependencies++\n console.log(`[${chalk.blue(name)}] Unused peerDependency in package.json: ${chalk.red(dep)}`)\n console.log(` ${location}/package.json\\n`)\n console.log('')\n }\n }\n }\n\n if (devDeps) {\n for (const imp of externalDevImports) {\n if (!devDependencies.includes(imp)) {\n unlistedDevDependencies++\n console.log(`[${chalk.blue(name)}] Missing devDependency in package.json: ${chalk.red(imp)}`)\n console.log(` Found in: ${devImportPaths[imp].join(', ')}`)\n }\n }\n }\n\n const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies + typesInDependencies\n\n return totalErrors\n}\n\nexport const deplint = ({ pkg }: { pkg: string }) => {\n if (pkg) {\n const { location, name } = yarnWorkspace(pkg)\n\n console.log(`Running Deplint for ${name}`)\n check({\n name, location, devDeps: true,\n })\n } else {\n const workspaces = yarnWorkspaces()\n\n console.log('Deplint Started...')\n\n let totalErrors = 0\n\n for (const workspace of workspaces) {\n totalErrors += check(workspace)\n }\n\n if (totalErrors > 0) {\n console.log(`Found ${chalk.red(totalErrors)} unlisted imports.`)\n } else {\n console.log(`No unlisted imports found. ${chalk.green('✔')}`)\n }\n }\n return 0\n}\n","import { spawnSync } from 'node:child_process'\n\nimport type { Workspace } from './Workspace.ts'\n\nexport const yarnWorkspaces = (): Workspace[] => {\n const result = spawnSync('yarn', ['workspaces', 'list', '--json', '--recursive'], { encoding: 'utf8', shell: true })\n if (result.error) {\n throw result.error\n }\n return (\n result.stdout\n .toString()\n // NOTE: This probably doesn't work on Windows\n // TODO: Replace /r/n with /n first\n .split('\\n')\n .slice(0, -1)\n .map((item) => {\n return JSON.parse(item)\n })\n )\n}\n","import type { Workspace } from './Workspace.ts'\nimport { yarnWorkspaces } from './yarnWorkspaces.ts'\n\nexport const yarnWorkspace = (pkg: string): Workspace => {\n const workspace = yarnWorkspaces().find(({ name }) => name === pkg)\n if (!workspace) throw new Error(`Workspace ${pkg} not found`)\n return workspace\n}\n"],"mappings":"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","names":["path"]}
@@ -697,7 +697,7 @@ function getBasePackageName(importName) {
697
697
  }
698
698
  return importName.split("/")[0];
699
699
  }
700
- function getImportsFromFile(filePath, importPaths) {
700
+ function getImportsFromFile(filePath, importPaths, typeImportPaths) {
701
701
  const sourceCode = fs2.readFileSync(filePath, "utf8");
702
702
  const sourceFile = ts.createSourceFile(
703
703
  path3.basename(filePath),
@@ -706,23 +706,41 @@ function getImportsFromFile(filePath, importPaths) {
706
706
  true
707
707
  );
708
708
  const imports = [];
709
+ const typeImports = [];
709
710
  function visit(node) {
710
711
  if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
711
712
  const moduleSpecifier = node.moduleSpecifier?.getFullText();
713
+ const isTypeImport = ts.isImportDeclaration(node) ? node.importClause?.isTypeOnly ?? false : false;
712
714
  if (moduleSpecifier) {
713
715
  const trimmed = moduleSpecifier.split("'").at(1) ?? moduleSpecifier;
716
+ if (isTypeImport) {
717
+ typeImports.push(trimmed);
718
+ } else {
719
+ imports.push(trimmed);
720
+ }
721
+ }
722
+ } else if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {
723
+ const [arg] = node.arguments;
724
+ if (ts.isStringLiteral(arg)) {
725
+ const trimmed = arg.text;
714
726
  imports.push(trimmed);
715
727
  }
716
728
  }
717
729
  ts.forEachChild(node, visit);
718
730
  }
719
731
  visit(sourceFile);
720
- const cleanedImports = imports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:")).map(getBasePackageName);
732
+ const importsStartsWithExcludes = [".", "#", "node:"];
733
+ const cleanedImports = imports.filter((imp) => !importsStartsWithExcludes.some((exc) => imp.startsWith(exc))).map(getBasePackageName);
734
+ const cleanedTypeImports = typeImports.filter((imp) => !importsStartsWithExcludes.some((exc) => imp.startsWith(exc))).map(getBasePackageName);
721
735
  for (const imp of cleanedImports) {
722
736
  importPaths[imp] = importPaths[imp] || [];
723
737
  importPaths[imp].push(filePath);
724
738
  }
725
- return cleanedImports;
739
+ for (const imp of cleanedTypeImports) {
740
+ typeImportPaths[imp] = typeImportPaths[imp] || [];
741
+ typeImportPaths[imp].push(filePath);
742
+ }
743
+ return [cleanedImports, cleanedTypeImports];
726
744
  }
727
745
  function findFilesByGlob(cwd4, pattern) {
728
746
  return globSync(pattern, { cwd: cwd4, absolute: true });
@@ -742,10 +760,17 @@ function findFiles(path9) {
742
760
  }
743
761
  function getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }) {
744
762
  const prodImportPaths = {};
745
- const prodImports = prodSourceFiles.flatMap((path9) => getImportsFromFile(path9, prodImportPaths));
763
+ const prodTypeImportPaths = {};
764
+ const prodImportPairs = prodSourceFiles.map((path9) => getImportsFromFile(path9, prodImportPaths, prodTypeImportPaths));
765
+ const prodImports = prodImportPairs.flatMap((pair) => pair[0]);
766
+ const prodTypeImports = prodImportPairs.flatMap((pair) => pair[1]);
746
767
  const devImportPaths = {};
747
- const devImports = devSourceFiles.flatMap((path9) => getImportsFromFile(path9, devImportPaths));
768
+ const devTypeImportPaths = {};
769
+ const devImportPairs = devSourceFiles.map((path9) => getImportsFromFile(path9, devImportPaths, devTypeImportPaths));
770
+ const devImports = devImportPairs.flatMap((pair) => pair[0]);
771
+ const devTypeImports = devImportPairs.flatMap((pair) => pair[1]);
748
772
  const externalProdImports = prodImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
773
+ const externalProdTypeImports = prodTypeImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
749
774
  const externalDevImports = devImports.filter((imp) => !imp.startsWith(".") && !imp.startsWith("#") && !imp.startsWith("node:"));
750
775
  return {
751
776
  prodImports,
@@ -753,7 +778,10 @@ function getExternalImportsFromFiles({ prodSourceFiles, devSourceFiles }) {
753
778
  prodImportPaths,
754
779
  devImportPaths,
755
780
  externalProdImports,
756
- externalDevImports
781
+ externalDevImports,
782
+ prodTypeImports,
783
+ devTypeImports,
784
+ externalProdTypeImports
757
785
  };
758
786
  }
759
787
  function check({
@@ -765,6 +793,7 @@ function check({
765
793
  const { prodSourceFiles, devSourceFiles } = findFiles(location);
766
794
  const {
767
795
  prodImportPaths,
796
+ externalProdTypeImports,
768
797
  devImportPaths,
769
798
  externalProdImports,
770
799
  externalDevImports
@@ -777,6 +806,15 @@ function check({
777
806
  let unlistedDependencies = 0;
778
807
  let unlistedDevDependencies = 0;
779
808
  let unusedDependencies = 0;
809
+ let typesInDependencies = 0;
810
+ for (const imp of externalProdTypeImports) {
811
+ if (!dependencies.includes(imp) && !peerDependencies.includes(imp) && !devDependencies.includes(imp) && !devDependencies.includes(`@types/${imp}`)) {
812
+ unlistedDependencies++;
813
+ console.log(`[${chalk13.blue(name)}] Missing dependency in package.json: ${chalk13.red(imp)}`);
814
+ console.log(` ${prodImportPaths[imp].join("\n")}`);
815
+ console.log("");
816
+ }
817
+ }
780
818
  for (const imp of externalProdImports) {
781
819
  if (!dependencies.includes(imp) && !peerDependencies.includes(imp)) {
782
820
  unlistedDependencies++;
@@ -786,6 +824,13 @@ function check({
786
824
  }
787
825
  }
788
826
  for (const dep of dependencies) {
827
+ if (dep.startsWith("@types/")) {
828
+ typesInDependencies++;
829
+ console.log(`[${chalk13.blue(name)}] @types in dependencies in package.json: ${chalk13.red(dep)}`);
830
+ console.log(` ${location}/package.json
831
+ `);
832
+ console.log("");
833
+ }
789
834
  if (!externalProdImports.includes(dep)) {
790
835
  unusedDependencies++;
791
836
  console.log(`[${chalk13.blue(name)}] Unused dependency in package.json: ${chalk13.red(dep)}`);
@@ -814,7 +859,7 @@ function check({
814
859
  }
815
860
  }
816
861
  }
817
- const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies;
862
+ const totalErrors = unlistedDependencies + unlistedDevDependencies + unusedDependencies + typesInDependencies;
818
863
  return totalErrors;
819
864
  }
820
865
  var deplint = ({ pkg }) => {