license-checker-plugin 1.0.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/LICENSE +21 -0
- package/README.md +239 -0
- package/dist/LicensePluginCore.d.ts +84 -0
- package/dist/LicensePluginCore.js +148 -0
- package/dist/LicenseWebpackPlugin.d.ts +11 -0
- package/dist/LicenseWebpackPlugin.js +53 -0
- package/dist/Recorder.d.ts +14 -0
- package/dist/Recorder.js +46 -0
- package/dist/ViteLicensePlugin.d.ts +16 -0
- package/dist/ViteLicensePlugin.js +54 -0
- package/dist/checker/BuiltInLicenseChecker.d.ts +27 -0
- package/dist/checker/BuiltInLicenseChecker.js +311 -0
- package/dist/checker/LicenseCache.d.ts +9 -0
- package/dist/checker/LicenseCache.js +22 -0
- package/dist/checker/LicenseDatabase.d.ts +8 -0
- package/dist/checker/LicenseDatabase.js +52 -0
- package/dist/formatter/Formatter.d.ts +4 -0
- package/dist/formatter/Formatter.js +2 -0
- package/dist/formatter/HtmlFormatter.d.ts +6 -0
- package/dist/formatter/HtmlFormatter.js +53 -0
- package/dist/formatter/JsonFormatter.d.ts +5 -0
- package/dist/formatter/JsonFormatter.js +17 -0
- package/dist/formatter/MarkdownFormatter.d.ts +5 -0
- package/dist/formatter/MarkdownFormatter.js +18 -0
- package/dist/formatter/TxtFormatter.d.ts +12 -0
- package/dist/formatter/TxtFormatter.js +49 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +13 -0
- package/dist/model/LicenseBuildReport.d.ts +4 -0
- package/dist/model/LicenseBuildReport.js +2 -0
- package/dist/model/LicenseInfo.d.ts +17 -0
- package/dist/model/LicenseInfo.js +2 -0
- package/dist/model/PackageInfo.d.ts +13 -0
- package/dist/model/PackageInfo.js +2 -0
- package/dist/scanner/PackageResolver.d.ts +4 -0
- package/dist/scanner/PackageResolver.js +102 -0
- package/dist/scanner/PackageScanner.d.ts +9 -0
- package/dist/scanner/PackageScanner.js +56 -0
- package/dist/utils/fs.d.ts +3 -0
- package/dist/utils/fs.js +61 -0
- package/dist/utils/hash.d.ts +1 -0
- package/dist/utils/hash.js +7 -0
- package/dist/utils/path.d.ts +3 -0
- package/dist/utils/path.js +64 -0
- package/package.json +58 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface PackageInfo {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
path: string;
|
|
5
|
+
packageJsonPath: string;
|
|
6
|
+
chunks: string[];
|
|
7
|
+
modules: string[];
|
|
8
|
+
repository?: string;
|
|
9
|
+
homepage?: string;
|
|
10
|
+
author?: string;
|
|
11
|
+
publisher?: string;
|
|
12
|
+
private?: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PackageResolver = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const BuiltInLicenseChecker_1 = require("../checker/BuiltInLicenseChecker");
|
|
40
|
+
class PackageResolver {
|
|
41
|
+
resolve(modulePath, chunkName) {
|
|
42
|
+
if (!modulePath || !modulePath.includes('node_modules')) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const normalizedPath = modulePath.replace(/\\/g, '/');
|
|
46
|
+
const nodeModulesIdx = normalizedPath.lastIndexOf('/node_modules/');
|
|
47
|
+
if (nodeModulesIdx === -1) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const afterNodeModules = normalizedPath.slice(nodeModulesIdx + '/node_modules/'.length);
|
|
51
|
+
let packageName;
|
|
52
|
+
if (afterNodeModules.startsWith('@')) {
|
|
53
|
+
const parts = afterNodeModules.split('/');
|
|
54
|
+
if (parts.length < 2) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
packageName = `${parts[0]}/${parts[1]}`;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const [name] = afterNodeModules.split('/');
|
|
61
|
+
if (!name) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
packageName = name;
|
|
65
|
+
}
|
|
66
|
+
const packageRoot = path.join(normalizedPath.slice(0, nodeModulesIdx + '/node_modules/'.length).replace(/\//g, path.sep), packageName.replace(/\//g, path.sep));
|
|
67
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
68
|
+
try {
|
|
69
|
+
const rawContent = fs.readFileSync(packageJsonPath, 'utf-8');
|
|
70
|
+
const pkg = JSON.parse(rawContent);
|
|
71
|
+
let repository;
|
|
72
|
+
if (pkg.repository) {
|
|
73
|
+
if (typeof pkg.repository === 'string') {
|
|
74
|
+
repository = (0, BuiltInLicenseChecker_1.normalizeRepositoryUrl)(pkg.repository);
|
|
75
|
+
}
|
|
76
|
+
else if (typeof pkg.repository === 'object' && pkg.repository.url) {
|
|
77
|
+
repository = (0, BuiltInLicenseChecker_1.normalizeRepositoryUrl)(pkg.repository.url);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const parsed = (0, BuiltInLicenseChecker_1.parseAuthor)(pkg.author);
|
|
81
|
+
const publisher = parsed.name;
|
|
82
|
+
const author = parsed.email ? `${parsed.name || ''} <${parsed.email}>`.trim() : parsed.name;
|
|
83
|
+
return {
|
|
84
|
+
name: pkg.name || packageName,
|
|
85
|
+
version: pkg.version || 'unknown',
|
|
86
|
+
path: packageRoot,
|
|
87
|
+
packageJsonPath,
|
|
88
|
+
chunks: [chunkName],
|
|
89
|
+
modules: [modulePath],
|
|
90
|
+
repository,
|
|
91
|
+
homepage: pkg.homepage,
|
|
92
|
+
author,
|
|
93
|
+
publisher,
|
|
94
|
+
private: pkg.private === true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.PackageResolver = PackageResolver;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Compilation } from 'webpack';
|
|
2
|
+
import { PackageInfo } from '../model/PackageInfo';
|
|
3
|
+
export declare class PackageScanner {
|
|
4
|
+
private readonly resolver;
|
|
5
|
+
constructor();
|
|
6
|
+
scan(compilation: Compilation): Map<string, PackageInfo>;
|
|
7
|
+
private getChunkModules;
|
|
8
|
+
private getModuleResource;
|
|
9
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PackageScanner = void 0;
|
|
4
|
+
const PackageResolver_1 = require("./PackageResolver");
|
|
5
|
+
function isNormalModuleShape(module) {
|
|
6
|
+
return 'resource' in module || 'userRequest' in module;
|
|
7
|
+
}
|
|
8
|
+
class PackageScanner {
|
|
9
|
+
resolver;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.resolver = new PackageResolver_1.PackageResolver();
|
|
12
|
+
}
|
|
13
|
+
scan(compilation) {
|
|
14
|
+
const packages = new Map();
|
|
15
|
+
for (const chunk of compilation.chunks) {
|
|
16
|
+
const chunkName = chunk.name || String(chunk.id ?? 'unknown');
|
|
17
|
+
for (const module of this.getChunkModules(compilation, chunk)) {
|
|
18
|
+
const resource = this.getModuleResource(module);
|
|
19
|
+
if (!resource) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const pkgInfo = this.resolver.resolve(resource, chunkName);
|
|
23
|
+
if (!pkgInfo) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const key = `${pkgInfo.name}@${pkgInfo.version}`;
|
|
27
|
+
const existing = packages.get(key);
|
|
28
|
+
if (existing) {
|
|
29
|
+
if (!existing.chunks.includes(chunkName)) {
|
|
30
|
+
existing.chunks.push(chunkName);
|
|
31
|
+
}
|
|
32
|
+
if (!existing.modules.includes(resource)) {
|
|
33
|
+
existing.modules.push(resource);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
packages.set(key, pkgInfo);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return packages;
|
|
42
|
+
}
|
|
43
|
+
getChunkModules(compilation, chunk) {
|
|
44
|
+
return compilation.chunkGraph.getChunkModulesIterable(chunk);
|
|
45
|
+
}
|
|
46
|
+
getModuleResource(module) {
|
|
47
|
+
if (!isNormalModuleShape(module))
|
|
48
|
+
return null;
|
|
49
|
+
return (module.resource ||
|
|
50
|
+
module.userRequest ||
|
|
51
|
+
module.rootModule?.resource ||
|
|
52
|
+
module.rootModule?.userRequest ||
|
|
53
|
+
null);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.PackageScanner = PackageScanner;
|
package/dist/utils/fs.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.readFileIfExists = readFileIfExists;
|
|
37
|
+
exports.readJsonFile = readJsonFile;
|
|
38
|
+
exports.findFileInDir = findFileInDir;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
function readFileIfExists(filePath) {
|
|
42
|
+
try {
|
|
43
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
44
|
+
}
|
|
45
|
+
catch (_a) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function readJsonFile(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
52
|
+
return JSON.parse(content);
|
|
53
|
+
}
|
|
54
|
+
catch (_a) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function findFileInDir(dir, filename) {
|
|
59
|
+
const filePath = path.join(dir, filename);
|
|
60
|
+
return fs.existsSync(filePath) ? filePath : null;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hashString(str: string): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.findPackageRoot = findPackageRoot;
|
|
37
|
+
exports.isNodeModule = isNodeModule;
|
|
38
|
+
exports.getNodeModuleName = getNodeModuleName;
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const fs_1 = require("./fs");
|
|
41
|
+
function findPackageRoot(modulePath) {
|
|
42
|
+
let dir = path.dirname(modulePath);
|
|
43
|
+
const root = path.parse(dir).root;
|
|
44
|
+
while (dir !== root) {
|
|
45
|
+
const pkgJsonPath = path.join(dir, 'package.json');
|
|
46
|
+
const pkg = (0, fs_1.readJsonFile)(pkgJsonPath);
|
|
47
|
+
if (pkg && typeof pkg.name === 'string' && dir.includes('node_modules')) {
|
|
48
|
+
return dir;
|
|
49
|
+
}
|
|
50
|
+
const parent = path.dirname(dir);
|
|
51
|
+
if (parent === dir) {
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
dir = parent;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function isNodeModule(filePath) {
|
|
59
|
+
return filePath.includes('node_modules');
|
|
60
|
+
}
|
|
61
|
+
function getNodeModuleName(filePath) {
|
|
62
|
+
const match = filePath.match(/node_modules[\\/]((?:@[^\\/]+[\\/])?[^\\/]+)/);
|
|
63
|
+
return match ? match[1] : null;
|
|
64
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "license-checker-plugin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A bundler-agnostic plugin to generate third-party license notices for bundled packages. Supports webpack 5, Rspack, and Vite.",
|
|
5
|
+
"author": "Axetroy <axetroy.dev@gmail.com>",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/axetroy/license-checker-plugin"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/axetroy/license-checker-plugin",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/axetroy/license-checker-plugin/issues"
|
|
13
|
+
},
|
|
14
|
+
"main": "dist/index.js",
|
|
15
|
+
"types": "dist/index.d.ts",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc --project tsconfig.build.json",
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"test:webpack": "jest --testPathPattern=tests/integration/webpack/",
|
|
23
|
+
"test:rspack": "jest --testPathPattern=tests/integration/rspack/",
|
|
24
|
+
"test:vite": "jest --testPathPattern=tests/integration/vite/",
|
|
25
|
+
"lint": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"webpack",
|
|
29
|
+
"license",
|
|
30
|
+
"plugin",
|
|
31
|
+
"third-party",
|
|
32
|
+
"compliance"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20.0.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"webpack": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@rspack/core": "^1.7.12",
|
|
43
|
+
"@types/jest": "^29.5.14",
|
|
44
|
+
"@types/node": "^22.0.0",
|
|
45
|
+
"@types/spdx-expression-parse": "^4.0.0",
|
|
46
|
+
"css-loader": "^7.1.4",
|
|
47
|
+
"jest": "^29.7.0",
|
|
48
|
+
"lodash": "^4.17.21",
|
|
49
|
+
"ts-jest": "^29.1.5",
|
|
50
|
+
"typescript": "^5.5.4",
|
|
51
|
+
"vite": "^8.1.3",
|
|
52
|
+
"webpack": "^5.93.0",
|
|
53
|
+
"webpack-sources": "^3.2.3"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"spdx-expression-parse": "^4.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|