@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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/build/constants/index.d.ts +1 -0
  3. package/build/constants/index.js +17 -0
  4. package/build/constants/licenses.d.ts +7 -0
  5. package/build/constants/licenses.js +53 -0
  6. package/build/index.d.ts +2 -1
  7. package/build/index.js +5 -4
  8. package/build/licenses/LicenseCategory.d.ts +6 -0
  9. package/build/licenses/LicenseCategory.js +10 -0
  10. package/build/licenses/descriptions.d.ts +16 -0
  11. package/build/licenses/descriptions.js +53 -0
  12. package/build/licenses/index.d.ts +3 -0
  13. package/build/licenses/index.js +19 -0
  14. package/build/licenses/licenseAnalysis.d.ts +15 -0
  15. package/build/licenses/licenseAnalysis.js +65 -0
  16. package/build/{common.d.ts → node/common.d.ts} +6 -6
  17. package/build/{common.js → node/common.js} +108 -60
  18. package/build/node/index.d.ts +3 -0
  19. package/build/node/index.js +19 -0
  20. package/build/node/utils/index.d.ts +2 -0
  21. package/build/node/utils/index.js +38 -0
  22. package/build/{utils → node/utils}/packageUtils.d.ts +2 -2
  23. package/build/{utils → node/utils}/packageUtils.js +1 -1
  24. package/build/types/AggregatedLicensesMapping.d.ts +6 -0
  25. package/build/types/{LicenseObj.d.ts → License.d.ts} +8 -2
  26. package/build/types/LicenseAnalysisResult.d.ts +5 -0
  27. package/build/types/LicenseAnalysisResult.js +2 -0
  28. package/build/types/LicenseStats.d.ts +28 -0
  29. package/build/types/LicenseStats.js +2 -0
  30. package/build/types/ParentPackageInfo.d.ts +14 -0
  31. package/build/types/ParentPackageInfo.js +2 -0
  32. package/build/types/index.d.ts +5 -2
  33. package/build/types/index.js +5 -2
  34. package/build/utils/index.d.ts +0 -2
  35. package/build/utils/index.js +1 -3
  36. package/package.json +20 -7
  37. package/src/constants/index.ts +1 -0
  38. package/src/constants/licenses.ts +58 -0
  39. package/src/index.ts +2 -1
  40. package/src/licenses/LicenseCategory.ts +6 -0
  41. package/src/licenses/descriptions.ts +56 -0
  42. package/src/licenses/index.ts +3 -0
  43. package/src/licenses/licenseAnalysis.ts +78 -0
  44. package/src/{common.ts → node/common.ts} +104 -45
  45. package/src/node/index.ts +3 -0
  46. package/src/node/utils/index.ts +2 -0
  47. package/src/{utils → node/utils}/packageUtils.ts +3 -3
  48. package/src/types/AggregatedLicensesMapping.ts +7 -0
  49. package/src/types/{LicenseObj.ts → License.ts} +9 -2
  50. package/src/types/LicenseAnalysisResult.ts +7 -0
  51. package/src/types/LicenseStats.ts +33 -0
  52. package/src/types/ParentPackageInfo.ts +16 -0
  53. package/src/types/index.ts +5 -2
  54. package/src/utils/index.ts +0 -2
  55. package/build/types/AggregatedLicensesObj.d.ts +0 -6
  56. package/src/types/AggregatedLicensesObj.ts +0 -7
  57. /package/build/{utils → node/utils}/miscUtils.d.ts +0 -0
  58. /package/build/{utils → node/utils}/miscUtils.js +0 -0
  59. /package/build/types/{AggregatedLicensesObj.js → AggregatedLicensesMapping.js} +0 -0
  60. /package/build/types/{LicenseObj.js → License.js} +0 -0
  61. /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
@@ -1,3 +1,4 @@
1
- export * from './common';
2
1
  export * as Types from './types';
3
2
  export * from './utils';
