@callstack/licenses 0.2.2 → 0.3.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.
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} +75 -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} +62 -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
@@ -0,0 +1,38 @@
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.MiscUtils = exports.PackageUtils = void 0;
37
+ exports.PackageUtils = __importStar(require("./packageUtils"));
38
+ exports.MiscUtils = __importStar(require("./miscUtils"));
@@ -1,9 +1,9 @@
1
- import type { LicenseObj, ScanPackageOptionsFactory } from '../types';
1
+ import type { License, ScanPackageOptionsFactory } from '../../types';
2
2
  export declare function getPackageJsonPath(dependency: string, root?: string): string | null;
3
3
  export declare function resolvePackageJsonFromEntry(dependency: string): string | null;
4
4
  export declare function findPackageRoot(entryPath: string): string | undefined;
5
5
  export declare function normalizePackageName(packageName: string): string;
6
- export declare function prepareAboutLibrariesLicenseField(license: LicenseObj): string;
6
+ export declare function prepareAboutLibrariesLicenseField(license: License): string;
7
7
  export declare function parseAuthorField(json: {
8
8
  author: string | {
9
9
  name: string;
@@ -14,8 +14,8 @@ exports.parseLicenseField = parseLicenseField;
14
14
  exports.parseRepositoryFieldToUrl = parseRepositoryFieldToUrl;
15
15
  const fs_1 = __importDefault(require("fs"));
16
16
  const path_1 = __importDefault(require("path"));
17
+ const repositoryUtils_1 = require("../../utils/repositoryUtils");
17
18
  const miscUtils_1 = require("./miscUtils");
18
- const repositoryUtils_1 = require("./repositoryUtils");
19
19
  function getPackageJsonPath(dependency, root) {
20
20
  const rootsToSearch = [
21
21
  ...(root ? [root] : []), // provided for purpose of nested node_modules resolution inside a package dir, in a subdirectory inside the root node_modules dir
@@ -0,0 +1,6 @@
1
+ import type { License } from './License';
2
+ /**
3
+ * Mapping from package keys in format `<package-name>@<package-version>` to license objects.
4
+ * @see {@link License}
5
+ */
6
+ export type AggregatedLicensesMapping = Record<string, License>;
@@ -1,6 +1,7 @@
1
1
  import type { DependencyType } from './DependencyType';
2
+ import type { ParentPackageInfo } from './ParentPackageInfo';
2
3
  import type { ScanPackageCallContext } from './ScanPackageCallContext';
3
- export type LicenseObj = {
4
+ export type License = {
4
5
  /** Package name */
5
6
  name: string;
6
7
  /** Package author */
@@ -21,4 +22,9 @@ export type LicenseObj = {
21
22
  dependencyType: DependencyType;
22
23
  /** The required version specified in package.json */
23
24
  requiredVersion: string;
24
- } & Pick<ScanPackageCallContext, 'parentPackageName' | 'parentPackageRequiredVersion' | 'parentPackageResolvedVersion'>;
25
+ /**
26
+ * The name(s) of the package(s) that introduced the package as a dependency (of any type);
27
+ * empty array if the package is a dependency of the root package
28
+ */
29
+ parentPackages: ParentPackageInfo[];
30
+ } & Pick<ScanPackageCallContext, 'parentPackageRequiredVersion' | 'parentPackageResolvedVersion'>;
@@ -0,0 +1,5 @@
1
+ import type { LicenseCategory } from '../licenses/LicenseCategory';
2
+ import type { LicenseStats } from './LicenseStats';
3
+ export interface LicenseAnalysisResult extends LicenseStats {
4
+ categorizedLicenses: Record<string, LicenseCategory>;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,28 @@
1
+ import type { LicenseCategory } from '../licenses/LicenseCategory';
2
+ export interface LicenseStats {
3
+ /**
4
+ * Total number of packages
5
+ */
6
+ total: number;
7
+ /**
8
+ * Mapping of license category to count of packages in that category
9
+ */
10
+ byCategory: Record<LicenseCategory, number>;
11
+ /**
12
+ * Mapping of license name to count of packages with that license
13
+ */
14
+ byLicense: Record<string, number>;
15
+ /**
16
+ * Information about the presence of different license categories
17
+ */
18
+ categoriesPresence: {
19
+ hasAnyUnknown: boolean;
20
+ hasAnyWeakCopyleft: boolean;
21
+ hasAnyStrongCopyleft: boolean;
22
+ hasAllPermissive: boolean;
23
+ };
24
+ /**
25
+ * Description of the graph state based on the license categories
26
+ */
27
+ description: string;
28
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,14 @@
1
+ export type ParentPackageInfo = {
2
+ /**
3
+ * The name of the package
4
+ */
5
+ name: string;
6
+ /**
7
+ * The required version, as specified in package.json
8
+ */
9
+ requiredVersion: string;
10
+ /**
11
+ * The resolved version, as specified in package.json
12
+ */
13
+ resolvedVersion: string;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,5 @@
1
- export * from './LicenseObj';
2
- export * from './AggregatedLicensesObj';
1
+ export * from './License';
2
+ export * from './AggregatedLicensesMapping';
3
3
  export * from './AboutLibrariesLibraryJsonPayload';
4
4
  export * from './AboutLibrariesLicenseJsonPayload';
5
5
  export * from './LicensePlistPayload';
@@ -7,3 +7,6 @@ export * from './AboutLibrariesLikePackageInfo';
7
7
  export * from './ScanPackageOptions';
8
8
  export * from './ScanPackageCallContext';
9
9
  export * from './DependencyType';
10
+ export * from './ParentPackageInfo';
11
+ export * from './LicenseAnalysisResult';
12
+ export * from './LicenseStats';
@@ -14,8 +14,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./LicenseObj"), exports);
18
- __exportStar(require("./AggregatedLicensesObj"), exports);
17
+ __exportStar(require("./License"), exports);
18
+ __exportStar(require("./AggregatedLicensesMapping"), exports);
19
19
  __exportStar(require("./AboutLibrariesLibraryJsonPayload"), exports);
20
20
  __exportStar(require("./AboutLibrariesLicenseJsonPayload"), exports);
21
21
  __exportStar(require("./LicensePlistPayload"), exports);
@@ -23,3 +23,6 @@ __exportStar(require("./AboutLibrariesLikePackageInfo"), exports);
23
23
  __exportStar(require("./ScanPackageOptions"), exports);
24
24
  __exportStar(require("./ScanPackageCallContext"), exports);
25
25
  __exportStar(require("./DependencyType"), exports);
26
+ __exportStar(require("./ParentPackageInfo"), exports);
27
+ __exportStar(require("./LicenseAnalysisResult"), exports);
28
+ __exportStar(require("./LicenseStats"), exports);
@@ -1,4 +1,2 @@
1
- export * as PackageUtils from './packageUtils';
2
- export * as MiscUtils from './miscUtils';
3
1
  export * as RepositoryUtils from './repositoryUtils';
4
2
  export * as YamlUtils from './yamlUtils';
@@ -33,8 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.YamlUtils = exports.RepositoryUtils = exports.MiscUtils = exports.PackageUtils = void 0;
37
- exports.PackageUtils = __importStar(require("./packageUtils"));
38
- exports.MiscUtils = __importStar(require("./miscUtils"));
36
+ exports.YamlUtils = exports.RepositoryUtils = void 0;
39
37
  exports.RepositoryUtils = __importStar(require("./repositoryUtils"));
40
38
  exports.YamlUtils = __importStar(require("./yamlUtils"));
package/package.json CHANGED
@@ -1,15 +1,28 @@
1
1
  {
2
2
  "name": "@callstack/licenses",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "API package that exposes functionalities for programmatic scanning of licenses in Node.js projects.",
5
- "main": "build/index",
6
- "module": "build/index",
7
- "types": "build/index.d.ts",
5
+ "browser": "./build/index.js",
6
+ "main": "./build/node/index.js",
8
7
  "exports": {
9
8
  ".": {
10
- "source": "./src/index.ts",
11
- "types": "./build/index.d.ts",
12
- "default": "./build/index.js"
9
+ "import": {
10
+ "source": "./src/index.ts",
11
+ "types": "./build/index.d.ts",
12
+ "default": "./build/index.js"
13
+ },
14
+ "require": {
15
+ "source": "./src/node/index.ts",
16
+ "types": "./build/node/index.d.ts",
17
+ "default": "./build/node/index.js"
18
+ }
19
+ },
20
+ "./node": {
21
+ "import": {
22
+ "source": "./src/node/index.ts",
23
+ "types": "./build/node/index.d.ts",
24
+ "default": "./build/node/index.js"
25
+ }
13
26
  },
14
27
  "./package.json": "./package.json"
15
28
  },
@@ -0,0 +1 @@
1
+ export * from './licenses';
@@ -0,0 +1,58 @@
1
+ /**
2
+ * https://spdx.org/licenses
3
+ */
4
+
5
+ export const STRONG_COPYLEFT_LICENSES = new Set([
6
+ 'GPL',
7
+ 'GPL-1.0',
8
+ 'GPL-1.0+',
9
+ 'GPL-2.0',
10
+ 'GPL-2.0+',
11
+ 'GPL-2.0-only',
12
+ 'GPL-2.0-or-later',
13
+ 'GPL-3.0',
14
+ 'GPL-3.0+',
15
+ 'GPL-3.0-only',
16
+ 'GPL-3.0-or-later',
17
+ 'AGPL-3.0',
18
+ 'AGPL-3.0-only',
19
+ 'AGPL-3.0-or-later',
20
+ 'EUPL-1.0',
21
+ 'EUPL-1.1',
22
+ 'EUPL-1.2',
23
+ 'OSL-1.0',
24
+ 'OSL-1.1',
25
+ 'OSL-2.0',
26
+ 'OSL-2.1',
27
+ 'OSL-3.0',
28
+ ]);
29
+
30
+ export const WEAK_COPYLEFT_LICENSES = new Set([
31
+ 'CDDL-1.0',
32
+ 'CDDL-1.1',
33
+ 'EPL-1.0',
34
+ 'EPL-2.0',
35
+ 'LGPL',
36
+ 'LGPL-2.0',
37
+ 'LGPL-2.0+',
38
+ 'LGPL-2.0-only',
39
+ 'LGPL-2.0-or-later',
40
+ 'LGPL-2.1',
41
+ 'LGPL-2.1+',
42
+ 'LGPL-2.1-only',
43
+ 'LGPL-2.1-or-later',
44
+ 'LGPL-3.0',
45
+ 'LGPL-3.0+',
46
+ 'LGPL-3.0-only',
47
+ 'LGPL-3.0-or-later',
48
+ 'MPL-1.1',
49
+ 'MPL-2.0',
50
+ ]);
51
+
52
+ export const STRONG_COPYLEFT_LICENSES_LOWERCASE = new Set(
53
+ Array.from(STRONG_COPYLEFT_LICENSES).map((license) => license.toLowerCase()),
54
+ );
55
+
56
+ export const WEAK_COPYLEFT_LICENSES_LOWERCASE = new Set(
57
+ Array.from(WEAK_COPYLEFT_LICENSES).map((license) => license.toLowerCase()),
58
+ );
package/src/index.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';
@@ -0,0 +1,6 @@
1
+ export enum LicenseCategory {
2
+ STRONG_COPYLEFT = 'strong copyleft',
3
+ WEAK_COPYLEFT = 'weak copyleft',
4
+ PERMISSIVE = 'permissive',
5
+ UNKNOWN = 'unknown',
6
+ }
@@ -0,0 +1,56 @@
1
+ import { LicenseCategory } from './LicenseCategory';
2
+
3
+ export function getGraphStateInfo(stats: Record<LicenseCategory, number>) {
4
+ const hasAnyUnknown = stats[LicenseCategory.UNKNOWN] > 0;
5
+ const hasAnyWeakCopyleft = stats[LicenseCategory.WEAK_COPYLEFT] > 0;
6
+ const hasAnyStrongCopyleft = stats[LicenseCategory.STRONG_COPYLEFT] > 0;
7
+ const hasAllPermissive = !hasAnyUnknown && !hasAnyStrongCopyleft && !hasAnyWeakCopyleft;
8
+
9
+ let description = '';
10
+ if (hasAnyWeakCopyleft || hasAnyStrongCopyleft) {
11
+ description = `Some detected licenses are ${[
12
+ hasAnyWeakCopyleft ? 'weak' : null,
13
+ hasAnyStrongCopyleft ? 'strong' : null,
14
+ ]
15
+ .filter((x) => !!x)
16
+ .map((x) => `${x}-`)
17
+ .join(' and ')}copyleft`;
18
+ } else {
19
+ description = `${hasAllPermissive ? 'All' : stats[LicenseCategory.PERMISSIVE]} detected licenses are permissive`;
20
+ }
21
+
22
+ if (hasAnyUnknown) {
23
+ description += `, ${hasAllPermissive ? 'but ' : ''}${stats[LicenseCategory.UNKNOWN]} are unknown.`;
24
+ }
25
+
26
+ return {
27
+ description,
28
+ categoriesPresence: {
29
+ hasAnyUnknown,
30
+ hasAnyWeakCopyleft,
31
+ hasAnyStrongCopyleft,
32
+ hasAllPermissive,
33
+ },
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
+ export function getLicenseCategoryDescription(category: LicenseCategory): string {
43
+ switch (category) {
44
+ case LicenseCategory.STRONG_COPYLEFT:
45
+ return 'Strong Copyleft';
46
+
47
+ case LicenseCategory.WEAK_COPYLEFT:
48
+ return 'Weak Copyleft';
49
+
50
+ case LicenseCategory.PERMISSIVE:
51
+ return 'Permissive';
52
+
53
+ case LicenseCategory.UNKNOWN:
54
+ return 'Unknown';
55
+ }
56
+ }
@@ -0,0 +1,3 @@
1
+ export * from './LicenseCategory';
2
+ export * from './descriptions';
3
+ export * from './licenseAnalysis';
@@ -0,0 +1,78 @@
1
+ import { STRONG_COPYLEFT_LICENSES_LOWERCASE, WEAK_COPYLEFT_LICENSES_LOWERCASE } from '../constants/licenses';
2
+ import type { AggregatedLicensesMapping } from '../types';
3
+ import type { LicenseAnalysisResult } from '../types/LicenseAnalysisResult';
4
+
5
+ import { LicenseCategory } from './LicenseCategory';
6
+ import { getGraphStateInfo } from './descriptions';
7
+
8
+ /**
9
+ * Categorizes a license based on its copyleft characteristics.
10
+ * @param licenseType the license type
11
+ * @returns the license category
12
+ */
13
+ export function categorizeLicense(licenseType?: string): LicenseCategory {
14
+ if (!licenseType || licenseType === 'unknown') {
15
+ return LicenseCategory.UNKNOWN;
16
+ }
17
+
18
+ // check for strong copyleft licenses
19
+ if (STRONG_COPYLEFT_LICENSES_LOWERCASE.has(licenseType.toLowerCase())) {
20
+ return LicenseCategory.STRONG_COPYLEFT;
21
+ }
22
+
23
+ // check for weak copyleft licenses
24
+ if (WEAK_COPYLEFT_LICENSES_LOWERCASE.has(licenseType.toLowerCase())) {
25
+ return LicenseCategory.WEAK_COPYLEFT;
26
+ }
27
+
28
+ // everything else is considered permissive
29
+ return LicenseCategory.PERMISSIVE;
30
+ }
31
+
32
+ /**
33
+ * Analyzes license data and returns comprehensive statistics.
34
+ * @param report the licenses report data
35
+ * @returns the license analysis result
36
+ */
37
+ export function analyzeLicenses(report: AggregatedLicensesMapping): LicenseAnalysisResult {
38
+ const byCategory: Record<LicenseCategory, number> = {
39
+ [LicenseCategory.STRONG_COPYLEFT]: 0,
40
+ [LicenseCategory.WEAK_COPYLEFT]: 0,
41
+ [LicenseCategory.PERMISSIVE]: 0,
42
+ [LicenseCategory.UNKNOWN]: 0,
43
+ };
44
+
45
+ const byLicense: Record<string, number> = {};
46
+ const categorizedLicenses: Record<string, LicenseCategory> = {};
47
+
48
+ Object.entries(report).forEach(([packageKey, license]) => {
49
+ const licenseType = license.type;
50
+ const category = categorizeLicense(licenseType);
51
+
52
+ // stats by category
53
+ byCategory[category]++;
54
+
55
+ // stats by specific license
56
+ {
57
+ const key = licenseType ?? 'unknown';
58
+
59
+ byLicense[key] = (byLicense[key] ?? 0) + 1;
60
+ }
61
+
62
+ // memoization for lookup
63
+ categorizedLicenses[packageKey] = category;
64
+ });
65
+
66
+ const total = Object.keys(report).length;
67
+
68
+ const { categoriesPresence, description } = getGraphStateInfo(byCategory);
69
+
70
+ return {
71
+ total,
72
+ byCategory,
73
+ byLicense,
74
+ description,
75
+ categoriesPresence,
76
+ categorizedLicenses,
77
+ };
78
+ }
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
 
4
4
  import glob from 'glob';
5
5
 
@@ -7,13 +7,16 @@ import type {
7
7
  AboutLibrariesLibraryJsonPayload,
8
8
  AboutLibrariesLicenseJsonPayload,
9
9
  AboutLibrariesLikePackageInfo,
10
- AggregatedLicensesObj,
10
+ AggregatedLicensesMapping,
11
11
  DependencyType,
12
12
  LicensePlistPayload,
13
+ ParentPackageInfo,
13
14
  ScanPackageCallContext,
14
15
  ScanPackageOptionsFactory,
15
- } from './types';
16
- import { PackageUtils, YamlUtils } from './utils';
16
+ } from '../types';
17
+ import { YamlUtils } from '../utils';
18
+
19
+ import { PackageUtils } from './utils';
17
20
 
18
21
  type InternalScanGroupSpecifier = { packages: [depName: string, depVersion: string][]; dependencyType: DependencyType };
19
22
 
@@ -32,7 +35,7 @@ function scanPackage(
32
35
  packageName: string,
33
36
  requiredVersion: string,
34
37
  processedPackages: Set<string>,
35
- result: AggregatedLicensesObj,
38
+ result: AggregatedLicensesMapping,
36
39
  scanOptionsFactory: ScanPackageOptionsFactory = PackageUtils.legacyDefaultScanPackageOptionsFactory,
37
40
  {
38
41
  parentPackageRoot,
@@ -83,21 +86,37 @@ function scanPackage(
83
86
 
84
87
  const resolvedVersionPackageKey = `${packageName}@${localPackageJson.version}`;
85
88
 
86
- result[resolvedVersionPackageKey] = {
87
- name: packageName,
88
- author: PackageUtils.parseAuthorField(localPackageJson),
89
- content: licenseFiles?.[0] ? fs.readFileSync(licenseFiles[0], { encoding: 'utf-8' }) : undefined,
90
- file: licenseFiles?.[0] ? licenseFiles[0] : undefined,
91
- description: localPackageJson.description,
92
- type: PackageUtils.parseLicenseField(localPackageJson),
93
- url: PackageUtils.parseRepositoryFieldToUrl(localPackageJson),
94
- version: localPackageJson.version,
95
- requiredVersion,
96
- parentPackageName,
97
- parentPackageRequiredVersion,
98
- parentPackageResolvedVersion,
99
- dependencyType,
100
- };
89
+ let parentPackageInfo: ParentPackageInfo | undefined;
90
+ if (parentPackageName && parentPackageRequiredVersion && parentPackageResolvedVersion) {
91
+ parentPackageInfo = {
92
+ name: parentPackageName,
93
+ requiredVersion: parentPackageRequiredVersion,
94
+ resolvedVersion: parentPackageResolvedVersion,
95
+ };
96
+ }
97
+
98
+ if (parentPackageInfo && resolvedVersionPackageKey in result) {
99
+ result[resolvedVersionPackageKey].parentPackages = [
100
+ ...(result[resolvedVersionPackageKey].parentPackages ?? []),
101
+ parentPackageInfo,
102
+ ];
103
+ } else {
104
+ result[resolvedVersionPackageKey] = {
105
+ name: packageName,
106
+ author: PackageUtils.parseAuthorField(localPackageJson),
107
+ content: licenseFiles?.[0] ? fs.readFileSync(licenseFiles[0], { encoding: 'utf-8' }) : undefined,
108
+ file: licenseFiles?.[0] ? licenseFiles[0] : undefined,
109
+ description: localPackageJson.description,
110
+ type: PackageUtils.parseLicenseField(localPackageJson),
111
+ url: PackageUtils.parseRepositoryFieldToUrl(localPackageJson),
112
+ version: localPackageJson.version,
113
+ requiredVersion,
114
+ parentPackages: parentPackageInfo ? [parentPackageInfo] : [],
115
+ parentPackageRequiredVersion,
116
+ parentPackageResolvedVersion,
117
+ dependencyType,
118
+ };
119
+ }
101
120
  }
102
121
 
103
122
  const dependencies: MaybeDependencyMapping = localPackageJson.dependencies;
@@ -161,12 +180,12 @@ type MaybeDependencyMapping = DependencyMapping | undefined;
161
180
  export function scanDependencies(
162
181
  appPackageJsonPath: string,
163
182
  scanOptionsFactory: ScanPackageOptionsFactory = PackageUtils.legacyDefaultScanPackageOptionsFactory,
164
- ): AggregatedLicensesObj {
183
+ ): AggregatedLicensesMapping {
165
184
  const appPackageJson = require(path.resolve(appPackageJsonPath));
166
185
  const dependencies: MaybeDependencyMapping = appPackageJson.dependencies;
167
186
  const devDependencies: MaybeDependencyMapping = appPackageJson.devDependencies;
168
187
  const optionalDependencies: MaybeDependencyMapping = appPackageJson.optionalDependencies;
169
- const result: AggregatedLicensesObj = {};
188
+ const result: AggregatedLicensesMapping = {};
170
189
  const processedPackages = new Set<string>();
171
190
 
172
191
  const rootScanOptions = scanOptionsFactory({ isRoot: true, isWorkspacePackage: false });
@@ -205,24 +224,22 @@ export function scanDependencies(
205
224
  * @param iosProjectPath Path to the iOS project directory
206
225
  * @see {@link writeLicensePlistNPMOutput}
207
226
  */
208
- export function generateLicensePlistNPMOutput(licenses: AggregatedLicensesObj, iosProjectPath: string): string {
227
+ export function generateLicensePlistNPMOutput(licenses: AggregatedLicensesMapping, iosProjectPath: string): string {
209
228
  const renames: Record<string, string> = {};
210
- const licenseEntries = Object.entries(licenses).map(([packageKey, licenseObj]) => {
229
+ const licenseEntries = Object.entries(licenses).map(([packageKey, license]) => {
211
230
  const normalizedPackageNameWithVersion = PackageUtils.normalizePackageName(packageKey);
212
231
 
213
- if (licenseObj.name !== normalizedPackageNameWithVersion) {
214
- renames[normalizedPackageNameWithVersion] = licenseObj.name;
232
+ if (license.name !== normalizedPackageNameWithVersion) {
233
+ renames[normalizedPackageNameWithVersion] = license.name;
215
234
  }
216
235
 
217
- const relativeLicenseFile = licenseObj.file ? path.relative(iosProjectPath, licenseObj.file) : undefined;
236
+ const relativeLicenseFile = license.file ? path.relative(iosProjectPath, license.file) : undefined;
218
237
 
219
238
  return {
220
239
  name: normalizedPackageNameWithVersion,
221
- version: licenseObj.version,
222
- ...(licenseObj.url && { source: licenseObj.url }),
223
- ...(licenseObj.file
224
- ? { file: relativeLicenseFile }
225
- : { body: licenseObj.content ?? licenseObj.type ?? 'UNKNOWN' }),
240
+ version: license.version,
241
+ ...(license.url && { source: license.url }),
242
+ ...(license.file ? { file: relativeLicenseFile } : { body: license.content ?? license.type ?? 'UNKNOWN' }),
226
243
  } as LicensePlistPayload;
227
244
  });
228
245
 
@@ -261,7 +278,7 @@ export function generateLicensePlistNPMOutput(licenses: AggregatedLicensesObj, i
261
278
  * @see {@link generateLicensePlistNPMOutput}
262
279
  */
263
280
  export function writeLicensePlistNPMOutput(
264
- licenses: AggregatedLicensesObj,
281
+ licenses: AggregatedLicensesMapping,
265
282
  iosProjectPath: string,
266
283
  plistLikeOutput?: string,
267
284
  ) {
@@ -281,20 +298,20 @@ export function writeLicensePlistNPMOutput(
281
298
  * @returns Array of AboutLibrariesLikePackage objects, each representing a NPM dependency
282
299
  * @see {@link writeAboutLibrariesNPMOutput}
283
300
  */
284
- export function generateAboutLibrariesNPMOutput(licenses: AggregatedLicensesObj): AboutLibrariesLikePackageInfo[] {
301
+ export function generateAboutLibrariesNPMOutput(licenses: AggregatedLicensesMapping): AboutLibrariesLikePackageInfo[] {
285
302
  return Object.entries(licenses)
286
- .map(([packageKey, licenseObj]) => {
303
+ .map(([packageKey, license]) => {
287
304
  return {
288
- artifactVersion: licenseObj.version,
289
- content: licenseObj.content ?? '',
290
- description: licenseObj.description ?? '',
291
- developers: [{ name: licenseObj.author ?? '', organisationUrl: '' }],
292
- licenses: [PackageUtils.prepareAboutLibrariesLicenseField(licenseObj)],
293
- name: licenseObj.name,
305
+ artifactVersion: license.version,
306
+ content: license.content ?? '',
307
+ description: license.description ?? '',
308
+ developers: [{ name: license.author ?? '', organisationUrl: '' }],
309
+ licenses: [PackageUtils.prepareAboutLibrariesLicenseField(license)],
310
+ name: license.name,
294
311
  tag: '',
295
- type: licenseObj.type,
312
+ type: license.type,
296
313
  uniqueId: PackageUtils.normalizePackageName(packageKey),
297
- website: licenseObj.url,
314
+ website: license.url,
298
315
  };
299
316
  })
300
317
  .map((jsonPayload) => {
@@ -344,7 +361,7 @@ export function generateAboutLibrariesNPMOutput(licenses: AggregatedLicensesObj)
344
361
  * @see {@link generateAboutLibrariesNPMOutput}
345
362
  */
346
363
  export function writeAboutLibrariesNPMOutput(
347
- licenses: AggregatedLicensesObj,
364
+ licenses: AggregatedLicensesMapping,
348
365
  androidProjectPath: string,
349
366
  aboutLibrariesLikeOutput?: AboutLibrariesLikePackageInfo[],
350
367
  ) {
@@ -0,0 +1,3 @@
1
+ export * from './common';
2
+ export * from './utils';
3
+ export * from '../';
@@ -0,0 +1,2 @@
1
+ export * as PackageUtils from './packageUtils';
2
+ export * as MiscUtils from './miscUtils';