imports-detector 0.1.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.
- package/README.md +669 -0
- package/bin/cli.js +2 -0
- package/dist/analyzer.d.ts +44 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +221 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +180 -0
- package/dist/cli.js.map +1 -0
- package/dist/extractor.d.ts +26 -0
- package/dist/extractor.d.ts.map +1 -0
- package/dist/extractor.js +239 -0
- package/dist/extractor.js.map +1 -0
- package/dist/file-discovery.d.ts +32 -0
- package/dist/file-discovery.d.ts.map +1 -0
- package/dist/file-discovery.js +81 -0
- package/dist/file-discovery.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/output/json-generator.d.ts +23 -0
- package/dist/output/json-generator.d.ts.map +1 -0
- package/dist/output/json-generator.js +55 -0
- package/dist/output/json-generator.js.map +1 -0
- package/dist/output/text-generator.d.ts +28 -0
- package/dist/output/text-generator.d.ts.map +1 -0
- package/dist/output/text-generator.js +92 -0
- package/dist/output/text-generator.js.map +1 -0
- package/dist/parser.d.ts +24 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +62 -0
- package/dist/parser.js.map +1 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
# Imports Detector
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/imports-detector)
|
|
4
|
+
[](https://www.npmjs.com/package/imports-detector)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/al-maqdi/imports-detector)
|
|
7
|
+
|
|
8
|
+
A powerful package for detecting and analyzing imports in JavaScript/TypeScript applications. Find files importing specific modules, list all imports, and generate comprehensive dependency reports.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- 📦 **Multiple Import Type Detection**
|
|
13
|
+
- Static ES6 imports (`import { x } from 'y'`)
|
|
14
|
+
- Dynamic imports (`import('y')`)
|
|
15
|
+
- Lazy imports (React.lazy, Next.js dynamic)
|
|
16
|
+
- CommonJS require statements (`require('y')`)
|
|
17
|
+
|
|
18
|
+
- 🔍 **Find Importers** - Find all files that import a specific module
|
|
19
|
+
- 📋 **List All Imports** - Comprehensive import analysis for entire projects
|
|
20
|
+
- 📊 **Multiple Output Formats** - JSON, text, and more
|
|
21
|
+
- ⚡ **Fast** - Uses Babel parser for efficient AST traversal
|
|
22
|
+
- 🎯 **TypeScript Support** - First-class TypeScript support
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
### Use with npx (No Installation Needed)
|
|
27
|
+
|
|
28
|
+
The easiest way to use imports-detector without installing anything:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx imports-detector find --module-path ./src/components/forms/RadioField.tsx ./src
|
|
32
|
+
npx imports-detector find Test ./src
|
|
33
|
+
npx imports-detector list ./src
|
|
34
|
+
npx imports-detector report ./src --output report.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Why npx?**
|
|
38
|
+
|
|
39
|
+
- ✅ No installation required
|
|
40
|
+
- ✅ Always uses the latest version
|
|
41
|
+
- ✅ Perfect for one-off analysis tasks
|
|
42
|
+
- ✅ No need to add to your project dependencies
|
|
43
|
+
|
|
44
|
+
### Install as a dev dependency (Recommended)
|
|
45
|
+
|
|
46
|
+
Install locally in your project for use in scripts and programmatic analysis:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install -D imports-detector
|
|
50
|
+
# or
|
|
51
|
+
yarn add -D imports-detector
|
|
52
|
+
# or
|
|
53
|
+
pnpm add -D imports-detector
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Why devDependency?**
|
|
57
|
+
|
|
58
|
+
- imports-detector is a development tool for code analysis
|
|
59
|
+
- It's not needed in production builds
|
|
60
|
+
- Similar to ESLint, Prettier, TypeScript, and testing frameworks
|
|
61
|
+
- Used during development for auditing and understanding dependencies
|
|
62
|
+
|
|
63
|
+
### Install globally for CLI use
|
|
64
|
+
|
|
65
|
+
Install globally to use the CLI across multiple projects:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install -g imports-detector
|
|
69
|
+
# or
|
|
70
|
+
yarn global add imports-detector
|
|
71
|
+
# or
|
|
72
|
+
pnpm add -g imports-detector
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Use global installation if you frequently run imports-detector from anywhere without installing it in each project.
|
|
76
|
+
|
|
77
|
+
## CLI Usage
|
|
78
|
+
|
|
79
|
+
### Find Files Importing a Specific Module
|
|
80
|
+
|
|
81
|
+
Find all files that import a specific module or component:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
imports-detector find Test ./src
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Example output:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
🔍 Found 2 files importing "Test"
|
|
91
|
+
|
|
92
|
+
./src/App.tsx
|
|
93
|
+
📦 ./components/Test (named): Test (line 2)
|
|
94
|
+
|
|
95
|
+
./src/pages/HomePage.tsx
|
|
96
|
+
📦 ../components/Test (default): Test (line 2)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Path-Specific Module Detection
|
|
100
|
+
|
|
101
|
+
Find files importing a module from a **specific path** (useful when you have multiple components with the same name):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Find files importing Dashboard specifically from the admin folder
|
|
105
|
+
imports-detector find Dashboard --module-path admin/Dashboard ./src
|
|
106
|
+
|
|
107
|
+
# Find files importing Test from components folder
|
|
108
|
+
imports-detector find Test --module-path components/Test ./src
|
|
109
|
+
|
|
110
|
+
# Find files importing Test using full path
|
|
111
|
+
imports-detector find Test --module-path src/components/Test ./src
|
|
112
|
+
|
|
113
|
+
# Find files importing Test from test fixtures
|
|
114
|
+
imports-detector find Test --module-path tests/fixtures/sample-project/src/components/Test ./src
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This is especially useful when you have multiple components with the same name:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
src/
|
|
121
|
+
├── admin/Dashboard.tsx ← Admin Dashboard
|
|
122
|
+
├── components/Dashboard.tsx ← User Dashboard
|
|
123
|
+
└── pages/
|
|
124
|
+
├── AdminPage.tsx ← Imports from admin/Dashboard ✅
|
|
125
|
+
└── UserPage.tsx ← Imports from components/Dashboard ✅
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Running `imports-detector find Dashboard --module-path admin/Dashboard ./src` will only find files that import from the `admin/Dashboard` path, not the `components/Dashboard` path.
|
|
129
|
+
|
|
130
|
+
##### Path Matching Examples
|
|
131
|
+
|
|
132
|
+
The `--module-path` option is flexible and supports various path formats:
|
|
133
|
+
|
|
134
|
+
**Example 1: Relative paths**
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Both of these will match imports from './admin/Dashboard'
|
|
138
|
+
imports-detector find Dashboard --module-path admin/Dashboard ./src
|
|
139
|
+
imports-detector find Dashboard --module-path ./admin/Dashboard ./src
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Example 2: Full paths**
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Using full path to the Test component
|
|
146
|
+
imports-detector find Test --module-path tests/fixtures/sample-project/src/components/Test ./src
|
|
147
|
+
|
|
148
|
+
# This will find:
|
|
149
|
+
# ✅ import { Test } from './components/Test'
|
|
150
|
+
# ✅ import { Test } from '../components/Test'
|
|
151
|
+
# ✅ import { Test } from '../../tests/fixtures/sample-project/src/components/Test'
|
|
152
|
+
# ❌ But NOT imports from './components/Button' or './utils/Test'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Example 3: Deeply nested paths**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Find imports from a deeply nested component
|
|
159
|
+
imports-detector find UserCard --module-path src/components/admin/users/UserCard ./src
|
|
160
|
+
|
|
161
|
+
# This matches:
|
|
162
|
+
# ✅ import { UserCard } from '../admin/users/UserCard'
|
|
163
|
+
# ✅ import { UserCard } from './components/admin/users/UserCard'
|
|
164
|
+
# ❌ But NOT from './components/users/UserCard' (missing 'admin')
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Example 4: Multiple components, same name**
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# You have:
|
|
171
|
+
# - src/components/Header.tsx
|
|
172
|
+
# - src/layouts/Header.tsx
|
|
173
|
+
# - src/admin/Header.tsx
|
|
174
|
+
|
|
175
|
+
# Find only imports of the admin Header:
|
|
176
|
+
imports-detector find Header --module-path src/admin/Header ./src
|
|
177
|
+
|
|
178
|
+
# Result: Only files importing from the admin/Header path
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Example 5: Test files**
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Find files importing a test utility
|
|
185
|
+
imports-detector find Test --module-path tests/fixtures/sample-project/src/components/Test ./src
|
|
186
|
+
|
|
187
|
+
# Or using relative path from search directory
|
|
188
|
+
imports-detector find Test --module-path components/Test ./src
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**How Path Matching Works:**
|
|
192
|
+
|
|
193
|
+
The path matching is intelligent and handles:
|
|
194
|
+
|
|
195
|
+
- ✅ Relative paths: `./admin/Dashboard`, `../admin/Dashboard`
|
|
196
|
+
- ✅ Absolute paths: `src/admin/Dashboard`, `/home/user/project/src/admin/Dashboard`
|
|
197
|
+
- ✅ Path normalization: `admin/Dashboard` matches `./admin/Dashboard` and `../admin/Dashboard`
|
|
198
|
+
- ✅ Case-insensitive matching: `Admin/Dashboard` matches `admin/dashboard`
|
|
199
|
+
- ✅ File extensions: Automatically stripped, so `Test.tsx` matches `Test`
|
|
200
|
+
|
|
201
|
+
**Pro Tips:**
|
|
202
|
+
|
|
203
|
+
1. **Use specific paths when you have duplicate names:**
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Good: Specific
|
|
207
|
+
imports-detector find Header --module-path src/layouts/Header ./src
|
|
208
|
+
|
|
209
|
+
# Less specific: May find too many results
|
|
210
|
+
imports-detector find Header ./src
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
2. **Match the import path format used in your code:**
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# If your code imports like: import { X } from '@/components/Test'
|
|
217
|
+
# Use: imports-detector find Test --module-path components/Test ./src
|
|
218
|
+
|
|
219
|
+
# If your code imports like: import { X } from '../../src/components/Test'
|
|
220
|
+
# Use: imports-detector find Test --module-path src/components/Test ./src
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
3. **Test with broader search first, then narrow down:**
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Step 1: See all Test imports
|
|
227
|
+
imports-detector find Test ./src
|
|
228
|
+
|
|
229
|
+
# Step 2: Narrow to specific path
|
|
230
|
+
imports-detector find Test --module-path components/Test ./src
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### List All Imports
|
|
234
|
+
|
|
235
|
+
List all imports in each file:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
imports-detector list ./src
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Example output:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
📦 Import Analysis Report
|
|
245
|
+
==================================================
|
|
246
|
+
|
|
247
|
+
Summary:
|
|
248
|
+
Total Files: 5
|
|
249
|
+
Total Imports: 9
|
|
250
|
+
Static: 8 | Dynamic: 0 | Lazy: 0 | Require: 1
|
|
251
|
+
|
|
252
|
+
--------------------------------------------------
|
|
253
|
+
|
|
254
|
+
./src/App.tsx
|
|
255
|
+
[STATIC] react (default): React (line 1)
|
|
256
|
+
[STATIC] ./components/Test (named): Test (line 2)
|
|
257
|
+
[STATIC] ./components/Button (named): Button (line 3)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Generate Reports
|
|
261
|
+
|
|
262
|
+
Generate a detailed report:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
imports-detector report ./src --output report.txt
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
JSON output:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
imports-detector report ./src --output report.json --format json
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### CLI Options
|
|
275
|
+
|
|
276
|
+
Global options:
|
|
277
|
+
|
|
278
|
+
- `--path <path>` - Root directory to analyze
|
|
279
|
+
- `--module-path <path>` - Specific module path to match (e.g., `admin/Dashboard`)
|
|
280
|
+
- `--include <patterns>` - File extensions to include (comma-separated)
|
|
281
|
+
- `--exclude <patterns>` - Patterns to exclude (comma-separated)
|
|
282
|
+
- `--format <format>` - Output format: json or text (default: text)
|
|
283
|
+
- `--output <file>` - Output file path
|
|
284
|
+
- `--no-static` - Exclude static imports
|
|
285
|
+
- `--no-dynamic` - Exclude dynamic imports
|
|
286
|
+
- `--no-lazy` - Exclude lazy imports
|
|
287
|
+
- `--no-require` - Exclude require calls
|
|
288
|
+
- `-v, --verbose` - Verbose output
|
|
289
|
+
|
|
290
|
+
Examples:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Find files importing React
|
|
294
|
+
imports-detector find React --path ./src
|
|
295
|
+
|
|
296
|
+
# Find files importing Dashboard from admin folder only
|
|
297
|
+
imports-detector find Dashboard --module-path admin/Dashboard --path ./src
|
|
298
|
+
|
|
299
|
+
# Export results to JSON
|
|
300
|
+
imports-detector find React --path ./src --include "**/*.tsx" --format json --output results.json
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
## Library API
|
|
304
|
+
|
|
305
|
+
### Basic Usage
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import {
|
|
309
|
+
ImportAnalyzer,
|
|
310
|
+
findFilesImporting,
|
|
311
|
+
analyzeProject,
|
|
312
|
+
} from 'imports-detector';
|
|
313
|
+
|
|
314
|
+
// Find files importing a specific module
|
|
315
|
+
const results = await findFilesImporting('Test', './src');
|
|
316
|
+
|
|
317
|
+
// Analyze entire project
|
|
318
|
+
const analysis = await analyzeProject('./src');
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### ImportAnalyzer Class
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
import { ImportAnalyzer } from 'imports-detector';
|
|
325
|
+
|
|
326
|
+
const analyzer = new ImportAnalyzer({
|
|
327
|
+
detectStatic: true,
|
|
328
|
+
detectDynamic: true,
|
|
329
|
+
detectLazy: true,
|
|
330
|
+
detectRequire: true,
|
|
331
|
+
includeExtensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
332
|
+
excludePatterns: ['**/node_modules/**'],
|
|
333
|
+
verbose: true,
|
|
334
|
+
modulePath: 'admin/Dashboard', // Optional: filter by specific path
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Find files importing a specific module
|
|
338
|
+
const results = await analyzer.findFilesImporting('Test', './src');
|
|
339
|
+
console.log(`Found ${results.length} files importing Test`);
|
|
340
|
+
|
|
341
|
+
// Find files importing from a specific path
|
|
342
|
+
const pathResults = await analyzer.findFilesImporting('Dashboard', './src');
|
|
343
|
+
// With modulePath set to 'admin/Dashboard', this only finds imports from admin/Dashboard
|
|
344
|
+
|
|
345
|
+
// Analyze entire project
|
|
346
|
+
const analysis = await analyzer.analyzeProject('./src');
|
|
347
|
+
console.log(`Total files: ${analysis.totalFiles}`);
|
|
348
|
+
console.log(`Total imports: ${analysis.totalImports}`);
|
|
349
|
+
|
|
350
|
+
// Analyze a single file
|
|
351
|
+
const fileImports = analyzer.analyzeFile('./src/App.tsx');
|
|
352
|
+
console.log('Static imports:', fileImports.static);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Output Formats
|
|
356
|
+
|
|
357
|
+
#### Find Results
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const results = await analyzer.findFilesImporting('Test', './src');
|
|
361
|
+
|
|
362
|
+
// Result structure:
|
|
363
|
+
[
|
|
364
|
+
{
|
|
365
|
+
file: '/path/to/App.tsx',
|
|
366
|
+
imports: [
|
|
367
|
+
{
|
|
368
|
+
module: './components/Test',
|
|
369
|
+
type: 'static',
|
|
370
|
+
line: 2,
|
|
371
|
+
column: 8,
|
|
372
|
+
specifiers: ['Test'],
|
|
373
|
+
kind: 'named',
|
|
374
|
+
raw: "import { Test } from './components/Test'",
|
|
375
|
+
},
|
|
376
|
+
],
|
|
377
|
+
},
|
|
378
|
+
];
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
#### Project Analysis
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
const analysis = await analyzer.analyzeProject('./src');
|
|
385
|
+
|
|
386
|
+
// Result structure:
|
|
387
|
+
{
|
|
388
|
+
totalFiles: 5,
|
|
389
|
+
totalImports: 9,
|
|
390
|
+
files: {
|
|
391
|
+
'/path/to/App.tsx': {
|
|
392
|
+
file: '/path/to/App.tsx',
|
|
393
|
+
static: [...],
|
|
394
|
+
dynamic: [...],
|
|
395
|
+
lazy: [...],
|
|
396
|
+
require: [...]
|
|
397
|
+
},
|
|
398
|
+
// ... more files
|
|
399
|
+
},
|
|
400
|
+
summary: {
|
|
401
|
+
static: 8,
|
|
402
|
+
dynamic: 0,
|
|
403
|
+
lazy: 0,
|
|
404
|
+
require: 1
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## API Reference
|
|
410
|
+
|
|
411
|
+
### Classes
|
|
412
|
+
|
|
413
|
+
#### `ImportAnalyzer`
|
|
414
|
+
|
|
415
|
+
Main analyzer class for detecting imports.
|
|
416
|
+
|
|
417
|
+
**Constructor Options:**
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
interface DetectorOptions {
|
|
421
|
+
includeExtensions?: string[]; // File extensions to scan
|
|
422
|
+
excludePatterns?: string[]; // Patterns to exclude
|
|
423
|
+
detectStatic?: boolean; // Detect static imports (default: true)
|
|
424
|
+
detectDynamic?: boolean; // Detect dynamic imports (default: true)
|
|
425
|
+
detectLazy?: boolean; // Detect lazy imports (default: true)
|
|
426
|
+
detectRequire?: boolean; // Detect require calls (default: true)
|
|
427
|
+
verbose?: boolean; // Enable verbose logging
|
|
428
|
+
modulePath?: string; // Specific module path to match (for path-specific filtering)
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
**Methods:**
|
|
433
|
+
|
|
434
|
+
- `findFilesImporting(moduleName: string, searchPath: string): Promise<ImporterResult[]>`
|
|
435
|
+
- `analyzeProject(searchPath: string): Promise<ProjectAnalysis>`
|
|
436
|
+
- `analyzeFile(filePath: string): FileImports`
|
|
437
|
+
|
|
438
|
+
### Types
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
enum ImportType {
|
|
442
|
+
STATIC = 'static',
|
|
443
|
+
DYNAMIC = 'dynamic',
|
|
444
|
+
LAZY = 'lazy',
|
|
445
|
+
REQUIRE = 'require',
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
interface Import {
|
|
449
|
+
module: string; // The module being imported
|
|
450
|
+
type: ImportType; // Type of import
|
|
451
|
+
line: number; // Line number
|
|
452
|
+
column: number; // Column number
|
|
453
|
+
specifiers?: string[]; // Imported specifiers
|
|
454
|
+
kind?: 'named' | 'default' | 'namespace';
|
|
455
|
+
raw?: string; // Raw import statement
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
interface FileImports {
|
|
459
|
+
file: string;
|
|
460
|
+
static: Import[];
|
|
461
|
+
dynamic: Import[];
|
|
462
|
+
lazy: Import[];
|
|
463
|
+
require: Import[];
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
interface ImporterResult {
|
|
467
|
+
file: string;
|
|
468
|
+
imports: Import[];
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
interface ProjectAnalysis {
|
|
472
|
+
totalFiles: number;
|
|
473
|
+
totalImports: number;
|
|
474
|
+
files: Record<string, FileImports>;
|
|
475
|
+
summary: {
|
|
476
|
+
static: number;
|
|
477
|
+
dynamic: number;
|
|
478
|
+
lazy: number;
|
|
479
|
+
require: number;
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Examples
|
|
485
|
+
|
|
486
|
+
### Example 1: Find all components using React
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { findFilesImporting } from 'imports-detector';
|
|
490
|
+
|
|
491
|
+
const results = await findFilesImporting('react', './src');
|
|
492
|
+
results.forEach((result) => {
|
|
493
|
+
console.log(`${result.file} imports React`);
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### Example 2: Find files importing a specific Test component
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
import { ImportAnalyzer } from 'imports-detector';
|
|
501
|
+
|
|
502
|
+
// Find files importing Test from components folder only
|
|
503
|
+
const analyzer = new ImportAnalyzer({
|
|
504
|
+
modulePath: 'components/Test',
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
const results = await analyzer.findFilesImporting('Test', './src');
|
|
508
|
+
console.log(
|
|
509
|
+
`Found ${results.length} files importing Test from components folder`,
|
|
510
|
+
);
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Example 3: Distinguish between multiple components with the same name
|
|
514
|
+
|
|
515
|
+
```typescript
|
|
516
|
+
import { ImportAnalyzer } from 'imports-detector';
|
|
517
|
+
|
|
518
|
+
// Scenario: You have multiple Dashboard components
|
|
519
|
+
// - src/admin/Dashboard.tsx
|
|
520
|
+
// - src/user/Dashboard.tsx
|
|
521
|
+
// - src/components/Dashboard.tsx
|
|
522
|
+
|
|
523
|
+
// Find only files importing the admin Dashboard
|
|
524
|
+
const adminAnalyzer = new ImportAnalyzer({
|
|
525
|
+
modulePath: 'src/admin/Dashboard',
|
|
526
|
+
});
|
|
527
|
+
const adminImports = await adminAnalyzer.findFilesImporting(
|
|
528
|
+
'Dashboard',
|
|
529
|
+
'./src',
|
|
530
|
+
);
|
|
531
|
+
|
|
532
|
+
// Find only files importing the user Dashboard
|
|
533
|
+
const userAnalyzer = new ImportAnalyzer({
|
|
534
|
+
modulePath: 'src/user/Dashboard',
|
|
535
|
+
});
|
|
536
|
+
const userImports = await userAnalyzer.findFilesImporting('Dashboard', './src');
|
|
537
|
+
|
|
538
|
+
console.log(`Admin Dashboard imported by ${adminImports.length} files`);
|
|
539
|
+
console.log(`User Dashboard imported by ${userImports.length} files`);
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### Example 4: Find unused components
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import { analyzeProject } from 'imports-detector';
|
|
546
|
+
|
|
547
|
+
const analysis = await analyzeProject('./src');
|
|
548
|
+
const componentFiles = Object.keys(analysis.files).filter((f) =>
|
|
549
|
+
f.includes('/components/'),
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
// Check if each component is imported elsewhere
|
|
553
|
+
for (const componentFile of componentFiles) {
|
|
554
|
+
const componentName = componentFile
|
|
555
|
+
.split('/')
|
|
556
|
+
.pop()
|
|
557
|
+
?.replace(/\.(tsx|ts)$/, '');
|
|
558
|
+
if (componentName) {
|
|
559
|
+
const importers = await findFilesImporting(componentName, './src');
|
|
560
|
+
if (importers.length === 0) {
|
|
561
|
+
console.log(`Component ${componentName} is not used anywhere`);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Example 3: Analyze import patterns
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { ImportAnalyzer } from 'imports-detector';
|
|
571
|
+
|
|
572
|
+
const analyzer = new ImportAnalyzer();
|
|
573
|
+
const analysis = await analyzer.analyzeProject('./src');
|
|
574
|
+
|
|
575
|
+
// Count lazy imports
|
|
576
|
+
const lazyImportCount = Object.values(analysis.files).reduce(
|
|
577
|
+
(sum, file) => sum + file.lazy.length,
|
|
578
|
+
0,
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
console.log(`Found ${lazyImportCount} lazy imports in the project`);
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
## Technical Details
|
|
585
|
+
|
|
586
|
+
### Supported Import Patterns
|
|
587
|
+
|
|
588
|
+
#### Static ES6 Imports
|
|
589
|
+
|
|
590
|
+
```javascript
|
|
591
|
+
import React from 'react';
|
|
592
|
+
import { useState } from 'react';
|
|
593
|
+
import * as Utils from './utils';
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
#### Dynamic Imports
|
|
597
|
+
|
|
598
|
+
```javascript
|
|
599
|
+
const module = await import('./module');
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
#### Lazy Imports
|
|
603
|
+
|
|
604
|
+
```javascript
|
|
605
|
+
// React.lazy
|
|
606
|
+
const LazyComponent = React.lazy(() => import('./Component'));
|
|
607
|
+
|
|
608
|
+
// Next.js dynamic
|
|
609
|
+
const DynamicComponent = dynamic(() => import('./Component'));
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
#### CommonJS Require
|
|
613
|
+
|
|
614
|
+
```javascript
|
|
615
|
+
const fs = require('fs');
|
|
616
|
+
const { readFile } = require('fs');
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### Dependencies
|
|
620
|
+
|
|
621
|
+
- @babel/parser - AST parsing
|
|
622
|
+
- @babel/traverse - AST traversal
|
|
623
|
+
- @babel/types - AST node utilities
|
|
624
|
+
- fast-glob - File pattern matching
|
|
625
|
+
- commander - CLI framework
|
|
626
|
+
|
|
627
|
+
## License
|
|
628
|
+
|
|
629
|
+
MIT
|
|
630
|
+
|
|
631
|
+
## Publishing to npm
|
|
632
|
+
|
|
633
|
+
If you want to publish your own version or fork:
|
|
634
|
+
|
|
635
|
+
### 1. Build the package
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
npm run build
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### 2. Login to npm
|
|
642
|
+
|
|
643
|
+
```bash
|
|
644
|
+
npm login
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### 3. Publish
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
npm publish
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
The package includes a `prepublishOnly` script that automatically builds before publishing.
|
|
654
|
+
|
|
655
|
+
### After Publishing
|
|
656
|
+
|
|
657
|
+
Once published, users can use your package with npx:
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
npx imports-detector find Test ./src
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
## Contributing
|
|
664
|
+
|
|
665
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
666
|
+
|
|
667
|
+
## Support
|
|
668
|
+
|
|
669
|
+
For issues and questions, please open an issue on GitHub.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DetectorOptions, FileImports, ImporterResult, ProjectAnalysis } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Main Analyzer Class
|
|
4
|
+
* Orchestrates file discovery, parsing, and import extraction
|
|
5
|
+
*/
|
|
6
|
+
export declare class ImportAnalyzer {
|
|
7
|
+
private fileDiscovery;
|
|
8
|
+
private parser;
|
|
9
|
+
private extractor;
|
|
10
|
+
private options;
|
|
11
|
+
constructor(options?: DetectorOptions);
|
|
12
|
+
/**
|
|
13
|
+
* Find all files that import a specific module
|
|
14
|
+
* @param moduleName - Name of the module to search for (e.g., 'Test', 'react')
|
|
15
|
+
* @param searchPath - Root directory to search
|
|
16
|
+
*/
|
|
17
|
+
findFilesImporting(moduleName: string, searchPath: string): Promise<ImporterResult[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Analyze all imports in a project
|
|
20
|
+
* @param searchPath - Root directory to analyze
|
|
21
|
+
*/
|
|
22
|
+
analyzeProject(searchPath: string): Promise<ProjectAnalysis>;
|
|
23
|
+
/**
|
|
24
|
+
* Get all imports from a specific file
|
|
25
|
+
*/
|
|
26
|
+
analyzeFile(filePath: string): FileImports;
|
|
27
|
+
/**
|
|
28
|
+
* Filter imports by module name
|
|
29
|
+
* Handles both named imports and file paths
|
|
30
|
+
* If modulePath is specified in options, also filters by import path
|
|
31
|
+
*/
|
|
32
|
+
private filterImportsByModule;
|
|
33
|
+
/**
|
|
34
|
+
* Check if an import module matches a specific path
|
|
35
|
+
* Supports both relative and absolute path matching
|
|
36
|
+
*/
|
|
37
|
+
private doesImportMatchPath;
|
|
38
|
+
/**
|
|
39
|
+
* Normalize module path for comparison
|
|
40
|
+
* Removes file extensions, leading ./ or ../, and normalizes separators
|
|
41
|
+
*/
|
|
42
|
+
private normalizeModulePath;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,cAAc,EACd,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,OAAO,CAAkB;gBAErB,OAAO,GAAE,eAAoB;IAqBzC;;;;OAIG;IACG,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IAqC5B;;;OAGG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAmDlE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW;IAc1C;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IA4B7B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAkD3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAM5B"}
|