0
# License Scanning
1
2
Core license analysis functionality that scans package dependency trees and extracts comprehensive license information from multiple sources including package.json files, license files, and README content.
3
4
## Capabilities
5
6
### Main Scanning Function
7
8
The primary function for initiating license analysis across a package dependency tree.
9
10
```javascript { .api }
11
/**
12
* Initialize license scanning for a given directory
13
* @param options - Configuration options for the scan
14
* @param callback - Callback function receiving results or errors
15
*/
16
function init(options: ScanOptions, callback: (err: Error | null, data: LicenseData) => void): void;
17
18
interface ScanOptions {
19
/** Directory to start scanning from (default: process.cwd()) */
20
start?: string;
21
/** Only include production dependencies */
22
production?: boolean;
23
/** Only include development dependencies */
24
development?: boolean;
25
/** Report guessed licenses as unknown */
26
unknown?: boolean;
27
/** Only list packages with unknown or guessed licenses */
28
onlyunknown?: boolean;
29
/** Look for direct dependencies only (not transitive) */
30
direct?: boolean;
31
/** Custom output format specification */
32
customFormat?: CustomFormat;
33
/** Path to custom format JSON file */
34
customPath?: string;
35
/** Comma-separated list of licenses to exclude from output */
36
exclude?: string;
37
/** Semicolon-separated list of licenses that cause failure (exit code 1) */
38
failOn?: string;
39
/** Semicolon-separated list of only allowed licenses (others cause failure) */
40
onlyAllow?: string;
41
/** Semicolon-separated list of specific packages to include */
42
packages?: string;
43
/** Semicolon-separated list of packages to exclude */
44
excludePackages?: string;
45
/** Exclude packages marked as private */
46
excludePrivatePackages?: boolean;
47
/** Output license file paths as relative to base path */
48
relativeLicensePath?: boolean;
49
/** Enable colored output for terminal display */
50
color?: boolean;
51
}
52
```
53
54
**Usage Examples:**
55
56
```javascript
57
const checker = require("license-checker");
58
59
// Basic scan of current directory
60
checker.init({
61
start: process.cwd()
62
}, function(err, packages) {
63
if (err) {
64
console.error("Error:", err);
65
} else {
66
console.log("Found", Object.keys(packages).length, "packages");
67
console.log(packages);
68
}
69
});
70
71
// Production dependencies only with custom format
72
checker.init({
73
start: "./my-project",
74
production: true,
75
customFormat: {
76
name: "",
77
version: "",
78
licenses: "",
79
repository: ""
80
}
81
}, function(err, packages) {
82
if (err) throw err;
83
Object.keys(packages).forEach(key => {
84
const pkg = packages[key];
85
console.log(`${pkg.name}@${pkg.version}: ${pkg.licenses}`);
86
});
87
});
88
89
// Exclude specific licenses
90
checker.init({
91
start: process.cwd(),
92
exclude: "MIT,ISC,BSD-3-Clause"
93
}, function(err, packages) {
94
// Only packages NOT licensed under MIT, ISC, or BSD-3-Clause
95
console.log(packages);
96
});
97
98
// Fail on GPL licenses
99
checker.init({
100
start: process.cwd(),
101
failOn: "GPL-2.0;GPL-3.0;LGPL-2.1"
102
}, function(err, packages) {
103
// Process will exit with code 1 if any GPL licenses found
104
console.log(packages);
105
});
106
107
// Only allow specific licenses
108
checker.init({
109
start: process.cwd(),
110
onlyAllow: "MIT;Apache-2.0;BSD-3-Clause"
111
}, function(err, packages) {
112
// Process will exit with code 1 if any other licenses found
113
console.log(packages);
114
});
115
```
116
117
### License Detection
118
119
The scanning engine uses multiple strategies to detect license information:
120
121
1. **package.json fields**: Checks `license` and `licenses` fields
122
2. **SPDX expressions**: Parses and validates SPDX license expressions
123
3. **License files**: Scans for LICENSE, LICENCE, COPYING files with pattern matching
124
4. **README content**: Extracts license information from README files when other sources unavailable
125
5. **Pattern matching**: Uses regex patterns to identify common license texts
126
127
**License File Precedence:**
128
1. `LICENSE` (exact match)
129
2. `LICENSE-*` (e.g., LICENSE-MIT)
130
3. `LICENCE` (exact match)
131
4. `LICENCE-*` (e.g., LICENCE-MIT)
132
5. `COPYING`
133
6. `README`
134
135
### Data Structure
136
137
The callback receives license data organized by package identifier:
138
139
```javascript { .api }
140
interface LicenseData {
141
[packageKey: string]: PackageInfo;
142
}
143
144
interface PackageInfo {
145
/** License identifier(s) - string for single license, array for multiple */
146
licenses: string | string[];
147
/** Git repository URL (normalized from various formats) */
148
repository?: string;
149
/** Package author/publisher name */
150
publisher?: string;
151
/** Author email address */
152
email?: string;
153
/** Author or package homepage URL */
154
url?: string;
155
/** Local filesystem path to the package */
156
path?: string;
157
/** Path to the license file (absolute or relative based on options) */
158
licenseFile?: string;
159
/** Full text content of the license file */
160
licenseText?: string;
161
/** Extracted copyright statements from license files */
162
copyright?: string;
163
/** Path to NOTICE file if present */
164
noticeFile?: string;
165
/** Whether the package is marked as private */
166
private?: boolean;
167
/** Dependency path information (when unknown option is enabled) */
168
dependencyPath?: string;
169
}
170
```
171
172
Package keys follow the format: `package-name@version`
173
174
**Example output:**
175
176
```javascript
177
{
178
"license-checker@25.0.1": {
179
"licenses": "BSD-3-Clause",
180
"repository": "https://github.com/davglass/license-checker",
181
"publisher": "Dav Glass",
182
"email": "davglass@gmail.com",
183
"path": "/path/to/node_modules/license-checker",
184
"licenseFile": "/path/to/node_modules/license-checker/LICENSE"
185
},
186
"chalk@2.4.2": {
187
"licenses": "MIT",
188
"repository": "https://github.com/chalk/chalk",
189
"publisher": "Sindre Sorhus",
190
"email": "sindresorhus@gmail.com",
191
"url": "sindresorhus.com",
192
"path": "/path/to/node_modules/chalk",
193
"licenseFile": "/path/to/node_modules/chalk/license"
194
}
195
}
196
```
197
198
### Error Handling
199
200
The scanning function handles various error conditions:
201
202
- **No packages found**: Returns error if no valid packages detected in scan path
203
- **Invalid SPDX expressions**: Attempts correction or reports as "Custom:" format
204
- **Missing license information**: Reports as "UNKNOWN" when no license data found
205
- **Private packages**: Reports as "UNLICENSED" when package.json has `"private": true`
206
- **Circular dependencies**: Prevents infinite recursion in dependency trees
207
- **File system errors**: Handles missing directories, permission issues, unreadable files
208
209
### Custom Formatting
210
211
The `customFormat` option allows extracting additional fields from package.json:
212
213
```javascript
214
checker.init({
215
start: process.cwd(),
216
customFormat: {
217
"name": "", // Extract package name
218
"version": "", // Extract package version
219
"description": "", // Extract package description
220
"homepage": "", // Extract homepage URL
221
"author": "", // Extract author information
222
"keywords": [], // Extract keywords array
223
"licenseText": false, // Include full license text
224
"copyright": false // Include copyright extraction
225
}
226
}, callback);
227
```
228
229
Fields set to `false` exclude that field from output. Fields with default values use the package.json value if available, otherwise use the default.