@callstack/licenses 0.2.2 → 0.3.1
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 +1 -1
- package/build/constants/index.d.ts +1 -0
- package/build/constants/index.js +17 -0
- package/build/constants/licenses.d.ts +7 -0
- package/build/constants/licenses.js +53 -0
- package/build/index.d.ts +2 -1
- package/build/index.js +5 -4
- package/build/licenses/LicenseCategory.d.ts +6 -0
- package/build/licenses/LicenseCategory.js +10 -0
- package/build/licenses/descriptions.d.ts +16 -0
- package/build/licenses/descriptions.js +53 -0
- package/build/licenses/index.d.ts +3 -0
- package/build/licenses/index.js +19 -0
- package/build/licenses/licenseAnalysis.d.ts +15 -0
- package/build/licenses/licenseAnalysis.js +65 -0
- package/build/{common.d.ts → node/common.d.ts} +6 -6
- package/build/{common.js → node/common.js} +108 -60
- package/build/node/index.d.ts +3 -0
- package/build/node/index.js +19 -0
- package/build/node/utils/index.d.ts +2 -0
- package/build/node/utils/index.js +38 -0
- package/build/{utils → node/utils}/packageUtils.d.ts +2 -2
- package/build/{utils → node/utils}/packageUtils.js +1 -1
- package/build/types/AggregatedLicensesMapping.d.ts +6 -0
- package/build/types/{LicenseObj.d.ts → License.d.ts} +8 -2
- package/build/types/LicenseAnalysisResult.d.ts +5 -0
- package/build/types/LicenseAnalysisResult.js +2 -0
- package/build/types/LicenseStats.d.ts +28 -0
- package/build/types/LicenseStats.js +2 -0
- package/build/types/ParentPackageInfo.d.ts +14 -0
- package/build/types/ParentPackageInfo.js +2 -0
- package/build/types/index.d.ts +5 -2
- package/build/types/index.js +5 -2
- package/build/utils/index.d.ts +0 -2
- package/build/utils/index.js +1 -3
- package/package.json +20 -7
- package/src/constants/index.ts +1 -0
- package/src/constants/licenses.ts +58 -0
- package/src/index.ts +2 -1
- package/src/licenses/LicenseCategory.ts +6 -0
- package/src/licenses/descriptions.ts +56 -0
- package/src/licenses/index.ts +3 -0
- package/src/licenses/licenseAnalysis.ts +78 -0
- package/src/{common.ts → node/common.ts} +104 -45
- package/src/node/index.ts +3 -0
- package/src/node/utils/index.ts +2 -0
- package/src/{utils → node/utils}/packageUtils.ts +3 -3
- package/src/types/AggregatedLicensesMapping.ts +7 -0
- package/src/types/{LicenseObj.ts → License.ts} +9 -2
- package/src/types/LicenseAnalysisResult.ts +7 -0
- package/src/types/LicenseStats.ts +33 -0
- package/src/types/ParentPackageInfo.ts +16 -0
- package/src/types/index.ts +5 -2
- package/src/utils/index.ts +0 -2
- package/build/types/AggregatedLicensesObj.d.ts +0 -6
- package/src/types/AggregatedLicensesObj.ts +0 -7
- /package/build/{utils → node/utils}/miscUtils.d.ts +0 -0
- /package/build/{utils → node/utils}/miscUtils.js +0 -0
- /package/build/types/{AggregatedLicensesObj.js → AggregatedLicensesMapping.js} +0 -0
- /package/build/types/{LicenseObj.js → License.js} +0 -0
- /package/src/{utils → node/utils}/miscUtils.ts +0 -0
package/README.md
CHANGED
|
@@ -30,10 +30,10 @@ You can use `@callstack/licenses` programmatically in your Node.js applications.
|
|
|
30
30
|
|
|
31
31
|
```typescript
|
|
32
32
|
import {
|
|
33
|
+
Types,
|
|
33
34
|
generateAboutLibrariesNPMOutput,
|
|
34
35
|
generateLicensePlistNPMOutput,
|
|
35
36
|
scanDependencies,
|
|
36
|
-
Types,
|
|
37
37
|
} from '@callstack/licenses';
|
|
38
38
|
import * as md from 'ts-markdown-builder';
|
|
39
39
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './licenses';
|
|
@@ -0,0 +1,17 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./licenses"), exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* https://spdx.org/licenses
|
|
3
|
+
*/
|
|
4
|
+
export declare const STRONG_COPYLEFT_LICENSES: Set<string>;
|
|
5
|
+
export declare const WEAK_COPYLEFT_LICENSES: Set<string>;
|
|
6
|
+
export declare const STRONG_COPYLEFT_LICENSES_LOWERCASE: Set<string>;
|
|
7
|
+
export declare const WEAK_COPYLEFT_LICENSES_LOWERCASE: Set<string>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* https://spdx.org/licenses
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.WEAK_COPYLEFT_LICENSES_LOWERCASE = exports.STRONG_COPYLEFT_LICENSES_LOWERCASE = exports.WEAK_COPYLEFT_LICENSES = exports.STRONG_COPYLEFT_LICENSES = void 0;
|
|
7
|
+
exports.STRONG_COPYLEFT_LICENSES = new Set([
|
|
8
|
+
'GPL',
|
|
9
|
+
'GPL-1.0',
|
|
10
|
+
'GPL-1.0+',
|
|
11
|
+
'GPL-2.0',
|
|
12
|
+
'GPL-2.0+',
|
|
13
|
+
'GPL-2.0-only',
|
|
14
|
+
'GPL-2.0-or-later',
|
|
15
|
+
'GPL-3.0',
|
|
16
|
+
'GPL-3.0+',
|
|
17
|
+
'GPL-3.0-only',
|
|
18
|
+
'GPL-3.0-or-later',
|
|
19
|
+
'AGPL-3.0',
|
|
20
|
+
'AGPL-3.0-only',
|
|
21
|
+
'AGPL-3.0-or-later',
|
|
22
|
+
'EUPL-1.0',
|
|
23
|
+
'EUPL-1.1',
|
|
24
|
+
'EUPL-1.2',
|
|
25
|
+
'OSL-1.0',
|
|
26
|
+
'OSL-1.1',
|
|
27
|
+
'OSL-2.0',
|
|
28
|
+
'OSL-2.1',
|
|
29
|
+
'OSL-3.0',
|
|
30
|
+
]);
|
|
31
|
+
exports.WEAK_COPYLEFT_LICENSES = new Set([
|
|
32
|
+
'CDDL-1.0',
|
|
33
|
+
'CDDL-1.1',
|
|
34
|
+
'EPL-1.0',
|
|
35
|
+
'EPL-2.0',
|
|
36
|
+
'LGPL',
|
|
37
|
+
'LGPL-2.0',
|
|
38
|
+
'LGPL-2.0+',
|
|
39
|
+
'LGPL-2.0-only',
|
|
40
|
+
'LGPL-2.0-or-later',
|
|
41
|
+
'LGPL-2.1',
|
|
42
|
+
'LGPL-2.1+',
|
|
43
|
+
'LGPL-2.1-only',
|
|
44
|
+
'LGPL-2.1-or-later',
|
|
45
|
+
'LGPL-3.0',
|
|
46
|
+
'LGPL-3.0+',
|
|
47
|
+
'LGPL-3.0-only',
|
|
48
|
+
'LGPL-3.0-or-later',
|
|
49
|
+
'MPL-1.1',
|
|
50
|
+
'MPL-2.0',
|
|
51
|
+
]);
|
|
52
|
+
exports.STRONG_COPYLEFT_LICENSES_LOWERCASE = new Set(Array.from(exports.STRONG_COPYLEFT_LICENSES).map((license) => license.toLowerCase()));
|
|
53
|
+
exports.WEAK_COPYLEFT_LICENSES_LOWERCASE = new Set(Array.from(exports.WEAK_COPYLEFT_LICENSES).map((license) => license.toLowerCase()));
|
package/build/index.d.ts
CHANGED
package/build/index.js
CHANGED
|
@@ -15,9 +15,6 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
-
};
|
|
21
18
|
var __importStar = (this && this.__importStar) || (function () {
|
|
22
19
|
var ownKeys = function(o) {
|
|
23
20
|
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
@@ -35,8 +32,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
32
|
return result;
|
|
36
33
|
};
|
|
37
34
|
})();
|
|
35
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
|
+
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.Types = void 0;
|
|
40
|
-
__exportStar(require("./common"), exports);
|
|
41
40
|
exports.Types = __importStar(require("./types"));
|
|
42
41
|
__exportStar(require("./utils"), exports);
|
|
42
|
+
__exportStar(require("./licenses"), exports);
|
|
43
|
+
__exportStar(require("./constants"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LicenseCategory = void 0;
|
|
4
|
+
var LicenseCategory;
|
|
5
|
+
(function (LicenseCategory) {
|
|
6
|
+
LicenseCategory["STRONG_COPYLEFT"] = "strong copyleft";
|
|
7
|
+
LicenseCategory["WEAK_COPYLEFT"] = "weak copyleft";
|
|
8
|
+
LicenseCategory["PERMISSIVE"] = "permissive";
|
|
9
|
+
LicenseCategory["UNKNOWN"] = "unknown";
|
|
10
|
+
})(LicenseCategory || (exports.LicenseCategory = LicenseCategory = {}));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { LicenseCategory } from './LicenseCategory';
|
|
2
|
+
export declare function getGraphStateInfo(stats: Record<LicenseCategory, number>): {
|
|
3
|
+
description: string;
|
|
4
|
+
categoriesPresence: {
|
|
5
|
+
hasAnyUnknown: boolean;
|
|
6
|
+
hasAnyWeakCopyleft: boolean;
|
|
7
|
+
hasAnyStrongCopyleft: boolean;
|
|
8
|
+
hasAllPermissive: boolean;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Gets a human-readable description of the license category
|
|
13
|
+
* @param category the license category
|
|
14
|
+
* @returns the human-readable description of the license category
|
|
15
|
+
*/
|
|
16
|
+
export declare function getLicenseCategoryDescription(category: LicenseCategory): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getGraphStateInfo = getGraphStateInfo;
|
|
4
|
+
exports.getLicenseCategoryDescription = getLicenseCategoryDescription;
|
|
5
|
+
const LicenseCategory_1 = require("./LicenseCategory");
|
|
6
|
+
function getGraphStateInfo(stats) {
|
|
7
|
+
const hasAnyUnknown = stats[LicenseCategory_1.LicenseCategory.UNKNOWN] > 0;
|
|
8
|
+
const hasAnyWeakCopyleft = stats[LicenseCategory_1.LicenseCategory.WEAK_COPYLEFT] > 0;
|
|
9
|
+
const hasAnyStrongCopyleft = stats[LicenseCategory_1.LicenseCategory.STRONG_COPYLEFT] > 0;
|
|
10
|
+
const hasAllPermissive = !hasAnyUnknown && !hasAnyStrongCopyleft && !hasAnyWeakCopyleft;
|
|
11
|
+
let description = '';
|
|
12
|
+
if (hasAnyWeakCopyleft || hasAnyStrongCopyleft) {
|
|
13
|
+
description = `Some detected licenses are ${[
|
|
14
|
+
hasAnyWeakCopyleft ? 'weak' : null,
|
|
15
|
+
hasAnyStrongCopyleft ? 'strong' : null,
|
|
16
|
+
]
|
|
17
|
+
.filter((x) => !!x)
|
|
18
|
+
.map((x) => `${x}-`)
|
|
19
|
+
.join(' and ')}copyleft`;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
description = `${hasAllPermissive ? 'All' : stats[LicenseCategory_1.LicenseCategory.PERMISSIVE]} detected licenses are permissive`;
|
|
23
|
+
}
|
|
24
|
+
if (hasAnyUnknown) {
|
|
25
|
+
description += `, ${hasAllPermissive ? 'but ' : ''}${stats[LicenseCategory_1.LicenseCategory.UNKNOWN]} are unknown.`;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
description,
|
|
29
|
+
categoriesPresence: {
|
|
30
|
+
hasAnyUnknown,
|
|
31
|
+
hasAnyWeakCopyleft,
|
|
32
|
+
hasAnyStrongCopyleft,
|
|
33
|
+
hasAllPermissive,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets a human-readable description of the license category
|
|
39
|
+
* @param category the license category
|
|
40
|
+
* @returns the human-readable description of the license category
|
|
41
|
+
*/
|
|
42
|
+
function getLicenseCategoryDescription(category) {
|
|
43
|
+
switch (category) {
|
|
44
|
+
case LicenseCategory_1.LicenseCategory.STRONG_COPYLEFT:
|
|
45
|
+
return 'Strong Copyleft';
|
|
46
|
+
case LicenseCategory_1.LicenseCategory.WEAK_COPYLEFT:
|
|
47
|
+
return 'Weak Copyleft';
|
|
48
|
+
case LicenseCategory_1.LicenseCategory.PERMISSIVE:
|
|
49
|
+
return 'Permissive';
|
|
50
|
+
case LicenseCategory_1.LicenseCategory.UNKNOWN:
|
|
51
|
+
return 'Unknown';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./LicenseCategory"), exports);
|
|
18
|
+
__exportStar(require("./descriptions"), exports);
|
|
19
|
+
__exportStar(require("./licenseAnalysis"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AggregatedLicensesMapping } from '../types';
|
|
2
|
+
import type { LicenseAnalysisResult } from '../types/LicenseAnalysisResult';
|
|
3
|
+
import { LicenseCategory } from './LicenseCategory';
|
|
4
|
+
/**
|
|
5
|
+
* Categorizes a license based on its copyleft characteristics.
|
|
6
|
+
* @param licenseType the license type
|
|
7
|
+
* @returns the license category
|
|
8
|
+
*/
|
|
9
|
+
export declare function categorizeLicense(licenseType?: string): LicenseCategory;
|
|
10
|
+
/**
|
|
11
|
+
* Analyzes license data and returns comprehensive statistics.
|
|
12
|
+
* @param report the licenses report data
|
|
13
|
+
* @returns the license analysis result
|
|
14
|
+
*/
|
|
15
|
+
export declare function analyzeLicenses(report: AggregatedLicensesMapping): LicenseAnalysisResult;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.categorizeLicense = categorizeLicense;
|
|
4
|
+
exports.analyzeLicenses = analyzeLicenses;
|
|
5
|
+
const licenses_1 = require("../constants/licenses");
|
|
6
|
+
const LicenseCategory_1 = require("./LicenseCategory");
|
|
7
|
+
const descriptions_1 = require("./descriptions");
|
|
8
|
+
/**
|
|
9
|
+
* Categorizes a license based on its copyleft characteristics.
|
|
10
|
+
* @param licenseType the license type
|
|
11
|
+
* @returns the license category
|
|
12
|
+
*/
|
|
13
|
+
function categorizeLicense(licenseType) {
|
|
14
|
+
if (!licenseType || licenseType === 'unknown') {
|
|
15
|
+
return LicenseCategory_1.LicenseCategory.UNKNOWN;
|
|
16
|
+
}
|
|
17
|
+
// check for strong copyleft licenses
|
|
18
|
+
if (licenses_1.STRONG_COPYLEFT_LICENSES_LOWERCASE.has(licenseType.toLowerCase())) {
|
|
19
|
+
return LicenseCategory_1.LicenseCategory.STRONG_COPYLEFT;
|
|
20
|
+
}
|
|
21
|
+
// check for weak copyleft licenses
|
|
22
|
+
if (licenses_1.WEAK_COPYLEFT_LICENSES_LOWERCASE.has(licenseType.toLowerCase())) {
|
|
23
|
+
return LicenseCategory_1.LicenseCategory.WEAK_COPYLEFT;
|
|
24
|
+
}
|
|
25
|
+
// everything else is considered permissive
|
|
26
|
+
return LicenseCategory_1.LicenseCategory.PERMISSIVE;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Analyzes license data and returns comprehensive statistics.
|
|
30
|
+
* @param report the licenses report data
|
|
31
|
+
* @returns the license analysis result
|
|
32
|
+
*/
|
|
33
|
+
function analyzeLicenses(report) {
|
|
34
|
+
const byCategory = {
|
|
35
|
+
[LicenseCategory_1.LicenseCategory.STRONG_COPYLEFT]: 0,
|
|
36
|
+
[LicenseCategory_1.LicenseCategory.WEAK_COPYLEFT]: 0,
|
|
37
|
+
[LicenseCategory_1.LicenseCategory.PERMISSIVE]: 0,
|
|
38
|
+
[LicenseCategory_1.LicenseCategory.UNKNOWN]: 0,
|
|
39
|
+
};
|
|
40
|
+
const byLicense = {};
|
|
41
|
+
const categorizedLicenses = {};
|
|
42
|
+
Object.entries(report).forEach(([packageKey, license]) => {
|
|
43
|
+
const licenseType = license.type;
|
|
44
|
+
const category = categorizeLicense(licenseType);
|
|
45
|
+
// stats by category
|
|
46
|
+
byCategory[category]++;
|
|
47
|
+
// stats by specific license
|
|
48
|
+
{
|
|
49
|
+
const key = licenseType ?? 'unknown';
|
|
50
|
+
byLicense[key] = (byLicense[key] ?? 0) + 1;
|
|
51
|
+
}
|
|
52
|
+
// memoization for lookup
|
|
53
|
+
categorizedLicenses[packageKey] = category;
|
|
54
|
+
});
|
|
55
|
+
const total = Object.keys(report).length;
|
|
56
|
+
const { categoriesPresence, description } = (0, descriptions_1.getGraphStateInfo)(byCategory);
|
|
57
|
+
return {
|
|
58
|
+
total,
|
|
59
|
+
byCategory,
|
|
60
|
+
byLicense,
|
|
61
|
+
description,
|
|
62
|
+
categoriesPresence,
|
|
63
|
+
categorizedLicenses,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AboutLibrariesLikePackageInfo,
|
|
1
|
+
import type { AboutLibrariesLikePackageInfo, AggregatedLicensesMapping, ScanPackageOptionsFactory } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* Scans `package.json` and searches for all packages under `dependencies` field. Supports monorepo projects.
|
|
4
4
|
*
|
|
@@ -6,7 +6,7 @@ import type { AboutLibrariesLikePackageInfo, AggregatedLicensesObj, ScanPackageO
|
|
|
6
6
|
* @param scanOptionsFactory Factory function to create scan options for dependencies; defaults to {@link PackageUtils.legacyDefaultScanPackageOptionsFactory}
|
|
7
7
|
* @returns Aggregated licenses object containing all scanned dependencies and their license information
|
|
8
8
|
*/
|
|
9
|
-
export declare function scanDependencies(appPackageJsonPath: string, scanOptionsFactory?: ScanPackageOptionsFactory):
|
|
9
|
+
export declare function scanDependencies(appPackageJsonPath: string, scanOptionsFactory?: ScanPackageOptionsFactory): AggregatedLicensesMapping;
|
|
10
10
|
/**
|
|
11
11
|
* Generates LicensePlist-compatible metadata for NPM dependencies as a YAML string.
|
|
12
12
|
*
|
|
@@ -16,7 +16,7 @@ export declare function scanDependencies(appPackageJsonPath: string, scanOptions
|
|
|
16
16
|
* @param iosProjectPath Path to the iOS project directory
|
|
17
17
|
* @see {@link writeLicensePlistNPMOutput}
|
|
18
18
|
*/
|
|
19
|
-
export declare function generateLicensePlistNPMOutput(licenses:
|
|
19
|
+
export declare function generateLicensePlistNPMOutput(licenses: AggregatedLicensesMapping, iosProjectPath: string): string;
|
|
20
20
|
/**
|
|
21
21
|
* Writes LicensePlist-compatible metadata for NPM dependencies to a file
|
|
22
22
|
*
|
|
@@ -37,7 +37,7 @@ export declare function generateLicensePlistNPMOutput(licenses: AggregatedLicens
|
|
|
37
37
|
* @param plistLikeOutput Optional pre-generated string output to use instead of generating it using `generateLicensePlistNPMOutput`
|
|
38
38
|
* @see {@link generateLicensePlistNPMOutput}
|
|
39
39
|
*/
|
|
40
|
-
export declare function writeLicensePlistNPMOutput(licenses:
|
|
40
|
+
export declare function writeLicensePlistNPMOutput(licenses: AggregatedLicensesMapping, iosProjectPath: string, plistLikeOutput?: string): void;
|
|
41
41
|
/**
|
|
42
42
|
* Generates AboutLibraries-compatible metadata for NPM dependencies
|
|
43
43
|
*
|
|
@@ -47,7 +47,7 @@ export declare function writeLicensePlistNPMOutput(licenses: AggregatedLicensesO
|
|
|
47
47
|
* @returns Array of AboutLibrariesLikePackage objects, each representing a NPM dependency
|
|
48
48
|
* @see {@link writeAboutLibrariesNPMOutput}
|
|
49
49
|
*/
|
|
50
|
-
export declare function generateAboutLibrariesNPMOutput(licenses:
|
|
50
|
+
export declare function generateAboutLibrariesNPMOutput(licenses: AggregatedLicensesMapping): AboutLibrariesLikePackageInfo[];
|
|
51
51
|
/**
|
|
52
52
|
* Generates AboutLibraries-compatible metadata for NPM dependencies
|
|
53
53
|
*
|
|
@@ -68,4 +68,4 @@ export declare function generateAboutLibrariesNPMOutput(licenses: AggregatedLice
|
|
|
68
68
|
* @param aboutLibrariesLikeOutput Optional pre-generated output to use instead of generating it using `generateAboutLibrariesNPMOutput`
|
|
69
69
|
* @see {@link generateAboutLibrariesNPMOutput}
|
|
70
70
|
*/
|
|
71
|
-
export declare function writeAboutLibrariesNPMOutput(licenses:
|
|
71
|
+
export declare function writeAboutLibrariesNPMOutput(licenses: AggregatedLicensesMapping, androidProjectPath: string, aboutLibrariesLikeOutput?: AboutLibrariesLikePackageInfo[]): void;
|
|
@@ -8,10 +8,11 @@ exports.generateLicensePlistNPMOutput = generateLicensePlistNPMOutput;
|
|
|
8
8
|
exports.writeLicensePlistNPMOutput = writeLicensePlistNPMOutput;
|
|
9
9
|
exports.generateAboutLibrariesNPMOutput = generateAboutLibrariesNPMOutput;
|
|
10
10
|
exports.writeAboutLibrariesNPMOutput = writeAboutLibrariesNPMOutput;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
13
|
const glob_1 = __importDefault(require("glob"));
|
|
14
|
-
const utils_1 = require("
|
|
14
|
+
const utils_1 = require("../utils");
|
|
15
|
+
const utils_2 = require("./utils");
|
|
15
16
|
/**
|
|
16
17
|
* Scans a single package and its dependencies for license information
|
|
17
18
|
*
|
|
@@ -23,7 +24,7 @@ const utils_1 = require("./utils");
|
|
|
23
24
|
* @param isOptionalDependency Whether the package is an optional dependency, in which case a warning will not be logged if the corresponding package.json is not found; defaults to `false`
|
|
24
25
|
* @param parentPackageRoot Optional path to the parent package root, has priority over default root to lock for dependencies in; used to discover different versions of the same package installed in nested node_modules, e.g. suppose `X@1`, `Y@1` where `Y@1` -> `X@2`; then, node_modules would have `X@1`, `Y@1` and `X@2` would be installed to `node_modules/Y/node_modules/X@2`
|
|
25
26
|
*/
|
|
26
|
-
function scanPackage(packageName, requiredVersion, processedPackages, result, scanOptionsFactory =
|
|
27
|
+
function scanPackage(packageName, requiredVersion, processedPackages, result, scanOptionsFactory = utils_2.PackageUtils.legacyDefaultScanPackageOptionsFactory, { parentPackageRoot, parentPackageName, dependencyType, parentPackageRequiredVersion, parentPackageResolvedVersion, }) {
|
|
27
28
|
const requiredVersionPackageKey = `${packageName}@${requiredVersion}`;
|
|
28
29
|
// Skip if already processed to avoid circular dependencies
|
|
29
30
|
if (processedPackages.has(requiredVersionPackageKey)) {
|
|
@@ -35,7 +36,7 @@ function scanPackage(packageName, requiredVersion, processedPackages, result, sc
|
|
|
35
36
|
}
|
|
36
37
|
processedPackages.add(requiredVersionPackageKey);
|
|
37
38
|
try {
|
|
38
|
-
const localPackageJsonPath =
|
|
39
|
+
const localPackageJsonPath = utils_2.PackageUtils.getPackageJsonPath(packageName, parentPackageRoot);
|
|
39
40
|
if (!localPackageJsonPath) {
|
|
40
41
|
// do not warn if the package is an optional dependency, it's normal it may not be installed
|
|
41
42
|
if (!dependencyType.toLowerCase().includes('optional')) {
|
|
@@ -43,31 +44,47 @@ function scanPackage(packageName, requiredVersion, processedPackages, result, sc
|
|
|
43
44
|
}
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
|
-
const localPackageJson = require(
|
|
47
|
+
const localPackageJson = require(node_path_1.default.resolve(localPackageJsonPath));
|
|
47
48
|
if (localPackageJson.private !== true) {
|
|
48
49
|
const licenseFiles = glob_1.default.sync('LICEN{S,C}E{.md,}', {
|
|
49
|
-
cwd:
|
|
50
|
+
cwd: node_path_1.default.dirname(localPackageJsonPath),
|
|
50
51
|
absolute: true,
|
|
51
52
|
nocase: true,
|
|
52
53
|
nodir: true,
|
|
53
54
|
ignore: '**/{__tests__,__fixtures__,__mocks__}/**',
|
|
54
55
|
});
|
|
55
56
|
const resolvedVersionPackageKey = `${packageName}@${localPackageJson.version}`;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
let parentPackageInfo;
|
|
58
|
+
if (parentPackageName && parentPackageRequiredVersion && parentPackageResolvedVersion) {
|
|
59
|
+
parentPackageInfo = {
|
|
60
|
+
name: parentPackageName,
|
|
61
|
+
requiredVersion: parentPackageRequiredVersion,
|
|
62
|
+
resolvedVersion: parentPackageResolvedVersion,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (parentPackageInfo && resolvedVersionPackageKey in result) {
|
|
66
|
+
result[resolvedVersionPackageKey].parentPackages = [
|
|
67
|
+
...(result[resolvedVersionPackageKey].parentPackages ?? []),
|
|
68
|
+
parentPackageInfo,
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
result[resolvedVersionPackageKey] = {
|
|
73
|
+
name: packageName,
|
|
74
|
+
author: utils_2.PackageUtils.parseAuthorField(localPackageJson),
|
|
75
|
+
content: licenseFiles?.[0] ? node_fs_1.default.readFileSync(licenseFiles[0], { encoding: 'utf-8' }) : undefined,
|
|
76
|
+
file: licenseFiles?.[0] ? licenseFiles[0] : undefined,
|
|
77
|
+
description: localPackageJson.description,
|
|
78
|
+
type: utils_2.PackageUtils.parseLicenseField(localPackageJson),
|
|
79
|
+
url: utils_2.PackageUtils.parseRepositoryFieldToUrl(localPackageJson),
|
|
80
|
+
version: localPackageJson.version,
|
|
81
|
+
requiredVersion,
|
|
82
|
+
parentPackages: parentPackageInfo ? [parentPackageInfo] : [],
|
|
83
|
+
parentPackageRequiredVersion,
|
|
84
|
+
parentPackageResolvedVersion,
|
|
85
|
+
dependencyType,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
71
88
|
}
|
|
72
89
|
const dependencies = localPackageJson.dependencies;
|
|
73
90
|
const devDependencies = localPackageJson.devDependencies;
|
|
@@ -82,7 +99,7 @@ function scanPackage(packageName, requiredVersion, processedPackages, result, sc
|
|
|
82
99
|
return;
|
|
83
100
|
}
|
|
84
101
|
// helper used for finding nested dependencies installed with different versions for a given package, see docstring of scanPackage
|
|
85
|
-
const currentPackageRoot =
|
|
102
|
+
const currentPackageRoot = node_path_1.default.dirname(localPackageJsonPath);
|
|
86
103
|
for (const { dependencyType, packages } of [
|
|
87
104
|
{
|
|
88
105
|
dependencyType: 'transitiveDependency',
|
|
@@ -119,8 +136,8 @@ function scanPackage(packageName, requiredVersion, processedPackages, result, sc
|
|
|
119
136
|
* @param scanOptionsFactory Factory function to create scan options for dependencies; defaults to {@link PackageUtils.legacyDefaultScanPackageOptionsFactory}
|
|
120
137
|
* @returns Aggregated licenses object containing all scanned dependencies and their license information
|
|
121
138
|
*/
|
|
122
|
-
function scanDependencies(appPackageJsonPath, scanOptionsFactory =
|
|
123
|
-
const appPackageJson = require(
|
|
139
|
+
function scanDependencies(appPackageJsonPath, scanOptionsFactory = utils_2.PackageUtils.legacyDefaultScanPackageOptionsFactory) {
|
|
140
|
+
const appPackageJson = require(node_path_1.default.resolve(appPackageJsonPath));
|
|
124
141
|
const dependencies = appPackageJson.dependencies;
|
|
125
142
|
const devDependencies = appPackageJson.devDependencies;
|
|
126
143
|
const optionalDependencies = appPackageJson.optionalDependencies;
|
|
@@ -149,6 +166,7 @@ function scanDependencies(appPackageJsonPath, scanOptionsFactory = utils_1.Packa
|
|
|
149
166
|
}
|
|
150
167
|
return result;
|
|
151
168
|
}
|
|
169
|
+
const PODSPEC_NAME_REGEX = /(Pod::Spec\.new\s+do\s+\|(?<specref>.*)\|).*(\k<specref>\.name\s+=\s+(?<quote>["'])(?<specname>[a-zA-Z0-9_\-@]+)\k<quote>)/;
|
|
152
170
|
/**
|
|
153
171
|
* Generates LicensePlist-compatible metadata for NPM dependencies as a YAML string.
|
|
154
172
|
*
|
|
@@ -160,24 +178,54 @@ function scanDependencies(appPackageJsonPath, scanOptionsFactory = utils_1.Packa
|
|
|
160
178
|
*/
|
|
161
179
|
function generateLicensePlistNPMOutput(licenses, iosProjectPath) {
|
|
162
180
|
const renames = {};
|
|
163
|
-
const licenseEntries = Object.entries(licenses).map(([packageKey,
|
|
164
|
-
const normalizedPackageNameWithVersion =
|
|
165
|
-
if (
|
|
166
|
-
renames[normalizedPackageNameWithVersion] =
|
|
181
|
+
const licenseEntries = Object.entries(licenses).map(([packageKey, license]) => {
|
|
182
|
+
const normalizedPackageNameWithVersion = utils_2.PackageUtils.normalizePackageName(packageKey);
|
|
183
|
+
if (license.name !== normalizedPackageNameWithVersion) {
|
|
184
|
+
renames[normalizedPackageNameWithVersion] = license.name;
|
|
167
185
|
}
|
|
168
|
-
const relativeLicenseFile =
|
|
186
|
+
const relativeLicenseFile = license.file ? node_path_1.default.relative(iosProjectPath, license.file) : undefined;
|
|
169
187
|
return {
|
|
170
188
|
name: normalizedPackageNameWithVersion,
|
|
171
|
-
version:
|
|
172
|
-
...(
|
|
173
|
-
...(
|
|
174
|
-
? { file: relativeLicenseFile }
|
|
175
|
-
: { body: licenseObj.content ?? licenseObj.type ?? 'UNKNOWN' }),
|
|
189
|
+
version: license.version,
|
|
190
|
+
...(license.url && { source: license.url }),
|
|
191
|
+
...(license.file ? { file: relativeLicenseFile } : { body: license.content ?? license.type ?? 'UNKNOWN' }),
|
|
176
192
|
};
|
|
177
193
|
});
|
|
194
|
+
const excludedEntries = Object.values(licenses).reduce((acc, license) => {
|
|
195
|
+
const packageName = license.name;
|
|
196
|
+
const localPackageJsonPath = utils_2.PackageUtils.getPackageJsonPath(packageName);
|
|
197
|
+
if (!localPackageJsonPath) {
|
|
198
|
+
return acc;
|
|
199
|
+
}
|
|
200
|
+
const podspecFiles = glob_1.default.sync('**.podspec', {
|
|
201
|
+
cwd: node_path_1.default.dirname(localPackageJsonPath),
|
|
202
|
+
absolute: true,
|
|
203
|
+
nocase: true,
|
|
204
|
+
nodir: true,
|
|
205
|
+
ignore: '**/{__tests__,__fixtures__,__mocks__}/**',
|
|
206
|
+
});
|
|
207
|
+
if (!podspecFiles) {
|
|
208
|
+
return acc;
|
|
209
|
+
}
|
|
210
|
+
const podspecEntries = podspecFiles.map((podspecFile) => {
|
|
211
|
+
const podspecContent = node_fs_1.default.readFileSync(podspecFile, { encoding: 'utf-8' });
|
|
212
|
+
const podspecContentShrinked = podspecContent.replace(/\n/g, ' ');
|
|
213
|
+
const { specname } = PODSPEC_NAME_REGEX.exec(podspecContentShrinked)?.groups ?? {};
|
|
214
|
+
return { name: specname ?? packageName };
|
|
215
|
+
});
|
|
216
|
+
return [...acc, ...podspecEntries];
|
|
217
|
+
}, []);
|
|
178
218
|
const yamlDoc = {
|
|
179
219
|
...(Object.keys(renames).length > 0 && { rename: renames }),
|
|
180
220
|
manual: licenseEntries,
|
|
221
|
+
/**
|
|
222
|
+
* Adding excludes to prevent duplicates - NPM packages with iOS Podspecs are already
|
|
223
|
+
* manually included in the `licenseEntries`. However License Plist is automatically including all
|
|
224
|
+
* the entries detected via Pods-<project-name>-acknowledgements.plist, which also
|
|
225
|
+
* includes the NPM package with iOS Podspecs - let's filter them out,
|
|
226
|
+
* so that only the manual NPM entries are displayed
|
|
227
|
+
*/
|
|
228
|
+
exclude: excludedEntries,
|
|
181
229
|
};
|
|
182
230
|
const yamlContent = [
|
|
183
231
|
'# BEGIN Generated NPM license entries',
|
|
@@ -210,7 +258,7 @@ function writeLicensePlistNPMOutput(licenses, iosProjectPath, plistLikeOutput) {
|
|
|
210
258
|
if (!plistLikeOutput) {
|
|
211
259
|
plistLikeOutput = generateLicensePlistNPMOutput(licenses, iosProjectPath);
|
|
212
260
|
}
|
|
213
|
-
|
|
261
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(iosProjectPath, 'license_plist.yml'), plistLikeOutput, { encoding: 'utf-8' });
|
|
214
262
|
}
|
|
215
263
|
/**
|
|
216
264
|
* Generates AboutLibraries-compatible metadata for NPM dependencies
|
|
@@ -223,18 +271,18 @@ function writeLicensePlistNPMOutput(licenses, iosProjectPath, plistLikeOutput) {
|
|
|
223
271
|
*/
|
|
224
272
|
function generateAboutLibrariesNPMOutput(licenses) {
|
|
225
273
|
return Object.entries(licenses)
|
|
226
|
-
.map(([packageKey,
|
|
274
|
+
.map(([packageKey, license]) => {
|
|
227
275
|
return {
|
|
228
|
-
artifactVersion:
|
|
229
|
-
content:
|
|
230
|
-
description:
|
|
231
|
-
developers: [{ name:
|
|
232
|
-
licenses: [
|
|
233
|
-
name:
|
|
276
|
+
artifactVersion: license.version,
|
|
277
|
+
content: license.content ?? '',
|
|
278
|
+
description: license.description ?? '',
|
|
279
|
+
developers: [{ name: license.author ?? '', organisationUrl: '' }],
|
|
280
|
+
licenses: [utils_2.PackageUtils.prepareAboutLibrariesLicenseField(license)],
|
|
281
|
+
name: license.name,
|
|
234
282
|
tag: '',
|
|
235
|
-
type:
|
|
236
|
-
uniqueId:
|
|
237
|
-
website:
|
|
283
|
+
type: license.type,
|
|
284
|
+
uniqueId: utils_2.PackageUtils.normalizePackageName(packageKey),
|
|
285
|
+
website: license.url,
|
|
238
286
|
};
|
|
239
287
|
})
|
|
240
288
|
.map((jsonPayload) => {
|
|
@@ -282,27 +330,27 @@ function generateAboutLibrariesNPMOutput(licenses) {
|
|
|
282
330
|
* @see {@link generateAboutLibrariesNPMOutput}
|
|
283
331
|
*/
|
|
284
332
|
function writeAboutLibrariesNPMOutput(licenses, androidProjectPath, aboutLibrariesLikeOutput) {
|
|
285
|
-
const aboutLibrariesConfigDirPath =
|
|
286
|
-
const aboutLibrariesConfigLibrariesDirPath =
|
|
287
|
-
const aboutLibrariesConfigLicensesDirPath =
|
|
288
|
-
if (!
|
|
289
|
-
|
|
333
|
+
const aboutLibrariesConfigDirPath = node_path_1.default.join(androidProjectPath, 'config');
|
|
334
|
+
const aboutLibrariesConfigLibrariesDirPath = node_path_1.default.join(aboutLibrariesConfigDirPath, 'libraries');
|
|
335
|
+
const aboutLibrariesConfigLicensesDirPath = node_path_1.default.join(aboutLibrariesConfigDirPath, 'licenses');
|
|
336
|
+
if (!node_fs_1.default.existsSync(aboutLibrariesConfigDirPath)) {
|
|
337
|
+
node_fs_1.default.mkdirSync(aboutLibrariesConfigDirPath);
|
|
290
338
|
}
|
|
291
|
-
if (!
|
|
292
|
-
|
|
339
|
+
if (!node_fs_1.default.existsSync(aboutLibrariesConfigLibrariesDirPath)) {
|
|
340
|
+
node_fs_1.default.mkdirSync(aboutLibrariesConfigLibrariesDirPath);
|
|
293
341
|
}
|
|
294
|
-
if (!
|
|
295
|
-
|
|
342
|
+
if (!node_fs_1.default.existsSync(aboutLibrariesConfigLicensesDirPath)) {
|
|
343
|
+
node_fs_1.default.mkdirSync(aboutLibrariesConfigLicensesDirPath);
|
|
296
344
|
}
|
|
297
345
|
if (!aboutLibrariesLikeOutput) {
|
|
298
346
|
aboutLibrariesLikeOutput = generateAboutLibrariesNPMOutput(licenses);
|
|
299
347
|
}
|
|
300
348
|
aboutLibrariesLikeOutput.forEach(({ normalizedPackageNameWithVersion, libraryJsonPayload, licenseJsonPayload }) => {
|
|
301
|
-
const libraryJsonFilePath =
|
|
302
|
-
const licenseJsonFilePath =
|
|
303
|
-
|
|
304
|
-
if (!
|
|
305
|
-
|
|
349
|
+
const libraryJsonFilePath = node_path_1.default.join(aboutLibrariesConfigLibrariesDirPath, `${normalizedPackageNameWithVersion}.json`);
|
|
350
|
+
const licenseJsonFilePath = node_path_1.default.join(aboutLibrariesConfigLicensesDirPath, `${licenseJsonPayload.hash}.json`);
|
|
351
|
+
node_fs_1.default.writeFileSync(libraryJsonFilePath, JSON.stringify(libraryJsonPayload));
|
|
352
|
+
if (!node_fs_1.default.existsSync(licenseJsonFilePath)) {
|
|
353
|
+
node_fs_1.default.writeFileSync(licenseJsonFilePath, JSON.stringify(licenseJsonPayload));
|
|
306
354
|
}
|
|
307
355
|
});
|
|
308
356
|
}
|