Programmatic Usage (API)

In case your use case involves programmatic usage of the functionality provided by license-kit, you can use the @callstack/react-native-legal-shared package. This package exposes the core functionalities of the license management tool, allowing you to integrate it into your Node.js applications.

Installation

To get started, install the package using your preferred package manager:

npm
pnpm
yarn
bun
npm install -D @callstack/react-native-legal-shared

Usage

Basic Usage

import {
  generateAboutLibrariesNPMOutput,
  generateLicensePlistNPMOutput,
  scanDependencies,
  Types,
} from '@callstack/react-native-legal-shared';
import * as md from 'ts-markdown-builder';

// apart from dependencies, also include devDependencies, but only from the root package.json;
// also, include all transitive dependencies & optional dependencies
const optionsFactory: Types.ScanPackageOptionsFactory = ({ isRoot }) => ({
  includeDevDependencies: isRoot,
  includeTransitiveDependencies: true,
  includeOptionalDependencies: true,
});

// scan dependencies of a package
const licenses = scanDependencies(packageJsonPath, optionsFactory);

// generate AboutLibraries-compatible JSON metadata
const aboutLibrariesCompatibleReport = generateAboutLibrariesNPMOutput(licenses);

// generate LicensePlist-compatible metadata
const licensePlistReport = generateLicensePlistNPMOutput(licenses, iosProjectPath);

// generate a Markdown report
const markdownString = md
  .joinBlocks(
    Object.entries(licenses)
      .flatMap(([packageKey, { name: packageName, version, author, content, description, file, type, url }]) => [
        md.heading(packageName, { level: 2 }),
        '\n',
        `Version: ${version}<br/>\n`,
        url ? `URL: ${url}<br/>\n` : '',
        author ? `Author: ${author}<br/>\n\n` : '',
        content ?? '',
        '\n',
        description ? `Description: ${description}\n` : '',
        file ? `\nFile: ${file}\n` : '',
        type ? `Type: ${type}` : '',
        '\n',
        md.horizontalRule,
      ])
      .join('\n'),
  )
  .toString();

Options

As you can see in the example above, filtering for the packages to be included in the scan for dependencies is based on the passed in ScanPackageOptionsFactory. This factory would be invoked for every scanned package.json file, including the root and any considered dependencies and - given a ScanPackageOptionsFactoryPackageInfo object informing of the context of the package being scanned - should produce an accompanying configuration that would filter this package's dependencies.

This approach gives a programmatic control at an arbitrary level of precision over filtering of dependencies to be included.

As a reference, you can see how this is used in the license-kit CLI in createScanOptionsFactory of scanOptionsUtils.ts.

API Documentation

The API documentation is published under: https://callstackincubator.github.io/react-native-legal/api/.

Additional details

License Types

The tool recognizes various license types:

  • Strong Copyleft: Licenses that require derivative works to be released under the same license (e.g., GPL-3.0)
  • Weak Copyleft: Licenses that require derivative works to be released under the same license, but with some exceptions (e.g., LGPL-3.0)
  • Permissive: Licenses that allow for more flexible use (e.g., MIT, Apache-2.0)

Monorepo Support

react-native-legal scans dependencies from workspace packages with the workspace:* notation in your package.json in addition to the app's direct dependencies.

INFO

If a monorepo package is private, its name and license won't be included in the license list, but its dependencies will still be scanned and included.

Known Limitations

file: dependencies

WARNING

This tool (and in turn, the CLI and RN plugins) do not support file: specified dependencies, which is a known limitation. If such packages are scanned and their dependencies (of any type) are not installed in the root node_modules directory, such dependencies will not be found and included.

If you would like to have support for this, please start a discussion on Github.

Default scanOptionsFactory value

The default value for the optional scanOptionsFactory parameter in scanPackage & scanDependencies functions is set to the following:

{
  includeTransitiveDependencies: true,
  includeDevDependencies: false,
}

Which can be found in ScanPackageOptions.ts.

WARNING

This default includeDevDependencies behaviour is different from the default values of license-kit CLI's equivalent flag --dev-deps-mode, which is set to root-only by default.

To achieve the same default behaviour as in the CLI (root-only), set includeDevDependencies to isRoot in the programmatic API:

const optionsFactory: Types.ScanPackageOptionsFactory = ({ isRoot }) => ({
  includeDevDependencies: isRoot,
  includeTransitiveDependencies: ...,
  includeOptionalDependencies: ...,
});