@callstack/licenses 0.2.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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -0
  3. package/build/common.d.ts +71 -0
  4. package/build/common.js +308 -0
  5. package/build/index.d.ts +3 -0
  6. package/build/index.js +42 -0
  7. package/build/types/AboutLibrariesLibraryJsonPayload.d.ts +13 -0
  8. package/build/types/AboutLibrariesLibraryJsonPayload.js +2 -0
  9. package/build/types/AboutLibrariesLicenseJsonPayload.d.ts +6 -0
  10. package/build/types/AboutLibrariesLicenseJsonPayload.js +2 -0
  11. package/build/types/AboutLibrariesLikePackageInfo.d.ts +7 -0
  12. package/build/types/AboutLibrariesLikePackageInfo.js +2 -0
  13. package/build/types/AggregatedLicensesObj.d.ts +6 -0
  14. package/build/types/AggregatedLicensesObj.js +2 -0
  15. package/build/types/DependencyType.d.ts +3 -0
  16. package/build/types/DependencyType.js +2 -0
  17. package/build/types/LicenseObj.d.ts +24 -0
  18. package/build/types/LicenseObj.js +2 -0
  19. package/build/types/LicensePlistPayload.d.ts +7 -0
  20. package/build/types/LicensePlistPayload.js +2 -0
  21. package/build/types/ScanPackageCallContext.d.ts +25 -0
  22. package/build/types/ScanPackageCallContext.js +2 -0
  23. package/build/types/ScanPackageOptions.d.ts +24 -0
  24. package/build/types/ScanPackageOptions.js +2 -0
  25. package/build/types/index.d.ts +9 -0
  26. package/build/types/index.js +25 -0
  27. package/build/utils/index.d.ts +4 -0
  28. package/build/utils/index.js +40 -0
  29. package/build/utils/miscUtils.d.ts +6 -0
  30. package/build/utils/miscUtils.js +39 -0
  31. package/build/utils/packageUtils.d.ts +26 -0
  32. package/build/utils/packageUtils.js +100 -0
  33. package/build/utils/repositoryUtils.d.ts +1 -0
  34. package/build/utils/repositoryUtils.js +18 -0
  35. package/build/utils/yamlUtils.d.ts +4 -0
  36. package/build/utils/yamlUtils.js +64 -0
  37. package/package.json +67 -0
  38. package/src/common.ts +384 -0
  39. package/src/index.ts +3 -0
  40. package/src/types/AboutLibrariesLibraryJsonPayload.ts +10 -0
  41. package/src/types/AboutLibrariesLicenseJsonPayload.ts +6 -0
  42. package/src/types/AboutLibrariesLikePackageInfo.ts +8 -0
  43. package/src/types/AggregatedLicensesObj.ts +7 -0
  44. package/src/types/DependencyType.ts +3 -0
  45. package/src/types/LicenseObj.ts +34 -0
  46. package/src/types/LicensePlistPayload.ts +7 -0
  47. package/src/types/ScanPackageCallContext.ts +30 -0
  48. package/src/types/ScanPackageOptions.ts +29 -0
  49. package/src/types/index.ts +9 -0
  50. package/src/utils/index.ts +4 -0
  51. package/src/utils/miscUtils.ts +42 -0
  52. package/src/utils/packageUtils.ts +103 -0
  53. package/src/utils/repositoryUtils.ts +17 -0
  54. package/src/utils/yamlUtils.ts +73 -0
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Scan options for controlling which dependencies of a package are scanned
3
+ */
4
+ export type ScanPackageOptions = {
5
+ /** Whether transitive dependencies should be scanned */
6
+ includeTransitiveDependencies: boolean;
7
+ /** Whether to include devDependencies in the scan; includeTransitiveDependencies option applies */
8
+ includeDevDependencies: boolean;
9
+ /** Whether to include optionalDependencies in the scan; includeTransitiveDependencies option applies */
10
+ includeOptionalDependencies: boolean;
11
+ };
12
+ /**
13
+ * Information about a single package to be scanned
14
+ */
15
+ export type ScanPackageOptionsFactoryPackageInfo = {
16
+ /** `true` if the analyzed package.json is the root of the scanned project */
17
+ isRoot: boolean;
18
+ /** `true` if the analyzed package.json is a dependency related to the project via a `workspace:...` dependency specifier */
19
+ isWorkspacePackage: boolean;
20
+ };
21
+ /**
22
+ * Factory to create a filter for scan options for dependencies of a given package
23
+ */
24
+ export type ScanPackageOptionsFactory = (packageInfo: ScanPackageOptionsFactoryPackageInfo) => ScanPackageOptions;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ export * from './LicenseObj';
2
+ export * from './AggregatedLicensesObj';
3
+ export * from './AboutLibrariesLibraryJsonPayload';
4
+ export * from './AboutLibrariesLicenseJsonPayload';
5
+ export * from './LicensePlistPayload';
6
+ export * from './AboutLibrariesLikePackageInfo';
7
+ export * from './ScanPackageOptions';
8
+ export * from './ScanPackageCallContext';
9
+ export * from './DependencyType';
@@ -0,0 +1,25 @@
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("./LicenseObj"), exports);
18
+ __exportStar(require("./AggregatedLicensesObj"), exports);
19
+ __exportStar(require("./AboutLibrariesLibraryJsonPayload"), exports);
20
+ __exportStar(require("./AboutLibrariesLicenseJsonPayload"), exports);
21
+ __exportStar(require("./LicensePlistPayload"), exports);
22
+ __exportStar(require("./AboutLibrariesLikePackageInfo"), exports);
23
+ __exportStar(require("./ScanPackageOptions"), exports);
24
+ __exportStar(require("./ScanPackageCallContext"), exports);
25
+ __exportStar(require("./DependencyType"), exports);
@@ -0,0 +1,4 @@
1
+ export * as PackageUtils from './packageUtils';
2
+ export * as MiscUtils from './miscUtils';
3
+ export * as RepositoryUtils from './repositoryUtils';
4
+ export * as YamlUtils from './yamlUtils';
@@ -0,0 +1,40 @@
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.YamlUtils = exports.RepositoryUtils = exports.MiscUtils = exports.PackageUtils = void 0;
37
+ exports.PackageUtils = __importStar(require("./packageUtils"));
38
+ exports.MiscUtils = __importStar(require("./miscUtils"));
39
+ exports.RepositoryUtils = __importStar(require("./repositoryUtils"));
40
+ exports.YamlUtils = __importStar(require("./yamlUtils"));
@@ -0,0 +1,6 @@
1
+ export declare function sha512(text: string): string;
2
+ export declare function compareObjects(a: unknown, b: unknown): boolean;
3
+ /**
4
+ * Makes a deep-check between array items and provided object, returns true if array has provided object.
5
+ */
6
+ export declare function arrayIncludesObject(array?: unknown[], object?: unknown): boolean | undefined;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.sha512 = sha512;
7
+ exports.compareObjects = compareObjects;
8
+ exports.arrayIncludesObject = arrayIncludesObject;
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ function sha512(text) {
11
+ return crypto_1.default.createHash('sha512').update(text).digest('hex');
12
+ }
13
+ function compareObjects(a, b) {
14
+ if (a == null || b == null || typeof a !== 'object' || typeof b !== 'object') {
15
+ return a === b;
16
+ }
17
+ const entriesA = Object.entries(a);
18
+ const entriesB = Object.entries(b);
19
+ return (entriesA.length === entriesB.length &&
20
+ entriesA
21
+ .map(([keyA, valueA]) => {
22
+ const entry = entriesB.find(([keyB]) => keyA === keyB);
23
+ if (!entry) {
24
+ return valueA === entry;
25
+ }
26
+ const [, valueB] = entry;
27
+ return compareObjects(valueA, valueB);
28
+ })
29
+ .reduce((acc, curr) => acc && curr, true));
30
+ }
31
+ /**
32
+ * Makes a deep-check between array items and provided object, returns true if array has provided object.
33
+ */
34
+ function arrayIncludesObject(array, object) {
35
+ if (!Array.isArray(array)) {
36
+ return;
37
+ }
38
+ return array.map((item) => compareObjects(item, object)).reduce((acc, curr) => acc || curr, false);
39
+ }
@@ -0,0 +1,26 @@
1
+ import type { LicenseObj, ScanPackageOptionsFactory } from '../types';
2
+ export declare function getPackageJsonPath(dependency: string, root?: string): string | null;
3
+ export declare function resolvePackageJsonFromEntry(dependency: string): string | null;
4
+ export declare function findPackageRoot(entryPath: string): string | undefined;
5
+ export declare function normalizePackageName(packageName: string): string;
6
+ export declare function prepareAboutLibrariesLicenseField(license: LicenseObj): string;
7
+ export declare function parseAuthorField(json: {
8
+ author: string | {
9
+ name: string;
10
+ };
11
+ }): string | undefined;
12
+ export declare function parseLicenseField(json: {
13
+ license: string | {
14
+ type: string;
15
+ };
16
+ }): string | undefined;
17
+ export declare function parseRepositoryFieldToUrl(json: {
18
+ repository: string | {
19
+ url?: string;
20
+ };
21
+ }): string | undefined;
22
+ /**
23
+ * Default value consistent with legacy behaviour assumptions for the scan package options factory
24
+ * used so as not to introduce breaking API changes to the shared package
25
+ */
26
+ export declare const legacyDefaultScanPackageOptionsFactory: ScanPackageOptionsFactory;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.legacyDefaultScanPackageOptionsFactory = void 0;
7
+ exports.getPackageJsonPath = getPackageJsonPath;
8
+ exports.resolvePackageJsonFromEntry = resolvePackageJsonFromEntry;
9
+ exports.findPackageRoot = findPackageRoot;
10
+ exports.normalizePackageName = normalizePackageName;
11
+ exports.prepareAboutLibrariesLicenseField = prepareAboutLibrariesLicenseField;
12
+ exports.parseAuthorField = parseAuthorField;
13
+ exports.parseLicenseField = parseLicenseField;
14
+ exports.parseRepositoryFieldToUrl = parseRepositoryFieldToUrl;
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const miscUtils_1 = require("./miscUtils");
18
+ const repositoryUtils_1 = require("./repositoryUtils");
19
+ function getPackageJsonPath(dependency, root) {
20
+ const rootsToSearch = [
21
+ ...(root ? [root] : []), // provided for purpose of nested node_modules resolution inside a package dir, in a subdirectory inside the root node_modules dir
22
+ process.cwd(), // fallback - root node_modules directory home
23
+ ]; // in order of priority (left-to-right)
24
+ try {
25
+ return require.resolve(`${dependency}/package.json`, { paths: rootsToSearch });
26
+ }
27
+ catch (error) {
28
+ for (const root of rootsToSearch) {
29
+ const pkgJsonInNodeModules = path_1.default.join(root, 'node_modules', dependency, 'package.json');
30
+ if (fs_1.default.existsSync(pkgJsonInNodeModules)) {
31
+ return pkgJsonInNodeModules;
32
+ }
33
+ }
34
+ return resolvePackageJsonFromEntry(dependency); // final fallback
35
+ }
36
+ }
37
+ function resolvePackageJsonFromEntry(dependency) {
38
+ try {
39
+ const entryPath = require.resolve(dependency);
40
+ const packageDir = findPackageRoot(entryPath);
41
+ if (!packageDir)
42
+ return null;
43
+ const packageJsonPath = path_1.default.join(packageDir, 'package.json');
44
+ return fs_1.default.existsSync(packageJsonPath) ? packageJsonPath : null;
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ function findPackageRoot(entryPath) {
51
+ let currentDir = path_1.default.dirname(entryPath);
52
+ while (currentDir !== path_1.default.dirname(currentDir)) {
53
+ if (fs_1.default.existsSync(path_1.default.join(currentDir, 'package.json')))
54
+ return currentDir;
55
+ currentDir = path_1.default.dirname(currentDir);
56
+ }
57
+ }
58
+ function normalizePackageName(packageName) {
59
+ return packageName.replace('/', '_');
60
+ }
61
+ function prepareAboutLibrariesLicenseField(license) {
62
+ if (!license.type) {
63
+ return '';
64
+ }
65
+ return `${license.type}_${(0, miscUtils_1.sha512)(license.content ?? license.type)}`;
66
+ }
67
+ function parseAuthorField(json) {
68
+ if (typeof json.author === 'object' && typeof json.author.name === 'string') {
69
+ return json.author.name;
70
+ }
71
+ if (typeof json.author === 'string') {
72
+ return json.author;
73
+ }
74
+ }
75
+ function parseLicenseField(json) {
76
+ if (typeof json.license === 'object' && typeof json.license.type === 'string') {
77
+ return json.license.type;
78
+ }
79
+ if (typeof json.license === 'string') {
80
+ return json.license;
81
+ }
82
+ }
83
+ function parseRepositoryFieldToUrl(json) {
84
+ if (typeof json.repository === 'object' && typeof json.repository.url === 'string') {
85
+ return (0, repositoryUtils_1.normalizeRepositoryUrl)(json.repository.url);
86
+ }
87
+ if (typeof json.repository === 'string') {
88
+ return (0, repositoryUtils_1.normalizeRepositoryUrl)(json.repository);
89
+ }
90
+ }
91
+ /**
92
+ * Default value consistent with legacy behaviour assumptions for the scan package options factory
93
+ * used so as not to introduce breaking API changes to the shared package
94
+ */
95
+ const legacyDefaultScanPackageOptionsFactory = () => ({
96
+ includeTransitiveDependencies: true,
97
+ includeDevDependencies: false,
98
+ includeOptionalDependencies: true,
99
+ });
100
+ exports.legacyDefaultScanPackageOptionsFactory = legacyDefaultScanPackageOptionsFactory;
@@ -0,0 +1 @@
1
+ export declare function normalizeRepositoryUrl(url: string): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeRepositoryUrl = normalizeRepositoryUrl;
4
+ function normalizeRepositoryUrl(url) {
5
+ return (url
6
+ .replace('git+ssh://git@', 'git://')
7
+ .replace('.git', '')
8
+ .replace('git+https://github.com', 'https://github.com')
9
+ .replace('.git', '')
10
+ .replace('git://github.com', 'https://github.com')
11
+ .replace('.git', '')
12
+ .replace('git@github.com:', 'https://github.com/')
13
+ .replace('.git', '')
14
+ .replace('github:', 'https://github.com/')
15
+ .replace('.git', '')
16
+ // below: handling of edge case: git+ssh://git@github.com:X/Y.git -> https://github.com:X/Y
17
+ .replace('github.com:', 'github.com/'));
18
+ }
@@ -0,0 +1,4 @@
1
+ export declare function needsQuoting(value: string): boolean;
2
+ export declare function formatYamlKey(key: string): string;
3
+ export declare function formatYamlValue(value: string, indent: number): string;
4
+ export declare function toYaml(obj: unknown, indent?: number): string;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.needsQuoting = needsQuoting;
4
+ exports.formatYamlKey = formatYamlKey;
5
+ exports.formatYamlValue = formatYamlValue;
6
+ exports.toYaml = toYaml;
7
+ function needsQuoting(value) {
8
+ return (value === '' || // empty string
9
+ /^[#:>|-]/.test(value) || // starts with special char
10
+ /^['"{}[\],&*#?|<>=!%@`]/.test(value) || // starts with indicator chars
11
+ /^[\s]|[\s]$/.test(value) || // has leading/trailing whitespace
12
+ /^[\d.+-]/.test(value) || // looks like a number/bool/null
13
+ /[\n"'\\\s]/.test(value) || // contains newlines, quotes, backslash, or spaces
14
+ /^(true|false|yes|no|null|on|off)$/i.test(value) // is a YAML keyword
15
+ );
16
+ }
17
+ function formatYamlKey(key) {
18
+ return /[@/_.]/.test(key) ? `"${key}"` : key;
19
+ }
20
+ function formatYamlValue(value, indent) {
21
+ if (value.includes('\n')) {
22
+ const indentedValue = value
23
+ .split('\n')
24
+ .map((line) => `${' '.repeat(indent)}${line}`)
25
+ .join('\n');
26
+ // Return the block indicator on the same line as the content
27
+ return `|${indentedValue ? '\n' + indentedValue : ''}`;
28
+ }
29
+ if (needsQuoting(value)) {
30
+ if (value.includes("'") && !value.includes('"')) {
31
+ return `"${value.replace(/["\\]/g, '\\$&')}"`;
32
+ }
33
+ return `'${value.replace(/'/g, "''")}'`;
34
+ }
35
+ return value;
36
+ }
37
+ function toYaml(obj, indent = 0) {
38
+ const spaces = ' '.repeat(indent);
39
+ if (obj == null)
40
+ return '';
41
+ if (Array.isArray(obj)) {
42
+ return obj.map((item) => `${spaces}- ${toYaml(item, indent + 2).trimStart()}`).join('\n');
43
+ }
44
+ if (typeof obj === 'object') {
45
+ return Object.entries(obj)
46
+ .filter(([, v]) => v != null)
47
+ .map(([key, value]) => {
48
+ const formattedKey = formatYamlKey(key);
49
+ const formattedValue = toYaml(value, indent + 2);
50
+ if (Array.isArray(value)) {
51
+ return `${spaces}${formattedKey}:\n${formattedValue}`;
52
+ }
53
+ if (typeof value === 'object' && value !== null) {
54
+ return `${spaces}${formattedKey}:\n${formattedValue}`;
55
+ }
56
+ if (typeof value === 'string' && value.includes('\n')) {
57
+ return `${spaces}${formattedKey}: ${formattedValue}`;
58
+ }
59
+ return `${spaces}${formattedKey}: ${formattedValue}`;
60
+ })
61
+ .join('\n');
62
+ }
63
+ return typeof obj === 'string' ? formatYamlValue(obj, indent) : String(obj);
64
+ }
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@callstack/licenses",
3
+ "version": "0.2.1",
4
+ "description": "Shared code for all packages",
5
+ "main": "build/index",
6
+ "module": "build/index",
7
+ "types": "build/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "source": "./src/index.ts",
11
+ "types": "./build/index.d.ts",
12
+ "default": "./build/index.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "src",
18
+ "build",
19
+ "!**/__tests__",
20
+ "!**/__fixtures__",
21
+ "!**/__mocks__",
22
+ "!**/.*"
23
+ ],
24
+ "scripts": {
25
+ "test": "jest",
26
+ "typecheck": "tsc",
27
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
28
+ "clean": "rimraf build",
29
+ "build": "tsc -p tsconfig.json",
30
+ "dev": "tsc --watch -p tsconfig.json"
31
+ },
32
+ "keywords": [
33
+ "nodejs",
34
+ "oss",
35
+ "license",
36
+ "acknowledgements",
37
+ "license-management"
38
+ ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/callstackincubator/react-native-legal.git",
42
+ "directory": "packages/shared"
43
+ },
44
+ "author": "Mateusz Mędrek <luigimario1913@gmail.com> (https://github.com/mateusz1913)",
45
+ "license": "MIT",
46
+ "bugs": {
47
+ "url": "https://github.com/callstackincubator/react-native-legal.git/issues"
48
+ },
49
+ "homepage": "https://callstackincubator.github.io/react-native-legal/",
50
+ "publishConfig": {
51
+ "registry": "https://registry.npmjs.org/"
52
+ },
53
+ "dependencies": {
54
+ "glob": "^7.1.3"
55
+ },
56
+ "devDependencies": {
57
+ "@babel/core": "7.27.4",
58
+ "@babel/preset-env": "7.27.2",
59
+ "@babel/preset-typescript": "7.27.1",
60
+ "@types/glob": "^8.1.0",
61
+ "@types/jest": "^29.5.5",
62
+ "babel-jest": "^29.7.0",
63
+ "jest": "^29.7.0",
64
+ "rimraf": "^6.0.1",
65
+ "typescript": "^5.8.3"
66
+ }
67
+ }