3
+ export * from './licenses';
4
+ export * from './constants';
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,6 @@
1
+ export declare enum LicenseCategory {
2
+ STRONG_COPYLEFT = "strong copyleft",
3
+ WEAK_COPYLEFT = "weak copyleft",
4
+ PERMISSIVE = "permissive",
5
+ UNKNOWN = "unknown"
6
+ }
@@ -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,3 @@
1
+ export * from './LicenseCategory';
2
+ export * from './descriptions';
3
+ export * from './licenseAnalysis';
@@ -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, AggregatedLicensesObj, ScanPackageOptionsFactory } from './types';
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): AggregatedLicensesObj;
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: AggregatedLicensesObj, iosProjectPath: string): string;
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: AggregatedLicensesObj, iosProjectPath: string, plistLikeOutput?: string): void;
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: AggregatedLicensesObj): AboutLibrariesLikePackageInfo[];
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: AggregatedLicensesObj, androidProjectPath: string, aboutLibrariesLikeOutput?: AboutLibrariesLikePackageInfo[]): void;
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 fs_1 = __importDefault(require("fs"));
12
- const path_1 = __importDefault(require("path"));
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("./utils");
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 = utils_1.PackageUtils.legacyDefaultScanPackageOptionsFactory, { parentPackageRoot, parentPackageName, dependencyType, parentPackageRequiredVersion, parentPackageResolvedVersion, }) {
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 = utils_1.PackageUtils.getPackageJsonPath(packageName, parentPackageRoot);
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(path_1.default.resolve(localPackageJsonPath));
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: path_1.default.dirname(localPackageJsonPath),
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
- result[resolvedVersionPackageKey] = {
57
- name: packageName,
58
- author: utils_1.PackageUtils.parseAuthorField(localPackageJson),
59
- content: licenseFiles?.[0] ? fs_1.default.readFileSync(licenseFiles[0], { encoding: 'utf-8' }) : undefined,
60
- file: licenseFiles?.[0] ? licenseFiles[0] : undefined,
61
- description: localPackageJson.description,
62
- type: utils_1.PackageUtils.parseLicenseField(localPackageJson),
63
- url: utils_1.PackageUtils.parseRepositoryFieldToUrl(localPackageJson),
64
- version: localPackageJson.version,
65
- requiredVersion,
66
- parentPackageName,
67
- parentPackageRequiredVersion,
68
- parentPackageResolvedVersion,
69
- dependencyType,
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 = path_1.default.dirname(localPackageJsonPath);
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 = utils_1.PackageUtils.legacyDefaultScanPackageOptionsFactory) {
123
- const appPackageJson = require(path_1.default.resolve(appPackageJsonPath));
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, licenseObj]) => {
164
- const normalizedPackageNameWithVersion = utils_1.PackageUtils.normalizePackageName(packageKey);
165
- if (licenseObj.name !== normalizedPackageNameWithVersion) {
166
- renames[normalizedPackageNameWithVersion] = licenseObj.name;
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 = licenseObj.file ? path_1.default.relative(iosProjectPath, licenseObj.file) : undefined;
186
+ const relativeLicenseFile = license.file ? node_path_1.default.relative(iosProjectPath, license.file) : undefined;
169
187
  return {
170
188
  name: normalizedPackageNameWithVersion,
171
- version: licenseObj.version,
172
- ...(licenseObj.url && { source: licenseObj.url }),
173
- ...(licenseObj.file
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
- fs_1.default.writeFileSync(path_1.default.join(iosProjectPath, 'license_plist.yml'), plistLikeOutput, { encoding: 'utf-8' });
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, licenseObj]) => {
274
+ .map(([packageKey, license]) => {
227
275
  return {
228
- artifactVersion: licenseObj.version,
229
- content: licenseObj.content ?? '',
230
- description: licenseObj.description ?? '',
231
- developers: [{ name: licenseObj.author ?? '', organisationUrl: '' }],
232
- licenses: [utils_1.PackageUtils.prepareAboutLibrariesLicenseField(licenseObj)],
233
- name: licenseObj.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: licenseObj.type,
236
- uniqueId: utils_1.PackageUtils.normalizePackageName(packageKey),
237
- website: licenseObj.url,
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 = path_1.default.join(androidProjectPath, 'config');
286
- const aboutLibrariesConfigLibrariesDirPath = path_1.default.join(aboutLibrariesConfigDirPath, 'libraries');
287
- const aboutLibrariesConfigLicensesDirPath = path_1.default.join(aboutLibrariesConfigDirPath, 'licenses');
288
- if (!fs_1.default.existsSync(aboutLibrariesConfigDirPath)) {
289
- fs_1.default.mkdirSync(aboutLibrariesConfigDirPath);
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 (!fs_1.default.existsSync(aboutLibrariesConfigLibrariesDirPath)) {
292
- fs_1.default.mkdirSync(aboutLibrariesConfigLibrariesDirPath);
339
+ if (!node_fs_1.default.existsSync(aboutLibrariesConfigLibrariesDirPath)) {
340
+ node_fs_1.default.mkdirSync(aboutLibrariesConfigLibrariesDirPath);
293
341
  }
294
- if (!fs_1.default.existsSync(aboutLibrariesConfigLicensesDirPath)) {
295
- fs_1.default.mkdirSync(aboutLibrariesConfigLicensesDirPath);
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 = path_1.default.join(aboutLibrariesConfigLibrariesDirPath, `${normalizedPackageNameWithVersion}.json`);
302
- const licenseJsonFilePath = path_1.default.join(aboutLibrariesConfigLicensesDirPath, `${licenseJsonPayload.hash}.json`);
303
- fs_1.default.writeFileSync(libraryJsonFilePath, JSON.stringify(libraryJsonPayload));
304
- if (!fs_1.default.existsSync(licenseJsonFilePath)) {
305
- fs_1.default.writeFileSync(licenseJsonFilePath, JSON.stringify(licenseJsonPayload));
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
  }
@@ -0,0 +1,3 @@
1
+ export * from './common';
2
+ export * from './utils';
3
+ export * from '../';