From 5da1866571795ebbdbb6a41e56fe14e1545a29bc Mon Sep 17 00:00:00 2001 From: Nazar Sydiaha Date: Mon, 26 Jan 2026 10:24:15 +0100 Subject: [PATCH 1/2] feat(#9): provide customization options to the underlying native license generators --- docs/docs/docs/react-native.mdx | 22 +++++++++++- .../bare-plugin/src/android/androidCommand.ts | 10 ++++-- .../applyAndConfigureAboutLibrariesPlugin.ts | 7 ++-- .../bare-plugin/src/index.ts | 10 +++--- .../bare-plugin/src/ios/iosCommand.ts | 10 ++++-- .../src/ios/registerLicensePlistBuildPhase.ts | 5 +-- .../plugin-utils/src/android.ts | 29 ++++++++++++--- .../plugin-utils/src/ios.ts | 23 +++++++++++- .../plugin-utils/src/types.ts | 14 ++++++++ .../applyAndConfigureAboutLibrariesPlugin.ts | 4 ++- .../plugin/src/android/withAndroidLegal.ts | 7 ++-- .../react-native-legal/plugin/src/index.ts | 12 +++++-- .../src/ios/registerLicensePlistBuildPhase.ts | 5 +-- .../plugin/src/ios/withIosLegal.ts | 4 +-- .../react-native-legal/plugin/src/types.ts | 10 ++++-- .../react-native-legal/react-native.config.js | 35 +++++++++++++++++-- 16 files changed, 173 insertions(+), 34 deletions(-) diff --git a/docs/docs/docs/react-native.mdx b/docs/docs/docs/react-native.mdx index d3763c2..5fc99f6 100644 --- a/docs/docs/docs/react-native.mdx +++ b/docs/docs/docs/react-native.mdx @@ -53,7 +53,14 @@ This will ensure the required native dependencies are included. + { + "devDepsMode": "root-only", + "includeOptionalDeps": true, -+ "transitiveDepsMode": "all" ++ "transitiveDepsMode": "all", ++ "aboutLibraries": { ++ "gitHubApiToken": "YOUR_GITHUB_TOKEN" ++ }, ++ "licensePlist": { ++ "githubToken": "YOUR_GITHUB_TOKEN", ++ "addVersionNumbers": true ++ } + } + ] + ] @@ -75,6 +82,16 @@ interface PluginOptions { // `'none'` (no transitive dependencies of direct dependencies) // @default `'all'` transitiveDepsMode?: 'all' | 'from-external-only' | 'from-workspace-only' | 'none'; + aboutLibraries?: { + // GitHub API token used by AboutLibraries to resolve metadata. + gitHubApiToken?: string; + }; + licensePlist?: { + // GitHub token passed to LicensePlist (helps avoid rate limits). + githubToken?: string; + // @default `true` + addVersionNumbers?: boolean; + }; } ``` @@ -97,6 +114,9 @@ This will extract and prepare license metadata for use in your app. | `--tm, --transitive-deps-mode [mode]` | Controls, which transitive dependencies are included: | `'all'` | | `--dm, --dev-deps-mode [mode]` | | `'none'` | | `--od, --include-optional-deps [include]` | Whether to include optionalDependencies in the scan; other flags apply | `true` | +| `--al, --about-libraries-github-api-token [token]` | GitHub API token used by AboutLibraries to resolve metadata | — | +| `--github-token [token]` | GitHub token passed to LicensePlist (helps avoid rate limits) | — | +| `--add-version-numbers [boolean]` | Whether LicensePlist should add version numbers to entries | `true` | ## Usage diff --git a/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts b/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts index f1a9e76..2410786 100644 --- a/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts @@ -3,6 +3,8 @@ import path from 'node:path'; import { type Types as SharedTypes, scanDependencies, writeAboutLibrariesNPMOutput } from '@callstack/licenses'; +import type { AboutLibrariesOptions } from '../../../plugin-utils/build/types'; + import { addListActivity } from './addListActivity'; import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin'; import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin'; @@ -13,7 +15,11 @@ import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin'; * It scans the NPM dependencies, generates AboutLibraries-compatible metadata for them, * installs & configures AboutLibraries Gradle plugin and adds Android Activity with a list of dependencies and their licenses */ -export function androidCommand(androidProjectPath: string, scanOptionsFactory: SharedTypes.ScanPackageOptionsFactory) { +export function androidCommand( + androidProjectPath: string, + scanOptionsFactory: SharedTypes.ScanPackageOptionsFactory, + aboutLibraries?: AboutLibrariesOptions, +) { const licenses = scanDependencies( path.join(path.resolve(androidProjectPath, '..'), 'package.json'), scanOptionsFactory, @@ -27,6 +33,6 @@ export function androidCommand(androidProjectPath: string, scanOptionsFactory: S writeAboutLibrariesNPMOutput(licenses, androidProjectPath); declareAboutLibrariesPlugin(androidProjectPath); - applyAndConfigureAboutLibrariesPlugin(androidProjectPath); + applyAndConfigureAboutLibrariesPlugin(androidProjectPath, aboutLibraries); addListActivity(androidProjectPath); } diff --git a/packages/react-native-legal/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts b/packages/react-native-legal/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts index 708081a..a93b868 100644 --- a/packages/react-native-legal/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts +++ b/packages/react-native-legal/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts @@ -2,6 +2,7 @@ import fs from 'fs'; import path from 'path'; import { applyAndConfigureAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android'; +import type { AboutLibrariesOptions } from '../../../plugin-utils/build/types'; import { modifyFileContent } from './utils'; @@ -10,11 +11,13 @@ import { modifyFileContent } from './utils'; * * NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script) */ -export function applyAndConfigureAboutLibrariesPlugin(androidProjectPath: string) { +export function applyAndConfigureAboutLibrariesPlugin(androidProjectPath: string, options?: AboutLibrariesOptions) { if (fs.existsSync(path.join(androidProjectPath, 'app', 'build.gradle.kts'))) { console.warn('Gradle Kotlin scripts are not supported yet'); } else if (fs.existsSync(path.join(androidProjectPath, 'app', 'build.gradle'))) { - modifyFileContent(path.join(androidProjectPath, 'app', 'build.gradle'), applyAndConfigureAboutLibrariesPluginUtil); + modifyFileContent(path.join(androidProjectPath, 'app', 'build.gradle'), (content) => + applyAndConfigureAboutLibrariesPluginUtil(content, options), + ); } else { console.warn('Cannot find app/build.gradle file'); } diff --git a/packages/react-native-legal/bare-plugin/src/index.ts b/packages/react-native-legal/bare-plugin/src/index.ts index 95825cd..72f4438 100644 --- a/packages/react-native-legal/bare-plugin/src/index.ts +++ b/packages/react-native-legal/bare-plugin/src/index.ts @@ -1,5 +1,5 @@ import { createPluginScanOptionsFactory } from '../../plugin-utils/build/common'; -import type { PluginScanOptions } from '../../plugin-utils/build/types'; +import type { PluginOptions, PluginScanOptions } from '../../plugin-utils/build/types'; import { androidCommand } from './android/androidCommand'; import { iosCommand } from './ios/iosCommand'; @@ -7,16 +7,18 @@ import { iosCommand } from './ios/iosCommand'; function generateLegal( androidProjectPath: string | undefined, iosProjectPath: string | undefined, - pluginScanOptions: PluginScanOptions, + pluginOptions: PluginOptions, ) { + const { aboutLibraries, licensePlist, ...scanOptions } = pluginOptions; + const pluginScanOptions: PluginScanOptions = scanOptions; const scanOptionsFactory = createPluginScanOptionsFactory(pluginScanOptions); if (androidProjectPath) { - androidCommand(androidProjectPath, scanOptionsFactory); + androidCommand(androidProjectPath, scanOptionsFactory, aboutLibraries); } if (iosProjectPath) { - iosCommand(iosProjectPath, scanOptionsFactory); + iosCommand(iosProjectPath, scanOptionsFactory, licensePlist); } } diff --git a/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts b/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts index fd6d21a..8e7325b 100644 --- a/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts @@ -2,6 +2,8 @@ import path from 'node:path'; import { type Types as SharedTypes, scanDependencies, writeLicensePlistNPMOutput } from '@callstack/licenses'; +import type { LicensePlistOptions } from '../../../plugin-utils/build/types'; + import { addSettingsBundle } from './addSettingsBundle'; import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase'; @@ -11,11 +13,15 @@ import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase * It scans the NPM dependencies, generates LicensePlist-compatible metadata for them, * configures Settings.bundle and registers a shell script generating LicensePlist metadata for iOS dependencies */ -export function iosCommand(iosProjectPath: string, scanOptionsFactory: SharedTypes.ScanPackageOptionsFactory) { +export function iosCommand( + iosProjectPath: string, + scanOptionsFactory: SharedTypes.ScanPackageOptionsFactory, + licensePlist?: LicensePlistOptions, +) { const licenses = scanDependencies(path.join(path.resolve(iosProjectPath, '..'), 'package.json'), scanOptionsFactory); writeLicensePlistNPMOutput(licenses, iosProjectPath); addSettingsBundle(iosProjectPath); - registerLicensePlistBuildPhase(iosProjectPath); + registerLicensePlistBuildPhase(iosProjectPath, licensePlist); } diff --git a/packages/react-native-legal/bare-plugin/src/ios/registerLicensePlistBuildPhase.ts b/packages/react-native-legal/bare-plugin/src/ios/registerLicensePlistBuildPhase.ts index 752b3e8..ccf1e93 100644 --- a/packages/react-native-legal/bare-plugin/src/ios/registerLicensePlistBuildPhase.ts +++ b/packages/react-native-legal/bare-plugin/src/ios/registerLicensePlistBuildPhase.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import { registerLicensePlistBuildPhaseUtil } from '../../../plugin-utils/build/ios'; +import type { LicensePlistOptions } from '../../../plugin-utils/build/types'; import { getAllApplicationNativeTargets, getIOSPbxProj } from './utils'; @@ -10,12 +11,12 @@ import { getAllApplicationNativeTargets, getIOSPbxProj } from './utils'; * It scans available application native targets and for each of them * creates and links a shell script build phase responsible for iOS native deps license metadata */ -export function registerLicensePlistBuildPhase(iosProjectPath: string) { +export function registerLicensePlistBuildPhase(iosProjectPath: string, options?: LicensePlistOptions) { const { pbxproj, pbxprojPath } = getIOSPbxProj(iosProjectPath); const nativeTargets = getAllApplicationNativeTargets(pbxproj); nativeTargets.map((nativeTarget) => { - registerLicensePlistBuildPhaseUtil(nativeTarget.uuid, pbxproj); + registerLicensePlistBuildPhaseUtil(nativeTarget.uuid, pbxproj, options); }); fs.writeFileSync(pbxprojPath, pbxproj.writeSync()); diff --git a/packages/react-native-legal/plugin-utils/src/android.ts b/packages/react-native-legal/plugin-utils/src/android.ts index 4318b0f..a86a690 100644 --- a/packages/react-native-legal/plugin-utils/src/android.ts +++ b/packages/react-native-legal/plugin-utils/src/android.ts @@ -1,5 +1,7 @@ import { MiscUtils } from '@callstack/licenses'; +import type { AboutLibrariesOptions } from './types'; + /** * Applies Gradle Plugin Portal & AboutLibraries Gradle plugin repositories (if needed) inside root build.gradle */ @@ -32,7 +34,10 @@ export function declareAboutLibrariesPluginUtil(androidBuildGradleContent: strin /** * Applies and configures AboutLibraries Grale plugin (if needed) inside app's build.gradle */ -export function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuildGradleContent: string) { +export function applyAndConfigureAboutLibrariesPluginUtil( + androidAppBuildGradleContent: string, + options?: AboutLibrariesOptions, +) { // Apply plugin const applyPluginBlockRegex = new RegExp(`apply\\s+plugin:\\s+['"]${PLUGIN_APPLY_BLOCK_IDENTIFIER}['"]`); @@ -44,15 +49,29 @@ export function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuildGradleC } // Configure plugin - const pluginConfigRegex = /aboutLibraries {/; + const pluginConfigRegex = /aboutLibraries\s*{/; + const hasConfigBlock = androidAppBuildGradleContent.match(pluginConfigRegex)?.length; + const gitHubApiToken = options?.gitHubApiToken; + + if (!hasConfigBlock) { + const tokenLine = gitHubApiToken ? ` gitHubApiToken = "${gitHubApiToken}"\n` : ''; - if (!androidAppBuildGradleContent.match(pluginConfigRegex)?.length) { - androidAppBuildGradleContent += '\n\naboutLibraries {\n configPath = "config"\n prettyPrint = true\n}\n'; + androidAppBuildGradleContent += `\n\naboutLibraries {\n configPath = "config"\n prettyPrint = true\n${tokenLine}}\n`; console.log('About Libraries Gradle Plugin - CONFIGURED'); } else { - console.log('About Libraries Gradle Plugin already configured - SKIP'); + if (gitHubApiToken && !androidAppBuildGradleContent.match(/gitHubApiToken\s*=/)?.length) { + androidAppBuildGradleContent = androidAppBuildGradleContent.replace( + pluginConfigRegex, + `aboutLibraries {\n gitHubApiToken = "${gitHubApiToken}"`, + ); + console.log('About Libraries Gradle Plugin - UPDATED'); + } else { + console.log('About Libraries Gradle Plugin already configured - SKIP'); + } } + console.log('androidAppBuildGradleContent', androidAppBuildGradleContent); + return androidAppBuildGradleContent; } diff --git a/packages/react-native-legal/plugin-utils/src/ios.ts b/packages/react-native-legal/plugin-utils/src/ios.ts index fee0a3b..0db153b 100644 --- a/packages/react-native-legal/plugin-utils/src/ios.ts +++ b/packages/react-native-legal/plugin-utils/src/ios.ts @@ -3,6 +3,8 @@ import path from 'node:path'; import type { XcodeProject } from 'xcode'; +import type { LicensePlistOptions } from './types'; + /** * Creates a Settings.bundle from a template and invokes a callback responsible for linking new file to the iOS project */ @@ -35,9 +37,28 @@ export function addSettingsBundleUtil( /** * Creates a shell script build phase (if needed) and links it to native targets build phases */ +export function buildLicensePlistShellScript(options?: LicensePlistOptions) { + const args = ['${PODS_ROOT}/LicensePlist/license-plist']; + + if (options?.addVersionNumbers !== false) { + args.push('--add-version-numbers'); + } + + if (options?.githubToken) { + const quotedToken = `'${options.githubToken.replace(/'/g, `'\\''`)}'`; + + args.push(`--github-token ${quotedToken}`); + } + + args.push('--output-path ./Settings.bundle'); + + return args.join(' '); +} + export function registerLicensePlistBuildPhaseUtil( projectTargetId: string, pbxproj: XcodeProject, // Xcode Pbxproj + options?: LicensePlistOptions, ) { const nativeTargetSection = pbxproj.pbxNativeTargetSection(); const nativeTarget = nativeTargetSection[projectTargetId]; @@ -59,7 +80,7 @@ export function registerLicensePlistBuildPhaseUtil( projectTargetId, { shellPath: '/bin/sh', - shellScript: '${PODS_ROOT}/LicensePlist/license-plist --add-version-numbers --output-path ./Settings.bundle', + shellScript: buildLicensePlistShellScript(options), }, ); /** diff --git a/packages/react-native-legal/plugin-utils/src/types.ts b/packages/react-native-legal/plugin-utils/src/types.ts index 24974c6..952e201 100644 --- a/packages/react-native-legal/plugin-utils/src/types.ts +++ b/packages/react-native-legal/plugin-utils/src/types.ts @@ -3,3 +3,17 @@ export interface PluginScanOptions { includeOptionalDeps: boolean; transitiveDepsMode: 'all' | 'from-external-only' | 'from-workspace-only' | 'none'; } + +export interface AboutLibrariesOptions { + gitHubApiToken?: string; +} + +export interface LicensePlistOptions { + githubToken?: string; + addVersionNumbers?: boolean; +} + +export interface PluginOptions extends PluginScanOptions { + aboutLibraries?: AboutLibrariesOptions; + licensePlist?: LicensePlistOptions; +} diff --git a/packages/react-native-legal/plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts b/packages/react-native-legal/plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts index c6cf329..f0f89f4 100644 --- a/packages/react-native-legal/plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts +++ b/packages/react-native-legal/plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts @@ -2,17 +2,19 @@ import type { ExpoConfig } from 'expo/config'; import { withAppBuildGradle } from 'expo/config-plugins'; import { applyAndConfigureAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android'; +import type { AboutLibrariesOptions } from '../../../plugin-utils/build/types'; /** * Modifies application's build.gradle with AboutLibraries plugin * * NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script) */ -export function applyAndConfigureAboutLibrariesPlugin(config: ExpoConfig): ExpoConfig { +export function applyAndConfigureAboutLibrariesPlugin(config: ExpoConfig, options?: AboutLibrariesOptions): ExpoConfig { return withAppBuildGradle(config, (exportedConfig) => { if (exportedConfig.modResults.language === 'groovy') { exportedConfig.modResults.contents = applyAndConfigureAboutLibrariesPluginUtil( exportedConfig.modResults.contents, + options, ); } else { console.warn('Gradle Kotlin scripts are not supported yet'); diff --git a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts index 7bdc98c..1f53c66 100644 --- a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts +++ b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts @@ -15,7 +15,10 @@ import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin'; * It scans the NPM dependencies, generates AboutLibraries-compatible metadata, * installs & configures AboutLibraries Gradle plugin and adds Android Activity with a list of dependencies and their licenses */ -export const withAndroidLegal: ConfigPlugin = (config, { scanOptionsFactory }) => { +export const withAndroidLegal: ConfigPlugin = ( + config, + { scanOptionsFactory, aboutLibraries }, +) => { withAndroidManifest(config, async (exportedConfig) => { const licenses = scanDependencies( path.join(exportedConfig.modRequest.projectRoot, 'package.json'), @@ -26,7 +29,7 @@ export const withAndroidLegal: ConfigPlugin = (config, { return exportedConfig; }); config = declareAboutLibrariesPlugin(config); - config = applyAndConfigureAboutLibrariesPlugin(config); + config = applyAndConfigureAboutLibrariesPlugin(config, aboutLibraries); config = addListActivity(config); return config; }; diff --git a/packages/react-native-legal/plugin/src/index.ts b/packages/react-native-legal/plugin/src/index.ts index a0eadea..14f3b03 100644 --- a/packages/react-native-legal/plugin/src/index.ts +++ b/packages/react-native-legal/plugin/src/index.ts @@ -12,12 +12,18 @@ import type { PluginOptions } from './types'; const pak = require('react-native-legal/package.json'); const withReactNativeLegal: ConfigPlugin = (config, options) => { - const { devDepsMode = 'none', includeOptionalDeps = true, transitiveDepsMode = 'all' } = options ?? {}; + const { + devDepsMode = 'none', + includeOptionalDeps = true, + transitiveDepsMode = 'all', + aboutLibraries, + licensePlist, + } = options ?? {}; const pluginScanOptions: PluginScanOptions = { devDepsMode, includeOptionalDeps, transitiveDepsMode }; const scanOptionsFactory = createPluginScanOptionsFactory(pluginScanOptions); - config = withAndroidLegal(config, { scanOptionsFactory }); - config = withIosLegal(config, { scanOptionsFactory }); + config = withAndroidLegal(config, { scanOptionsFactory, aboutLibraries }); + config = withIosLegal(config, { scanOptionsFactory, licensePlist }); return config; }; diff --git a/packages/react-native-legal/plugin/src/ios/registerLicensePlistBuildPhase.ts b/packages/react-native-legal/plugin/src/ios/registerLicensePlistBuildPhase.ts index d406dc7..05d87ec 100644 --- a/packages/react-native-legal/plugin/src/ios/registerLicensePlistBuildPhase.ts +++ b/packages/react-native-legal/plugin/src/ios/registerLicensePlistBuildPhase.ts @@ -2,6 +2,7 @@ import type { ExpoConfig } from 'expo/config'; import { IOSConfig, withXcodeProject } from 'expo/config-plugins'; import { registerLicensePlistBuildPhaseUtil } from '../../../plugin-utils/build/ios'; +import type { LicensePlistOptions } from '../../../plugin-utils/build/types'; /** * Registers a shell script that invokes generation of license metadata with LicensePlist @@ -9,7 +10,7 @@ import { registerLicensePlistBuildPhaseUtil } from '../../../plugin-utils/build/ * It looks for the first application native target (Expo projects will only have single native target) * for which it creates & links a shell script build phase responsible for iOS native deps license metadata */ -export function registerLicensePlistBuildPhase(config: ExpoConfig): ExpoConfig { +export function registerLicensePlistBuildPhase(config: ExpoConfig, options?: LicensePlistOptions): ExpoConfig { return withXcodeProject(config, (exportedConfig) => { const projectName = IOSConfig.XcodeUtils.getProjectName(exportedConfig.modRequest.projectRoot); const projectTargetId = IOSConfig.XcodeUtils.getApplicationNativeTarget({ @@ -17,7 +18,7 @@ export function registerLicensePlistBuildPhase(config: ExpoConfig): ExpoConfig { projectName, }).uuid; - exportedConfig.modResults = registerLicensePlistBuildPhaseUtil(projectTargetId, exportedConfig.modResults); + exportedConfig.modResults = registerLicensePlistBuildPhaseUtil(projectTargetId, exportedConfig.modResults, options); return exportedConfig; }); diff --git a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts index 92cd875..3488bd8 100644 --- a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts +++ b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts @@ -14,7 +14,7 @@ import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase * It scans the NPM dependencies, generates LicensePlist-compatible metadata, * configures Settings.bundle and registers a shell script generating LicensePlist metadata for iOS dependencies */ -export const withIosLegal: ConfigPlugin = (config, { scanOptionsFactory }) => { +export const withIosLegal: ConfigPlugin = (config, { scanOptionsFactory, licensePlist }) => { withXcodeProject(config, async (exportedConfig) => { const licenses = scanDependencies( path.join(exportedConfig.modRequest.projectRoot, 'package.json'), @@ -25,6 +25,6 @@ export const withIosLegal: ConfigPlugin = (config, { scan return exportedConfig; }); config = addSettingsBundle(config); - config = registerLicensePlistBuildPhase(config); + config = registerLicensePlistBuildPhase(config, licensePlist); return config; }; diff --git a/packages/react-native-legal/plugin/src/types.ts b/packages/react-native-legal/plugin/src/types.ts index f9c43ed..2b0d432 100644 --- a/packages/react-native-legal/plugin/src/types.ts +++ b/packages/react-native-legal/plugin/src/types.ts @@ -1,9 +1,15 @@ import type { Types as SharedTypes } from '@callstack/licenses'; -import type { PluginScanOptions } from '../../plugin-utils/build/types'; +import type { + AboutLibrariesOptions, + LicensePlistOptions, + PluginOptions as SharedPluginOptions, +} from '../../plugin-utils/build/types'; -export type PluginOptions = PluginScanOptions; +export type PluginOptions = SharedPluginOptions; export type PlatformPluginOptions = { scanOptionsFactory: SharedTypes.ScanPackageOptionsFactory; + aboutLibraries?: AboutLibrariesOptions; + licensePlist?: LicensePlistOptions; }; diff --git a/packages/react-native-legal/react-native.config.js b/packages/react-native-legal/react-native.config.js index b3c3c61..319cced 100644 --- a/packages/react-native-legal/react-native.config.js +++ b/packages/react-native-legal/react-native.config.js @@ -36,13 +36,42 @@ module.exports = { }, default: 'all', }, + { + name: '--al, --about-libraries-github-api-token ', + description: 'GitHub API token used by AboutLibraries to resolve metadata', + parse: (val) => val, + }, + { + name: '--github-token ', + description: 'GitHub token passed to LicensePlist (helps avoid rate limits)', + parse: (val) => val, + }, + { + name: '--add-version-numbers [boolean]', + description: 'Whether LicensePlist should add version numbers to entries', + parse: (val) => val !== 'false', + default: true, + }, ], func: ([], { project: { android, ios } }, args) => { const generateLegal = require('./bare-plugin/build').default; - /** @type {import('./plugin-utils/build/types').PluginScanOptions} */ - const { devDepsMode, includeOptionalDeps, transitiveDepsMode } = args; + /** @type {import('./plugin-utils/build/types').PluginOptions} */ + const { + devDepsMode, + includeOptionalDeps, + transitiveDepsMode, + aboutLibrariesGithubApiToken, + githubToken, + addVersionNumbers, + } = args; - generateLegal(android?.sourceDir, ios?.sourceDir, { devDepsMode, includeOptionalDeps, transitiveDepsMode }); + generateLegal(android?.sourceDir, ios?.sourceDir, { + devDepsMode, + includeOptionalDeps, + transitiveDepsMode, + aboutLibraries: aboutLibrariesGithubApiToken ? { gitHubApiToken: aboutLibrariesGithubApiToken } : undefined, + licensePlist: { githubToken, addVersionNumbers }, + }); }, }, ], From 45e6752eb1e9b6bdf565a5499e70276404b8db03 Mon Sep 17 00:00:00 2001 From: Nazar Sydiaha Date: Mon, 26 Jan 2026 12:56:04 +0100 Subject: [PATCH 2/2] chore: add changeset --- .changeset/huge-jeans-laugh.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/huge-jeans-laugh.md diff --git a/.changeset/huge-jeans-laugh.md b/.changeset/huge-jeans-laugh.md new file mode 100644 index 0000000..1ff4605 --- /dev/null +++ b/.changeset/huge-jeans-laugh.md @@ -0,0 +1,5 @@ +--- +'react-native-legal': minor +--- + +Expose AboutLibraries and LicensePlist token options in the Expo plugin and RN CLI.