@callstack/licenses 0.3.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build/constants/licenses.d.ts +4 -0
- package/build/constants/licenses.js +15 -15
- package/build/licenses/OrPolicy.d.ts +21 -0
- package/build/licenses/OrPolicy.js +16 -0
- package/build/licenses/index.d.ts +3 -0
- package/build/licenses/index.js +3 -0
- package/build/licenses/licenseAnalysis.d.ts +7 -8
- package/build/licenses/licenseAnalysis.js +15 -29
- package/build/licenses/licenseClassification.d.ts +52 -0
- package/build/licenses/licenseClassification.js +136 -0
- package/build/licenses/licenseExpression.d.ts +37 -0
- package/build/licenses/licenseExpression.js +166 -0
- package/build/node/common.d.ts +23 -2
- package/build/node/common.js +159 -56
- package/build/node/index.d.ts +1 -0
- package/build/node/index.js +1 -0
- package/build/node/mergeLicensesMappings.d.ts +8 -0
- package/build/node/mergeLicensesMappings.js +28 -0
- package/build/node/utils/aboutLibrariesLicenses.d.ts +11 -0
- package/build/node/utils/aboutLibrariesLicenses.js +58 -0
- package/build/node/utils/licenseFiles.d.ts +8 -0
- package/build/node/utils/licenseFiles.js +45 -0
- package/build/node/utils/licensePlistBody.d.ts +6 -0
- package/build/node/utils/licensePlistBody.js +20 -0
- package/build/node/utils/packageUtils.d.ts +14 -5
- package/build/node/utils/packageUtils.js +35 -23
- package/build/types/AboutLibrariesLikePackageInfo.d.ts +1 -1
- package/build/types/License.d.ts +14 -6
- package/build/types/LicenseAnalysisResult.d.ts +7 -0
- package/build/types/LicenseExpression.d.ts +39 -0
- package/build/types/LicenseExpression.js +2 -0
- package/build/types/LicenseFile.d.ts +8 -0
- package/build/types/LicenseFile.js +2 -0
- package/build/types/LicenseStats.d.ts +1 -1
- package/build/types/ScanDependenciesOptions.d.ts +12 -0
- package/build/types/ScanDependenciesOptions.js +2 -0
- package/build/types/index.d.ts +3 -0
- package/build/types/index.js +3 -0
- package/package.json +9 -6
- package/src/constants/licenses.ts +15 -15
- package/src/licenses/OrPolicy.ts +23 -0
- package/src/licenses/index.ts +3 -0
- package/src/licenses/licenseAnalysis.ts +19 -33
- package/src/licenses/licenseClassification.ts +173 -0
- package/src/licenses/licenseExpression.ts +200 -0
- package/src/node/common.ts +217 -66
- package/src/node/index.ts +1 -0
- package/src/node/mergeLicensesMappings.ts +32 -0
- package/src/node/utils/aboutLibrariesLicenses.ts +69 -0
- package/src/node/utils/licenseFiles.ts +50 -0
- package/src/node/utils/licensePlistBody.ts +18 -0
- package/src/node/utils/packageUtils.ts +37 -26
- package/src/types/AboutLibrariesLikePackageInfo.ts +1 -1
- package/src/types/License.ts +16 -7
- package/src/types/LicenseAnalysisResult.ts +8 -0
- package/src/types/LicenseExpression.ts +22 -0
- package/src/types/LicenseFile.ts +10 -0
- package/src/types/LicenseStats.ts +1 -1
- package/src/types/ScanDependenciesOptions.ts +12 -0
- package/src/types/index.ts +3 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { renderLicenseExpression } from '../../licenses';
|
|
2
|
+
import type { License, LicenseExpression } from '../../types';
|
|
3
|
+
|
|
4
|
+
import { sha512 } from './miscUtils';
|
|
5
|
+
|
|
6
|
+
type LicenseLeaf = Extract<LicenseExpression, { kind: 'license' }>;
|
|
7
|
+
|
|
8
|
+
function collectLicenseLeaves(expression: LicenseExpression): LicenseLeaf[] {
|
|
9
|
+
switch (expression.kind) {
|
|
10
|
+
case 'license':
|
|
11
|
+
return [expression];
|
|
12
|
+
case 'and':
|
|
13
|
+
case 'or':
|
|
14
|
+
return [...collectLicenseLeaves(expression.left), ...collectLicenseLeaves(expression.right)];
|
|
15
|
+
case 'unknown':
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getAboutLibrariesEntries(license: License): { id?: string; name: string }[] {
|
|
21
|
+
const leavesById = new Map(collectLicenseLeaves(license.license).map((leaf) => [leaf.id, leaf]));
|
|
22
|
+
|
|
23
|
+
if (leavesById.size > 0) {
|
|
24
|
+
return [...leavesById.values()].map((leaf) => ({ id: leaf.id, name: renderLicenseExpression(leaf) }));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Unknown License: the Raw License is the best name we have
|
|
28
|
+
if (license.rawLicense) {
|
|
29
|
+
return [{ name: license.rawLicense }];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// nothing declared, but the package ships a license text, so keep it
|
|
33
|
+
if (license.licenseFiles.length > 0) {
|
|
34
|
+
return [{ name: renderLicenseExpression(license.license) }];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* One AboutLibraries license per License Identifier (or the Raw License when it is Unknown). Its name keeps
|
|
42
|
+
* a retained `+` and the License Exception; its content is the linked license file, else every unlinked text
|
|
43
|
+
* when the package has one license or exactly one unlinked text.
|
|
44
|
+
*/
|
|
45
|
+
export function prepareAboutLibrariesLicenses(license: License): { name: string; content: string }[] {
|
|
46
|
+
const entries = getAboutLibrariesEntries(license);
|
|
47
|
+
const unlinkedTexts = license.licenseFiles.filter((file) => !file.licenseId).map((file) => file.content);
|
|
48
|
+
|
|
49
|
+
// unlinked texts go to every license when there is only one text (it may cover all of them),
|
|
50
|
+
// or when there is only one license (it owns every text)
|
|
51
|
+
const sharedContent = entries.length === 1 || unlinkedTexts.length === 1 ? unlinkedTexts.join('\n\n') : '';
|
|
52
|
+
|
|
53
|
+
return entries.map(({ id, name }) => ({
|
|
54
|
+
name,
|
|
55
|
+
content: (id ? license.licenseFiles.find((file) => file.licenseId === id)?.content : undefined) ?? sharedContent,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function prepareAboutLibrariesLicenseField(name: string, content?: string) {
|
|
60
|
+
// The returned value is used as a filename under `android/config/licenses/`.
|
|
61
|
+
// Legacy/compound SPDX expressions like `MIT/X11` or `(MIT OR Apache-2.0)` would
|
|
62
|
+
// otherwise produce paths containing `/`, `(` or spaces, which causes the writer
|
|
63
|
+
// to either fail with ENOENT (when a `/` is interpreted as a subdirectory) or
|
|
64
|
+
// to produce names that are invalid on some filesystems.
|
|
65
|
+
const sanitizedName = name.replace(/[^A-Za-z0-9._-]/g, '_');
|
|
66
|
+
|
|
67
|
+
// hash the unsanitized name when there is no text, so that names differing only in sanitized characters stay distinct
|
|
68
|
+
return `${sanitizedName}_${sha512(content || name)}`;
|
|
69
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { glob } from 'glob';
|
|
5
|
+
|
|
6
|
+
import type { LicenseFile } from '../../types';
|
|
7
|
+
|
|
8
|
+
// `LICEN{S,C}E*` also matches code and data files such as `license.js` or `licenses.json`
|
|
9
|
+
const NON_LICENSE_EXTENSIONS = new Set(['.js', '.cjs', '.mjs', '.ts', '.cts', '.mts', '.tsx', '.jsx', '.json', '.map']);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reads every license file (`LICEN{S,C}E*`, `COPYING*`, case-insensitive) from the package root.
|
|
13
|
+
*
|
|
14
|
+
* A file is linked to a License Identifier by its name suffix (e.g. `LICENSE-APACHE` → `Apache-2.0`),
|
|
15
|
+
* but only when exactly one of `licenseIds` matches; otherwise it is listed without an identifier.
|
|
16
|
+
*/
|
|
17
|
+
export function readLicenseFiles(packageDir: string, licenseIds: string[]): LicenseFile[] {
|
|
18
|
+
return glob
|
|
19
|
+
.sync('{LICEN{S,C}E*,COPYING*}', { cwd: packageDir, absolute: true, nocase: true, nodir: true })
|
|
20
|
+
.sort()
|
|
21
|
+
.filter((file) => !NON_LICENSE_EXTENSIONS.has(path.extname(file).toLowerCase()))
|
|
22
|
+
.map((file) => {
|
|
23
|
+
const licenseId = linkLicenseId(path.basename(file), licenseIds);
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
file,
|
|
27
|
+
content: fs.readFileSync(file, { encoding: 'utf-8' }),
|
|
28
|
+
...(licenseId && { licenseId }),
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function linkLicenseId(fileName: string, licenseIds: string[]): string | undefined {
|
|
34
|
+
const suffix = fileName
|
|
35
|
+
.replace(/\.(txt|md)$/i, '')
|
|
36
|
+
.replace(/^(licen[sc]e|copying)[-_. ]*/i, '')
|
|
37
|
+
.toLowerCase();
|
|
38
|
+
|
|
39
|
+
if (!suffix) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const matching = licenseIds.filter((id) => {
|
|
44
|
+
const lowerId = id.toLowerCase();
|
|
45
|
+
|
|
46
|
+
return lowerId === suffix || lowerId.startsWith(`${suffix}-`);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return matching.length === 1 ? matching[0] : undefined;
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { renderLicenseExpression } from '../../licenses';
|
|
4
|
+
import type { License } from '../../types';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* LicensePlist body: every license text under a per-license heading (plain text, as LicensePlist shows
|
|
8
|
+
* bodies verbatim); the rendered License Expression when there is no text.
|
|
9
|
+
*/
|
|
10
|
+
export function buildLicensePlistBody(license: License) {
|
|
11
|
+
if (license.licenseFiles.length === 0) {
|
|
12
|
+
return renderLicenseExpression(license.license);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return license.licenseFiles
|
|
16
|
+
.map(({ file, content, licenseId }) => `=== ${licenseId ?? path.basename(file)} ===\n\n${content.trim()}`)
|
|
17
|
+
.join('\n\n');
|
|
18
|
+
}
|
|
@@ -1,35 +1,49 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { ScanPackageOptionsFactory } from '../../types';
|
|
5
5
|
import { normalizeRepositoryUrl } from '../../utils/repositoryUtils';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
export { prepareAboutLibrariesLicenseField, prepareAboutLibrariesLicenses } from './aboutLibrariesLicenses';
|
|
8
|
+
export { buildLicensePlistBody } from './licensePlistBody';
|
|
9
|
+
export { readLicenseFiles } from './licenseFiles';
|
|
8
10
|
|
|
9
|
-
export function getPackageJsonPath(dependency: string, root?: string) {
|
|
11
|
+
export function getPackageJsonPath(dependency: string, root?: string, projectRoot: string = process.cwd()) {
|
|
10
12
|
const rootsToSearch = [
|
|
11
13
|
...(root ? [root] : []), // provided for purpose of nested node_modules resolution inside a package dir, in a subdirectory inside the root node_modules dir
|
|
12
|
-
|
|
14
|
+
projectRoot, // fallback - root node_modules directory home
|
|
13
15
|
]; // in order of priority (left-to-right)
|
|
14
16
|
|
|
15
17
|
try {
|
|
16
18
|
return require.resolve(`${dependency}/package.json`, { paths: rootsToSearch });
|
|
17
19
|
} catch (error) {
|
|
18
20
|
for (const root of rootsToSearch) {
|
|
19
|
-
const pkgJsonInNodeModules =
|
|
21
|
+
const pkgJsonInNodeModules = findPackageJsonInNodeModules(dependency, root);
|
|
20
22
|
|
|
21
|
-
if (
|
|
23
|
+
if (pkgJsonInNodeModules) {
|
|
22
24
|
return pkgJsonInNodeModules;
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
return resolvePackageJsonFromEntry(dependency); // final fallback
|
|
28
|
+
return resolvePackageJsonFromEntry(dependency, rootsToSearch); // final fallback
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
function findPackageJsonInNodeModules(dependency: string, startDir: string) {
|
|
33
|
+
for (let currentDir = startDir; ; currentDir = path.dirname(currentDir)) {
|
|
34
|
+
if (path.basename(currentDir) !== 'node_modules') {
|
|
35
|
+
const pkgJsonInNodeModules = path.join(currentDir, 'node_modules', dependency, 'package.json');
|
|
36
|
+
|
|
37
|
+
if (fs.existsSync(pkgJsonInNodeModules)) return fs.realpathSync(pkgJsonInNodeModules);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (currentDir === path.dirname(currentDir)) return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function resolvePackageJsonFromEntry(dependency: string, paths?: string[]) {
|
|
31
45
|
try {
|
|
32
|
-
const entryPath = require.resolve(dependency);
|
|
46
|
+
const entryPath = require.resolve(dependency, paths ? { paths } : undefined);
|
|
33
47
|
const packageDir = findPackageRoot(entryPath);
|
|
34
48
|
|
|
35
49
|
if (!packageDir) return null;
|
|
@@ -54,21 +68,6 @@ export function normalizePackageName(packageName: string): string {
|
|
|
54
68
|
return packageName.replace('/', '_');
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
export function prepareAboutLibrariesLicenseField(license: License) {
|
|
58
|
-
if (!license.type) {
|
|
59
|
-
return '';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// The returned value is used as a filename under `android/config/licenses/`.
|
|
63
|
-
// Legacy/compound SPDX expressions like `MIT/X11` or `(MIT OR Apache-2.0)` would
|
|
64
|
-
// otherwise produce paths containing `/`, `(` or spaces, which causes the writer
|
|
65
|
-
// to either fail with ENOENT (when a `/` is interpreted as a subdirectory) or
|
|
66
|
-
// to produce names that are invalid on some filesystems.
|
|
67
|
-
const sanitizedType = license.type.replace(/[^A-Za-z0-9._-]/g, '_');
|
|
68
|
-
|
|
69
|
-
return `${sanitizedType}_${sha512(license.content ?? sanitizedType)}`;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
71
|
export function parseAuthorField(json: { author: string | { name: string } }) {
|
|
73
72
|
if (typeof json.author === 'object' && typeof json.author.name === 'string') {
|
|
74
73
|
return json.author.name;
|
|
@@ -79,14 +78,26 @@ export function parseAuthorField(json: { author: string | { name: string } }) {
|
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Reads the Raw License from package.json: the `license` string, the legacy `license: { type }` object,
|
|
83
|
+
* or the legacy `licenses: [{ type }, …]` array, whose types are joined with ` OR `.
|
|
84
|
+
*/
|
|
85
|
+
export function parseLicenseField(json: { license?: string | { type: string }; licenses?: Array<{ type?: string }> }) {
|
|
86
|
+
if (typeof json.license === 'object' && typeof json.license?.type === 'string') {
|
|
84
87
|
return json.license.type;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
if (typeof json.license === 'string') {
|
|
88
91
|
return json.license;
|
|
89
92
|
}
|
|
93
|
+
|
|
94
|
+
if (Array.isArray(json.licenses)) {
|
|
95
|
+
const types = json.licenses.flatMap((entry) =>
|
|
96
|
+
typeof entry?.type === 'string' && entry.type.trim() !== '' ? [entry.type] : [],
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return types.length > 0 ? types.join(' OR ') : undefined;
|
|
100
|
+
}
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
export function parseRepositoryFieldToUrl(json: { repository: string | { url?: string } }) {
|
|
@@ -4,5 +4,5 @@ import type { AboutLibrariesLicenseJsonPayload } from './AboutLibrariesLicenseJs
|
|
|
4
4
|
export type AboutLibrariesLikePackageInfo = {
|
|
5
5
|
normalizedPackageNameWithVersion: string;
|
|
6
6
|
libraryJsonPayload: AboutLibrariesLibraryJsonPayload;
|
|
7
|
-
|
|
7
|
+
licenseJsonPayloads: AboutLibrariesLicenseJsonPayload[];
|
|
8
8
|
};
|
package/src/types/License.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { DependencyType } from './DependencyType';
|
|
2
|
+
import type { LicenseExpression } from './LicenseExpression';
|
|
3
|
+
import type { LicenseFile } from './LicenseFile';
|
|
2
4
|
import type { ParentPackageInfo } from './ParentPackageInfo';
|
|
3
5
|
import type { ScanPackageCallContext } from './ScanPackageCallContext';
|
|
4
6
|
|
|
@@ -9,17 +11,24 @@ export type License = {
|
|
|
9
11
|
/** Package author */
|
|
10
12
|
author?: string;
|
|
11
13
|
|
|
12
|
-
/** Package license contents */
|
|
13
|
-
content?: string;
|
|
14
|
-
|
|
15
14
|
/** Package description */
|
|
16
15
|
description?: string;
|
|
17
16
|
|
|
18
|
-
/**
|
|
19
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Raw License: the license declaration exactly as written in package.json;
|
|
19
|
+
* for the legacy `licenses: [{ type }]` array, the types joined with ` OR `;
|
|
20
|
+
* `null` if the package declares no license
|
|
21
|
+
*/
|
|
22
|
+
rawLicense: string | null;
|
|
23
|
+
|
|
24
|
+
/** Parsed License Expression of {@link License.rawLicense} */
|
|
25
|
+
license: LicenseExpression;
|
|
26
|
+
|
|
27
|
+
/** Canonical SPDX License Identifiers found in {@link License.license}; empty for an Unknown License */
|
|
28
|
+
licenseIds: string[];
|
|
20
29
|
|
|
21
|
-
/** License
|
|
22
|
-
|
|
30
|
+
/** Every license file found in the package root, each linked to its License Identifier where unambiguous */
|
|
31
|
+
licenseFiles: LicenseFile[];
|
|
23
32
|
|
|
24
33
|
/** Package repository URL */
|
|
25
34
|
url?: string;
|
|
@@ -3,5 +3,13 @@ import type { LicenseCategory } from '../licenses/LicenseCategory';
|
|
|
3
3
|
import type { LicenseStats } from './LicenseStats';
|
|
4
4
|
|
|
5
5
|
export interface LicenseAnalysisResult extends LicenseStats {
|
|
6
|
+
/**
|
|
7
|
+
* Mapping of package key (`<package-name>@<package-version>`) to the License Category of that package
|
|
8
|
+
*/
|
|
6
9
|
categorizedLicenses: Record<string, LicenseCategory>;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Mapping of rendered License Expression to its License Category; has the same keys as {@link LicenseStats.byLicense}
|
|
13
|
+
*/
|
|
14
|
+
categoryByLicense: Record<string, LicenseCategory>;
|
|
7
15
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured meaning of a package's Raw License, following the SPDX License Expression
|
|
3
|
+
* syntax (SPDX spec v3.0.1, Annex B).
|
|
4
|
+
*
|
|
5
|
+
* The tree is binary: `A OR B OR C` is represented as `A OR (B OR C)`.
|
|
6
|
+
*
|
|
7
|
+
* @see https://spdx.github.io/spdx-spec/v3.0.1/annexes/spdx-license-expressions/
|
|
8
|
+
*/
|
|
9
|
+
export type LicenseExpression =
|
|
10
|
+
/**
|
|
11
|
+
* A single license, identified by its SPDX License Identifier (e.g. `MIT`).
|
|
12
|
+
* - `id` is canonical: deprecated identifiers are upgraded and `+` is absorbed into `-or-later` when such an identifier exists
|
|
13
|
+
* - `declaredId` and `plus` record what was written
|
|
14
|
+
* - `exception` is the License Exception attached with `WITH`
|
|
15
|
+
*/
|
|
16
|
+
| { kind: 'license'; id: string; declaredId: string; plus?: boolean; exception?: string }
|
|
17
|
+
/** Dual License: the licensee may comply with either operand */
|
|
18
|
+
| { kind: 'or'; left: LicenseExpression; right: LicenseExpression }
|
|
19
|
+
/** Both operands apply and must be complied with simultaneously */
|
|
20
|
+
| { kind: 'and'; left: LicenseExpression; right: LicenseExpression }
|
|
21
|
+
/** Unknown License: missing, unparseable, or not a license grant; `raw` keeps the original value */
|
|
22
|
+
| { kind: 'unknown'; raw: string | null };
|
|
@@ -12,7 +12,7 @@ export interface LicenseStats {
|
|
|
12
12
|
byCategory: Record<LicenseCategory, number>;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* Mapping of
|
|
15
|
+
* Mapping of rendered License Expression to count of packages with that expression
|
|
16
16
|
*/
|
|
17
17
|
byLicense: Record<string, number>;
|
|
18
18
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additional options for scanning dependencies of a project
|
|
3
|
+
*/
|
|
4
|
+
export type ScanDependenciesOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Paths to other project directories whose dependencies are scanned too,
|
|
7
|
+
* e.g. monorepo workspaces the app does not depend on;
|
|
8
|
+
* relative paths are resolved against the real directory (with symlinks resolved) of the scanned `package.json`;
|
|
9
|
+
* each of them must be a directory with a `package.json`, otherwise an error is thrown
|
|
10
|
+
*/
|
|
11
|
+
additionalProjectRoots?: readonly string[];
|
|
12
|
+
};
|
package/src/types/index.ts
CHANGED
|
@@ -5,8 +5,11 @@ export * from './AboutLibrariesLicenseJsonPayload';
|
|
|
5
5
|
export * from './LicensePlistPayload';
|
|
6
6
|
export * from './AboutLibrariesLikePackageInfo';
|
|
7
7
|
export * from './ScanPackageOptions';
|
|
8
|
+
export * from './ScanDependenciesOptions';
|
|
8
9
|
export * from './ScanPackageCallContext';
|
|
9
10
|
export * from './DependencyType';
|
|
10
11
|
export * from './ParentPackageInfo';
|
|
11
12
|
export * from './LicenseAnalysisResult';
|
|
12
13
|
export * from './LicenseStats';
|
|
14
|
+
export * from './LicenseExpression';
|
|
15
|
+
export * from './LicenseFile';
|