From 908bea04fed2891f3df2d45b3eefba509806909a Mon Sep 17 00:00:00 2001 From: artus9033 Date: Mon, 9 Jun 2025 11:06:21 +0200 Subject: [PATCH 01/35] refactor: extract common logic to shared package --- .eslintrc.js | 8 +- .gitignore | 3 +- CONTRIBUTING.md | 8 +- docs/docs/docs/standalone-cli.mdx | 25 + docs/docs/index.md | 5 +- package.json | 3 +- packages/licenses-aggregator/.editorconfig | 7 + packages/licenses-aggregator/README.md | 33 + packages/licenses-aggregator/package.json | 67 ++ packages/licenses-aggregator/src/index.ts | 18 + packages/licenses-aggregator/tsconfig.json | 17 + .../bare-plugin/src/android/androidCommand.ts | 2 +- .../bare-plugin/src/ios/iosCommand.ts | 2 +- .../bare-plugin/src/ios/utils.ts | 3 +- .../bare-plugin/tsconfig.json | 2 +- packages/react-native-legal/package.json | 3 +- .../plugin-utils/src/android.ts | 2 +- .../plugin-utils/tsconfig.json | 2 +- .../plugin/src/android/withAndroidLegal.ts | 2 +- .../plugin/src/ios/withIosLegal.ts | 2 +- packages/react-native-legal/tsconfig.json | 7 +- packages/shared/package.json | 63 ++ .../plugin-utils => shared}/src/common.ts | 2 +- packages/shared/src/index.ts | 1 + packages/shared/tsconfig.json | 19 + yarn.lock | 781 +++++++++++++++++- 26 files changed, 1048 insertions(+), 39 deletions(-) create mode 100644 docs/docs/docs/standalone-cli.mdx create mode 100644 packages/licenses-aggregator/.editorconfig create mode 100644 packages/licenses-aggregator/README.md create mode 100644 packages/licenses-aggregator/package.json create mode 100644 packages/licenses-aggregator/src/index.ts create mode 100644 packages/licenses-aggregator/tsconfig.json create mode 100644 packages/shared/package.json rename packages/{react-native-legal/plugin-utils => shared}/src/common.ts (99%) create mode 100644 packages/shared/src/index.ts create mode 100644 packages/shared/tsconfig.json diff --git a/.eslintrc.js b/.eslintrc.js index 8d2523a..a8df0f5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,13 @@ /** @type {import("eslint").Linter.Config} */ const config = { root: true, - extends: '@callstack', + extends: ['@callstack', 'plugin:import/typescript'], + plugins: ['import'], + settings: { + 'import/resolver': { + typescript: {}, + }, + }, ignorePatterns: ['node_modules/', '**/node_modules/', 'lib/', '**/lib/', 'build/', '**/build/'], rules: { // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs diff --git a/.gitignore b/.gitignore index 86fb96d..c76836d 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,8 @@ project.xcworkspace # Library build/ -packages/react-native-legal/lib/ +packages/*/lib/ +packages/*/build/ # Expo example examples/expo-example/android diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4c6a374..d750703 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,8 +77,8 @@ yarn ios The codebase of Expo Config Plugin is located in: - `packages/react-native-legal/plugin` -- `packages/react-native-legal/plugin-utils` - `packages/react-native-legal/app.plugin.js` (the entry point) +- `packages/licenses-aggregator` (logic) To test the changes, build the plugin run (from the root directory, the one with consisting all workspaces): @@ -97,8 +97,8 @@ yarn expo prebuild --clean The codebase of RN CLI plugin is located in: - `packages/react-native-legal/bare-plugin` -- `packages/react-native-legal/plugin-utils` - `packages/react-native-legal/react-native.config.js` (the entry point) +- `packages/react-native-legal/licenses-aggregator` (logic) To test the changes, build the plugin run (from the root directory, the one with consisting all workspaces): @@ -145,11 +145,13 @@ yarn format:swift Objective-C code is linted and formatted using following commands: Lint code + ```sh yarn lint:objc ``` Fixing formatting errors + ```sh yarn format:objc ``` @@ -157,11 +159,13 @@ yarn format:objc For Kotlin codebase, run the following to verify code quality: Lint Kotlin code + ```sh yarn lint:android ``` Format Kotlin code + ```sh yarn format:android ``` diff --git a/docs/docs/docs/standalone-cli.mdx b/docs/docs/docs/standalone-cli.mdx new file mode 100644 index 0000000..9d47166 --- /dev/null +++ b/docs/docs/docs/standalone-cli.mdx @@ -0,0 +1,25 @@ +import { PackageManagerTabs, Badge } from '@theme'; + +# Standalone CLI + +## Installation + +To get started, install the package using your preferred package manager: + + + +## Programmatic usage (API) + +Once the setup is complete, you can easily add a button to your app to display the list of open-source licenses: + +```tsx + +``` + +This will open a native screen listing all detected licenses. The title of the screen can be customized by passing a different string argument to `launchLicenseListScreen()`. + +## Programmatic usage (API) + +## Additional details + +For more notes on the mechanics of the tool, please see [Quick Start](/docs/quick-start) diff --git a/docs/docs/index.md b/docs/docs/index.md index 5aef0c2..f1daa45 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -8,6 +8,9 @@ hero: - theme: brand text: Quick Start link: /docs/quick-start + - theme: brand + text: Standalone CLI + link: /docs/standalone-cli - theme: alt text: GitHub link: https://github.com/callstackincubator/react-native-legal @@ -21,4 +24,4 @@ features: - title: Automatic Scanning details: Automatically scans your dependencies and generates license information for both iOS and Android platforms. icon: ๐Ÿ”Ž ---- \ No newline at end of file +--- diff --git a/package.json b/package.json index 57654f1..1c3c625 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ] }, "scripts": { - "build:library": "yarn workspace react-native-legal build-plugins && yarn workspace react-native-legal build-library", + "build:library": "yarn workspace @callstack/react-native-legal-shared build && yarn workspace react-native-legal build-plugins && yarn workspace licenses-aggregator build-library && yarn workspace react-native-legal build-library", "lint:js": "eslint \"**/*.{js,ts,tsx}\"", "typescript": "yarn build:library && tsc --noEmit -p examples/bare-example/tsconfig.json && tsc --noEmit -p examples/expo-example/tsconfig.json", "lint:android": "./scripts/lint-android.sh", @@ -39,6 +39,7 @@ "@evilmartians/lefthook": "1.4.3", "commitlint": "17.6.6", "eslint": "^8.46.0", + "eslint-import-resolver-typescript": "^4.4.3", "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-prettier": "^5.0.0", "prettier": "^3.0.1", diff --git a/packages/licenses-aggregator/.editorconfig b/packages/licenses-aggregator/.editorconfig new file mode 100644 index 0000000..bb2f764 --- /dev/null +++ b/packages/licenses-aggregator/.editorconfig @@ -0,0 +1,7 @@ +[*.{h,m,mm}] +indent_style = space +indent_size = 2 + +[*.{swift}] +indent_style = space +indent_size = 2 diff --git a/packages/licenses-aggregator/README.md b/packages/licenses-aggregator/README.md new file mode 100644 index 0000000..33e34ff --- /dev/null +++ b/packages/licenses-aggregator/README.md @@ -0,0 +1,33 @@ +# licenses-aggregator + +Aggregate license notes of OSS libraries used in your Node.js project + +## Installation + +```sh +npm install licenses-aggregator +``` + +## Usage + + +```js +import { multiply } from 'licenses-aggregator'; + +// ... + +const result = await multiply(3, 7); +``` + + +## Contributing + +See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. + +## License + +MIT + +--- + +Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) diff --git a/packages/licenses-aggregator/package.json b/packages/licenses-aggregator/package.json new file mode 100644 index 0000000..6f9fa6b --- /dev/null +++ b/packages/licenses-aggregator/package.json @@ -0,0 +1,67 @@ +{ + "name": "licenses-aggregator", + "version": "1.0.0", + "description": "Aggregate license notes of OSS libraries used in your Node.js project", + "main": "build/index", + "module": "build/index", + "types": "build/index.d.ts", + "bin": { + "license-kit": "build/index.js" + }, + "exports": { + ".": { + "source": "./src/index.ts", + "types": "./build/typescript/index.d.ts", + "default": "./build/module/index.js" + }, + "./package.json": "./package.json" + }, + "files": [ + "src", + "build", + "!**/__tests__", + "!**/__fixtures__", + "!**/__mocks__", + "!**/.*" + ], + "scripts": { + "test": "jest", + "typecheck": "tsc", + "lint": "eslint \"**/*.{js,ts,tsx}\"", + "clean": "del-cli build", + "build-library": "tsc -p tsconfig.json" + }, + "keywords": [ + "nodejs", + "oss", + "license", + "acknowledgements", + "license-management" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/callstackincubator/react-native-legal.git", + "directory": "packages/licenses-aggregator" + }, + "author": "Mateusz Mฤ™drek (https://github.com/mateusz1913)", + "license": "MIT", + "bugs": { + "url": "https://github.com/callstackincubator/react-native-legal.git/issues" + }, + "homepage": "https://callstackincubator.github.io/react-native-legal/", + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "devDependencies": { + "@types/jest": "^29.5.5", + "@types/signale": "^1.4.7", + "del-cli": "^5.1.0", + "jest": "^29.7.0", + "typescript": "^5.8.3" + }, + "dependencies": { + "@callstack/react-native-legal-shared": "workspace:*", + "commander": "^14.0.0", + "signale": "^1.4.0" + } +} diff --git a/packages/licenses-aggregator/src/index.ts b/packages/licenses-aggregator/src/index.ts new file mode 100644 index 0000000..fc36a75 --- /dev/null +++ b/packages/licenses-aggregator/src/index.ts @@ -0,0 +1,18 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; + +import { scanDependencies } from '@callstack/react-native-legal-shared'; +import signale from 'signale'; + +// import Command from 'commander'; +const repoRootPath = process.cwd(); + +const packageJsonPath = path.join(repoRootPath, 'package.json'); + +if (!fs.existsSync(packageJsonPath)) { + signale.error(`package.json not found at ${packageJsonPath}`); + process.exit(1); +} + +scanDependencies(packageJsonPath); diff --git a/packages/licenses-aggregator/tsconfig.json b/packages/licenses-aggregator/tsconfig.json new file mode 100644 index 0000000..c6832ec --- /dev/null +++ b/packages/licenses-aggregator/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": ["es2020"], + "module": "commonjs", + "target": "es2020", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "outDir": "build", + "rootDir": "src" + }, + "include": ["./src"], + "exclude": ["**/__mocks__/*", "**/__tests__/*"] +} 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 21acb32..f7bbf0c 100644 --- a/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts @@ -1,6 +1,6 @@ import path from 'path'; -import { generateAboutLibrariesNPMOutput, scanDependencies } from '../../../plugin-utils/build/common'; +import { generateAboutLibrariesNPMOutput, scanDependencies } from '@callstack/react-native-legal-shared'; import { addListActivity } from './addListActivity'; import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin'; 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 2fca632..f2fb08d 100644 --- a/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts @@ -1,6 +1,6 @@ import path from 'path'; -import { generateLicensePlistNPMOutput, scanDependencies } from '../../../plugin-utils/build/common'; +import { generateLicensePlistNPMOutput, scanDependencies } from '@callstack/react-native-legal-shared'; import { addSettingsBundle } from './addSettingsBundle'; import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase'; diff --git a/packages/react-native-legal/bare-plugin/src/ios/utils.ts b/packages/react-native-legal/bare-plugin/src/ios/utils.ts index 356453d..f8ce28d 100644 --- a/packages/react-native-legal/bare-plugin/src/ios/utils.ts +++ b/packages/react-native-legal/bare-plugin/src/ios/utils.ts @@ -1,10 +1,9 @@ import path from 'path'; +import glob from 'glob'; import type { XcodeProject } from 'xcode'; import xcode from 'xcode'; -const glob = require('glob'); - const ignoredPaths = ['**/@(Carthage|Pods|vendor|node_modules)/**']; /** diff --git a/packages/react-native-legal/bare-plugin/tsconfig.json b/packages/react-native-legal/bare-plugin/tsconfig.json index 8d5bfea..af3a726 100644 --- a/packages/react-native-legal/bare-plugin/tsconfig.json +++ b/packages/react-native-legal/bare-plugin/tsconfig.json @@ -17,4 +17,4 @@ }, "include": ["./src"], "exclude": ["**/__mocks__/*", "**/__tests__/*"] -} \ No newline at end of file +} diff --git a/packages/react-native-legal/package.json b/packages/react-native-legal/package.json index a8c8f58..bee1eff 100644 --- a/packages/react-native-legal/package.json +++ b/packages/react-native-legal/package.json @@ -35,7 +35,6 @@ "ios", "lib", "plugin", - "plugin-utils", "src", "LICENSE", "app.plugin.js", @@ -49,6 +48,7 @@ "tsc": "tsc" }, "devDependencies": { + "@types/glob": "^8.1.0", "@types/xml2js": "^0.4.11", "expo": "~52.0.36", "expo-module-scripts": "^4.0.0", @@ -57,6 +57,7 @@ "react-native-builder-bob": "0.23.1" }, "dependencies": { + "@callstack/react-native-legal-shared": "workspace:*", "glob": "^7.1.3", "xcode": "^3.0.1", "xml2js": "^0.6.2" diff --git a/packages/react-native-legal/plugin-utils/src/android.ts b/packages/react-native-legal/plugin-utils/src/android.ts index ecd5855..ab3edf9 100644 --- a/packages/react-native-legal/plugin-utils/src/android.ts +++ b/packages/react-native-legal/plugin-utils/src/android.ts @@ -1,4 +1,4 @@ -import { arrayIncludesObject } from './common'; +import { arrayIncludesObject } from '@callstack/react-native-legal-shared'; /** * Applies Gradle Plugin Portal & AboutLibraries Gradle plugin repositories (if needed) inside root build.gradle diff --git a/packages/react-native-legal/plugin-utils/tsconfig.json b/packages/react-native-legal/plugin-utils/tsconfig.json index 8d5bfea..af3a726 100644 --- a/packages/react-native-legal/plugin-utils/tsconfig.json +++ b/packages/react-native-legal/plugin-utils/tsconfig.json @@ -17,4 +17,4 @@ }, "include": ["./src"], "exclude": ["**/__mocks__/*", "**/__tests__/*"] -} \ No newline at end of file +} diff --git a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts index 1eb114e..b363c9c 100644 --- a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts +++ b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts @@ -2,7 +2,7 @@ import path from 'path'; import { type ConfigPlugin, withAndroidManifest } from 'expo/config-plugins'; -import { generateAboutLibrariesNPMOutput, scanDependencies } from '../../../plugin-utils/build/common'; +import { generateAboutLibrariesNPMOutput, scanDependencies } from '../../../../shared/build/index'; import { addListActivity } from './addListActivity'; import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin'; diff --git a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts index 546a264..026b4ec 100644 --- a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts +++ b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts @@ -2,7 +2,7 @@ import path from 'path'; import { type ConfigPlugin, withXcodeProject } from 'expo/config-plugins'; -import { generateLicensePlistNPMOutput, scanDependencies } from '../../../plugin-utils/build/common'; +import { generateLicensePlistNPMOutput, scanDependencies } from '../../../../shared/build/index'; import { addSettingsBundle } from './addSettingsBundle'; import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase'; diff --git a/packages/react-native-legal/tsconfig.json b/packages/react-native-legal/tsconfig.json index 4def6ca..c9279ec 100644 --- a/packages/react-native-legal/tsconfig.json +++ b/packages/react-native-legal/tsconfig.json @@ -20,10 +20,5 @@ "strict": true, "target": "esnext" }, - "exclude": [ - "node_modules", - "bare-plugin", - "plugin", - "plugin-utils" - ], + "exclude": ["node_modules", "bare-plugin", "plugin", "plugin-utils"] } diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..e2a2a73 --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,63 @@ +{ + "name": "@callstack/react-native-legal-shared", + "version": "1.0.0", + "description": "Shared code for all packages", + "private": true, + "main": "build/index", + "module": "build/index", + "types": "build/index.d.ts", + "exports": { + ".": { + "source": "./src/index.ts", + "types": "./build/index.d.ts", + "default": "./build/index.js" + }, + "./package.json": "./package.json" + }, + "files": [ + "src", + "build", + "!**/__tests__", + "!**/__fixtures__", + "!**/__mocks__", + "!**/.*" + ], + "scripts": { + "test": "jest", + "typecheck": "tsc", + "lint": "eslint \"**/*.{js,ts,tsx}\"", + "clean": "del-cli build", + "build": "tsc -p tsconfig.json" + }, + "keywords": [ + "nodejs", + "oss", + "license", + "acknowledgements", + "license-management" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/callstackincubator/react-native-legal.git", + "directory": "packages/licenses-aggregator" + }, + "author": "Mateusz Mฤ™drek (https://github.com/mateusz1913)", + "license": "MIT", + "bugs": { + "url": "https://github.com/callstackincubator/react-native-legal.git/issues" + }, + "homepage": "https://callstackincubator.github.io/react-native-legal/", + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "dependencies": { + "glob": "^7.1.3" + }, + "devDependencies": { + "@types/glob": "^8.1.0", + "@types/jest": "^29.5.5", + "del-cli": "^5.1.0", + "jest": "^29.7.0", + "typescript": "^5.8.3" + } +} diff --git a/packages/react-native-legal/plugin-utils/src/common.ts b/packages/shared/src/common.ts similarity index 99% rename from packages/react-native-legal/plugin-utils/src/common.ts rename to packages/shared/src/common.ts index 1e7caa0..8268bb6 100644 --- a/packages/react-native-legal/plugin-utils/src/common.ts +++ b/packages/shared/src/common.ts @@ -2,7 +2,7 @@ import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; -const glob = require('glob'); +import glob from 'glob'; type LicenseObj = { author?: string; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts new file mode 100644 index 0000000..d0b9323 --- /dev/null +++ b/packages/shared/src/index.ts @@ -0,0 +1 @@ +export * from './common'; diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..a061c1f --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "declaration": true, + "lib": ["es2020"], + "module": "commonjs", + "target": "es2020", + + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + + "outDir": "build", + "rootDir": "src" + }, + "include": ["./src"], + "exclude": ["**/__mocks__/*", "**/__tests__/*"] +} diff --git a/yarn.lock b/yarn.lock index f660493..f4d0034 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3105,6 +3105,19 @@ __metadata: languageName: node linkType: hard +"@callstack/react-native-legal-shared@workspace:*, @callstack/react-native-legal-shared@workspace:packages/shared": + version: 0.0.0-use.local + resolution: "@callstack/react-native-legal-shared@workspace:packages/shared" + dependencies: + "@types/glob": ^8.1.0 + "@types/jest": ^29.5.5 + del-cli: ^5.1.0 + glob: ^7.1.3 + jest: ^29.7.0 + typescript: ^5.8.3 + languageName: unknown + linkType: soft + "@callstack/rspress-theme@npm:^0.0.2": version: 0.0.2 resolution: "@callstack/rspress-theme@npm:0.0.2" @@ -3575,6 +3588,34 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/core@npm:1.4.3" + dependencies: + "@emnapi/wasi-threads": 1.0.2 + tslib: ^2.4.0 + checksum: 1c757d380b3cecec637a2eccfb31b770b995060f695d1e15b29a86e2038909a24152947ef6e4b6586759e6716148ff17f40e51367d1b79c9a3e1b6812537bdf4 + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" + dependencies: + tslib: ^2.4.0 + checksum: ff2074809638ed878e476ece370c6eae7e6257bf029a581bb7a290488d8f2a08c420a65988c7f03bfc6bb689218f0cd995d2f935bd182150b357fc2341142f4f + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.0.2": + version: 1.0.2 + resolution: "@emnapi/wasi-threads@npm:1.0.2" + dependencies: + tslib: ^2.4.0 + checksum: c289cd3d0e26f11de23429a4abc7f99927917c0871d5a22637cbb75170f2b58d3a42e80d76dea89d054e529f79e35cdc953324819a7f990305d0db2897fa5fab + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -4760,6 +4801,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^0.2.10": + version: 0.2.11 + resolution: "@napi-rs/wasm-runtime@npm:0.2.11" + dependencies: + "@emnapi/core": ^1.4.3 + "@emnapi/runtime": ^1.4.3 + "@tybys/wasm-util": ^0.9.0 + checksum: 7c614625784ab467cc7b36b4d7384854891469d0ddce8ca831d28b2abdf8cb3f014d8e8a181c98000719effb46950ab9134b245ab9a8044ad7a7da725b40f858 + languageName: node + linkType: hard + "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3": version: 2.1.8-no-fsevents.3 resolution: "@nicolo-ribaudo/chokidar-2@npm:2.1.8-no-fsevents.3" @@ -5805,6 +5857,15 @@ __metadata: languageName: node linkType: hard +"@tybys/wasm-util@npm:^0.9.0": + version: 0.9.0 + resolution: "@tybys/wasm-util@npm:0.9.0" + dependencies: + tslib: ^2.4.0 + checksum: 8d44c64e64e39c746e45b5dff7b534716f20e1f6e8fc206f8e4c8ac454ec0eb35b65646e446dd80745bc898db37a4eca549a936766d447c2158c9c43d44e7708 + languageName: node + linkType: hard + "@types/acorn@npm:^4.0.0": version: 4.0.6 resolution: "@types/acorn@npm:4.0.6" @@ -5880,6 +5941,16 @@ __metadata: languageName: node linkType: hard +"@types/glob@npm:^8.1.0": + version: 8.1.0 + resolution: "@types/glob@npm:8.1.0" + dependencies: + "@types/minimatch": ^5.1.2 + "@types/node": "*" + checksum: 9101f3a9061e40137190f70626aa0e202369b5ec4012c3fabe6f5d229cce04772db9a94fa5a0eb39655e2e4ad105c38afbb4af56a56c0996a8c7d4fc72350e3d + languageName: node + linkType: hard + "@types/graceful-fs@npm:^4.1.3": version: 4.1.6 resolution: "@types/graceful-fs@npm:4.1.6" @@ -5942,6 +6013,16 @@ __metadata: languageName: node linkType: hard +"@types/jest@npm:^29.5.5": + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" + dependencies: + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: 18dba4623f26661641d757c63da2db45e9524c9be96a29ef713c703a9a53792df9ecee9f7365a0858ddbd6440d98fe6b65ca67895ca5884b73cbc7ffc11f3838 + languageName: node + linkType: hard + "@types/jsdom@npm:^20.0.0": version: 20.0.1 resolution: "@types/jsdom@npm:20.0.1" @@ -5983,6 +6064,13 @@ __metadata: languageName: node linkType: hard +"@types/minimatch@npm:^5.1.2": + version: 5.1.2 + resolution: "@types/minimatch@npm:5.1.2" + checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 + languageName: node + linkType: hard + "@types/minimist@npm:^1.2.0": version: 1.2.2 resolution: "@types/minimist@npm:1.2.2" @@ -5990,6 +6078,13 @@ __metadata: languageName: node linkType: hard +"@types/minimist@npm:^1.2.2": + version: 1.2.5 + resolution: "@types/minimist@npm:1.2.5" + checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 + languageName: node + linkType: hard + "@types/ms@npm:*": version: 2.1.0 resolution: "@types/ms@npm:2.1.0" @@ -6103,6 +6198,15 @@ __metadata: languageName: node linkType: hard +"@types/signale@npm:^1.4.7": + version: 1.4.7 + resolution: "@types/signale@npm:1.4.7" + dependencies: + "@types/node": "*" + checksum: 2e732d9cec0a76f61e5776c120ee5854f67cb42cb70f6b9e0fffc37905cfeaf32cfd670df8ad7c32123ea5046524f1c1fcc41731d7cbbbd7082bef3285f3553e + languageName: node + linkType: hard + "@types/stack-utils@npm:^2.0.0": version: 2.0.1 resolution: "@types/stack-utils@npm:2.0.1" @@ -6405,6 +6509,127 @@ __metadata: languageName: node linkType: hard +"@unrs/resolver-binding-darwin-arm64@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.7.11" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.7.11" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.7.11" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.7.11" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.7.11" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.7.11" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.7.11" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.7.11" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.7.11" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.7.11" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.7.11" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.7.11" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.7.11" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.7.11" + dependencies: + "@napi-rs/wasm-runtime": ^0.2.10 + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.7.11" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.7.11" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.7.11": + version: 1.7.11 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.7.11" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@urql/core@npm:^5.0.0, @urql/core@npm:^5.0.6": version: 5.1.0 resolution: "@urql/core@npm:5.1.0" @@ -6578,6 +6803,16 @@ __metadata: languageName: node linkType: hard +"aggregate-error@npm:^4.0.0": + version: 4.0.1 + resolution: "aggregate-error@npm:4.0.1" + dependencies: + clean-stack: ^4.0.0 + indent-string: ^5.0.0 + checksum: bb3ffdfd13447800fff237c2cba752c59868ee669104bb995dfbbe0b8320e967d679e683dabb640feb32e4882d60258165cde0baafc4cd467cc7d275a13ad6b5 + languageName: node + linkType: hard + "ajv@npm:^6.12.4": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -7780,6 +8015,18 @@ __metadata: languageName: node linkType: hard +"camelcase-keys@npm:^7.0.0": + version: 7.0.2 + resolution: "camelcase-keys@npm:7.0.2" + dependencies: + camelcase: ^6.3.0 + map-obj: ^4.1.0 + quick-lru: ^5.1.1 + type-fest: ^1.2.1 + checksum: b5821cc48dd00e8398a30c5d6547f06837ab44de123f1b3a603d0a03399722b2fc67a485a7e47106eb02ef543c3b50c5ebaabc1242cde4b63a267c3258d2365b + languageName: node + linkType: hard + "camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -7787,7 +8034,7 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^6.2.0": +"camelcase@npm:^6.2.0, camelcase@npm:^6.3.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d @@ -7822,7 +8069,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.2": +"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.3.2, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -8019,6 +8266,15 @@ __metadata: languageName: node linkType: hard +"clean-stack@npm:^4.0.0": + version: 4.2.0 + resolution: "clean-stack@npm:4.2.0" + dependencies: + escape-string-regexp: 5.0.0 + checksum: 373f656a31face5c615c0839213b9b542a0a48057abfb1df66900eab4dc2a5c6097628e4a0b5aa559cdfc4e66f8a14ea47be9681773165a44470ef5fb8ccc172 + languageName: node + linkType: hard + "cli-cursor@npm:^2.1.0": version: 2.1.0 resolution: "cli-cursor@npm:2.1.0" @@ -8197,6 +8453,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^14.0.0": + version: 14.0.0 + resolution: "commander@npm:14.0.0" + checksum: 6e9bdaf2e8e4f512855ffc10579eeae2e84c4a7697a91b1a5f62aab3c9849182207855268dd7c3952ae7a2334312a7138f58e929e4b428aef5bf8af862685c9b + languageName: node + linkType: hard + "commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -8688,6 +8951,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.4.1": + version: 4.4.1 + resolution: "debug@npm:4.4.1" + dependencies: + ms: ^2.1.3 + peerDependenciesMeta: + supports-color: + optional: true + checksum: a43826a01cda685ee4cec00fb2d3322eaa90ccadbef60d9287debc2a886be3e835d9199c80070ede75a409ee57828c4c6cd80e4b154f2843f0dc95a570dc0729 + languageName: node + linkType: hard + "decamelize-keys@npm:^1.1.0": version: 1.1.1 resolution: "decamelize-keys@npm:1.1.1" @@ -8705,6 +8980,13 @@ __metadata: languageName: node linkType: hard +"decamelize@npm:^5.0.0": + version: 5.0.1 + resolution: "decamelize@npm:5.0.1" + checksum: 7c3b1ed4b3e60e7fbc00a35fb248298527c1cdfe603e41dfcf05e6c4a8cb9efbee60630deb677ed428908fb4e74e322966c687a094d1478ddc9c3a74e9dc7140 + languageName: node + linkType: hard + "decimal.js@npm:^10.4.2": version: 10.4.3 resolution: "decimal.js@npm:10.4.3" @@ -8859,6 +9141,19 @@ __metadata: languageName: node linkType: hard +"del-cli@npm:^5.1.0": + version: 5.1.0 + resolution: "del-cli@npm:5.1.0" + dependencies: + del: ^7.1.0 + meow: ^10.1.3 + bin: + del: cli.js + del-cli: cli.js + checksum: 7a8953d3d22716d08080d7344ce9b66fe1608ac4aa32b6106ba825eb986ed2a31ba7826c2f269a2060f013885274c8935628bb6009336adc29a36413dc660741 + languageName: node + linkType: hard + "del@npm:^6.0.0, del@npm:^6.1.1": version: 6.1.1 resolution: "del@npm:6.1.1" @@ -8875,6 +9170,22 @@ __metadata: languageName: node linkType: hard +"del@npm:^7.1.0": + version: 7.1.0 + resolution: "del@npm:7.1.0" + dependencies: + globby: ^13.1.2 + graceful-fs: ^4.2.10 + is-glob: ^4.0.3 + is-path-cwd: ^3.0.0 + is-path-inside: ^4.0.0 + p-map: ^5.5.0 + rimraf: ^3.0.2 + slash: ^4.0.0 + checksum: 93527e78e95125809ff20a112814b00648ed64af204be1a565862698060c9ec8f5c5fe1a4866725acfde9b0da6423f4b7a7642c1d38cd4b05cbeb643a7b089e3 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -9642,6 +9953,13 @@ __metadata: languageName: node linkType: hard +"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -9663,13 +9981,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^5.0.0": - version: 5.0.0 - resolution: "escape-string-regexp@npm:5.0.0" - checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e - languageName: node - linkType: hard - "escodegen@npm:^2.0.0": version: 2.1.0 resolution: "escodegen@npm:2.1.0" @@ -9732,6 +10043,21 @@ __metadata: languageName: node linkType: hard +"eslint-import-context@npm:^0.1.8": + version: 0.1.8 + resolution: "eslint-import-context@npm:0.1.8" + dependencies: + get-tsconfig: ^4.10.1 + stable-hash-x: ^0.1.1 + peerDependencies: + unrs-resolver: ^1.0.0 + peerDependenciesMeta: + unrs-resolver: + optional: true + checksum: c3a2be5320bfaf231a7fd33ffd38e33f3fbbd8a80f4e3220ca8e5c7329f0a0c0441a26a48be7fa91ec9a152871588d80f766829a9202a61b91aa8785f7fa1f51 + languageName: node + linkType: hard + "eslint-import-resolver-node@npm:^0.3.7": version: 0.3.7 resolution: "eslint-import-resolver-node@npm:0.3.7" @@ -9754,6 +10080,30 @@ __metadata: languageName: node linkType: hard +"eslint-import-resolver-typescript@npm:^4.4.3": + version: 4.4.3 + resolution: "eslint-import-resolver-typescript@npm:4.4.3" + dependencies: + debug: ^4.4.1 + eslint-import-context: ^0.1.8 + get-tsconfig: ^4.10.1 + is-bun-module: ^2.0.0 + stable-hash-x: ^0.1.1 + tinyglobby: ^0.2.14 + unrs-resolver: ^1.7.11 + peerDependencies: + eslint: "*" + eslint-plugin-import: "*" + eslint-plugin-import-x: "*" + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + checksum: 7678cc2af2446663b44cbc0fd1c657be1694276963929446229289576b24ed6e89435a76119303099a8cb66299ee146fde3ad3d431f405085762e7e65b01c33c + languageName: node + linkType: hard + "eslint-module-utils@npm:^2.12.0": version: 2.12.0 resolution: "eslint-module-utils@npm:2.12.0" @@ -10799,6 +11149,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.4.4": + version: 6.4.5 + resolution: "fdir@npm:6.4.5" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 14efd2d6617a6f9fb314916ccff64e00bdb96216f26542ec9dfa532ed60a7ebb45463f7009aa215c14071566bf43caeb8ba268ccb52a11e6b51e4aaa8cb58d81 + languageName: node + linkType: hard + "fetch-retry@npm:^4.1.1": version: 4.1.1 resolution: "fetch-retry@npm:4.1.1" @@ -10806,6 +11168,15 @@ __metadata: languageName: node linkType: hard +"figures@npm:^2.0.0": + version: 2.0.0 + resolution: "figures@npm:2.0.0" + dependencies: + escape-string-regexp: ^1.0.5 + checksum: 081beb16ea57d1716f8447c694f637668322398b57017b20929376aaf5def9823b35245b734cdd87e4832dc96e9c6f46274833cada77bfe15e5f980fea1fd21f + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -10859,6 +11230,15 @@ __metadata: languageName: node linkType: hard +"find-up@npm:^2.0.0": + version: 2.1.0 + resolution: "find-up@npm:2.1.0" + dependencies: + locate-path: ^2.0.0 + checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd + languageName: node + linkType: hard + "find-up@npm:^3.0.0": version: 3.0.0 resolution: "find-up@npm:3.0.0" @@ -11326,6 +11706,15 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.10.1": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" + dependencies: + resolve-pkg-maps: ^1.0.0 + checksum: 22925debda6bd0992171a44ee79a22c32642063ba79534372c4d744e0c9154abe2c031659da0fb86bc9e73fc56a3b76b053ea5d24ca3ac3da43d2e6f7d1c3c33 + languageName: node + linkType: hard + "getenv@npm:^1.0.0": version: 1.0.0 resolution: "getenv@npm:1.0.0" @@ -11502,6 +11891,19 @@ __metadata: languageName: node linkType: hard +"globby@npm:^13.1.2": + version: 13.2.2 + resolution: "globby@npm:13.2.2" + dependencies: + dir-glob: ^3.0.1 + fast-glob: ^3.3.0 + ignore: ^5.2.4 + merge2: ^1.4.1 + slash: ^4.0.0 + checksum: f3d84ced58a901b4fcc29c846983108c426631fe47e94872868b65565495f7bee7b3defd68923bd480582771fd4bbe819217803a164a618ad76f1d22f666f41e + languageName: node + linkType: hard + "gopd@npm:^1.0.1": version: 1.0.1 resolution: "gopd@npm:1.0.1" @@ -11518,7 +11920,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -12054,7 +12456,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.3.1": +"ignore@npm:^5.2.4, ignore@npm:^5.3.1": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be @@ -12135,6 +12537,13 @@ __metadata: languageName: node linkType: hard +"indent-string@npm:^5.0.0": + version: 5.0.0 + resolution: "indent-string@npm:5.0.0" + checksum: e466c27b6373440e6d84fbc19e750219ce25865cb82d578e41a6053d727e5520dc5725217d6eb1cc76005a1bb1696a0f106d84ce7ebda3033b963a38583fb3b3 + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -12378,6 +12787,15 @@ __metadata: languageName: node linkType: hard +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" + dependencies: + semver: ^7.7.1 + checksum: e75bd87cb1aaff7c97cf085509669559a713f741a43b4fd5979cb44c5c0c16c05670ce5f23fc22337d1379211fac118c525c5ed73544076ddaf181c1c21ace35 + languageName: node + linkType: hard + "is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" @@ -12656,6 +13074,13 @@ __metadata: languageName: node linkType: hard +"is-path-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "is-path-cwd@npm:3.0.0" + checksum: bc34d13b6a03dfca4a3ab6a8a5ba78ae4b24f4f1db4b2b031d2760c60d0913bd16a4b980dcb4e590adfc906649d5f5132684079a3972bd219da49deebb9adea8 + languageName: node + linkType: hard + "is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": version: 3.0.3 resolution: "is-path-inside@npm:3.0.3" @@ -12663,6 +13088,13 @@ __metadata: languageName: node linkType: hard +"is-path-inside@npm:^4.0.0": + version: 4.0.0 + resolution: "is-path-inside@npm:4.0.0" + checksum: 8810fa11c58e6360b82c3e0d6cd7d9c7d0392d3ac9eb10f980b81f9839f40ac6d1d6d6f05d069db0d227759801228f0b072e1b6c343e4469b065ab5fe0b68fe5 + languageName: node + linkType: hard + "is-plain-obj@npm:^1.1.0": version: 1.1.0 resolution: "is-plain-obj@npm:1.1.0" @@ -13713,7 +14145,7 @@ __metadata: languageName: node linkType: hard -"jest@npm:^29.6.3": +"jest@npm:^29.6.3, jest@npm:^29.7.0": version: 29.7.0 resolution: "jest@npm:29.7.0" dependencies: @@ -14065,6 +14497,23 @@ __metadata: languageName: node linkType: hard +"licenses-aggregator@workspace:packages/licenses-aggregator": + version: 0.0.0-use.local + resolution: "licenses-aggregator@workspace:packages/licenses-aggregator" + dependencies: + "@callstack/react-native-legal-shared": "workspace:*" + "@types/jest": ^29.5.5 + "@types/signale": ^1.4.7 + commander: ^14.0.0 + del-cli: ^5.1.0 + jest: ^29.7.0 + signale: ^1.4.0 + typescript: ^5.8.3 + bin: + license-kit: build/index.js + languageName: unknown + linkType: soft + "lighthouse-logger@npm:^1.0.0": version: 1.4.2 resolution: "lighthouse-logger@npm:1.4.2" @@ -14192,6 +14641,18 @@ __metadata: languageName: node linkType: hard +"load-json-file@npm:^4.0.0": + version: 4.0.0 + resolution: "load-json-file@npm:4.0.0" + dependencies: + graceful-fs: ^4.1.2 + parse-json: ^4.0.0 + pify: ^3.0.0 + strip-bom: ^3.0.0 + checksum: 8f5d6d93ba64a9620445ee9bde4d98b1eac32cf6c8c2d20d44abfa41a6945e7969456ab5f1ca2fb06ee32e206c9769a20eec7002fe290de462e8c884b6b8b356 + languageName: node + linkType: hard + "loader-utils@npm:^2.0.4": version: 2.0.4 resolution: "loader-utils@npm:2.0.4" @@ -14203,6 +14664,16 @@ __metadata: languageName: node linkType: hard +"locate-path@npm:^2.0.0": + version: 2.0.0 + resolution: "locate-path@npm:2.0.0" + dependencies: + p-locate: ^2.0.0 + path-exists: ^3.0.0 + checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 + languageName: node + linkType: hard + "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -14500,7 +14971,7 @@ __metadata: languageName: node linkType: hard -"map-obj@npm:^4.0.0": +"map-obj@npm:^4.0.0, map-obj@npm:^4.1.0": version: 4.3.0 resolution: "map-obj@npm:4.3.0" checksum: fbc554934d1a27a1910e842bc87b177b1a556609dd803747c85ece420692380827c6ae94a95cce4407c054fa0964be3bf8226f7f2cb2e9eeee432c7c1985684e @@ -14806,6 +15277,26 @@ __metadata: languageName: node linkType: hard +"meow@npm:^10.1.3": + version: 10.1.5 + resolution: "meow@npm:10.1.5" + dependencies: + "@types/minimist": ^1.2.2 + camelcase-keys: ^7.0.0 + decamelize: ^5.0.0 + decamelize-keys: ^1.1.0 + hard-rejection: ^2.1.0 + minimist-options: 4.1.0 + normalize-package-data: ^3.0.2 + read-pkg-up: ^8.0.0 + redent: ^4.0.0 + trim-newlines: ^4.0.2 + type-fest: ^1.2.2 + yargs-parser: ^20.2.9 + checksum: dd5f0caa4af18517813547dc66741dcbf52c4c23def5062578d39b11189fd9457aee5c1f2263a5cd6592a465023df8357e8ac876b685b64dbcf545e3f66c23a7 + languageName: node + linkType: hard + "meow@npm:^8.0.0": version: 8.1.2 resolution: "meow@npm:8.1.2" @@ -15575,7 +16066,7 @@ __metadata: languageName: node linkType: hard -"min-indent@npm:^1.0.0": +"min-indent@npm:^1.0.0, min-indent@npm:^1.0.1": version: 1.0.1 resolution: "min-indent@npm:1.0.1" checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 @@ -15815,6 +16306,15 @@ __metadata: languageName: node linkType: hard +"napi-postinstall@npm:^0.2.2": + version: 0.2.4 + resolution: "napi-postinstall@npm:0.2.4" + bin: + napi-postinstall: lib/cli.js + checksum: a0d07495a42953983bbefdf7bae7aa4114b01e231261bd01869568f4a0147347bf5e921dc0d4f618f93e56d54cc6e0d01f49e8da5d1f353ece019cc56157ab4b + languageName: node + linkType: hard + "natural-compare-lite@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare-lite@npm:1.4.0" @@ -15996,7 +16496,7 @@ __metadata: languageName: node linkType: hard -"normalize-package-data@npm:^3.0.0": +"normalize-package-data@npm:^3.0.0, normalize-package-data@npm:^3.0.2": version: 3.0.3 resolution: "normalize-package-data@npm:3.0.3" dependencies: @@ -16447,6 +16947,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^1.1.0": + version: 1.3.0 + resolution: "p-limit@npm:1.3.0" + dependencies: + p-try: ^1.0.0 + checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd + languageName: node + linkType: hard + "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -16465,6 +16974,15 @@ __metadata: languageName: node linkType: hard +"p-locate@npm:^2.0.0": + version: 2.0.0 + resolution: "p-locate@npm:2.0.0" + dependencies: + p-limit: ^1.1.0 + checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 + languageName: node + linkType: hard + "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -16508,6 +17026,22 @@ __metadata: languageName: node linkType: hard +"p-map@npm:^5.5.0": + version: 5.5.0 + resolution: "p-map@npm:5.5.0" + dependencies: + aggregate-error: ^4.0.0 + checksum: 065cb6fca6b78afbd070dd9224ff160dc23eea96e57863c09a0c8ea7ce921043f76854be7ee0abc295cff1ac9adcf700e79a1fbe3b80b625081087be58e7effb + languageName: node + linkType: hard + +"p-try@npm:^1.0.0": + version: 1.0.0 + resolution: "p-try@npm:1.0.0" + checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 + languageName: node + linkType: hard + "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -16765,6 +17299,13 @@ __metadata: languageName: node linkType: hard +"pify@npm:^3.0.0": + version: 3.0.0 + resolution: "pify@npm:3.0.0" + checksum: 6cdcbc3567d5c412450c53261a3f10991665d660961e06605decf4544a61a97a54fefe70a68d5c37080ff9d6f4cf51444c90198d1ba9f9309a6c0d6e9f5c4fde + languageName: node + linkType: hard + "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -16779,6 +17320,16 @@ __metadata: languageName: node linkType: hard +"pkg-conf@npm:^2.1.0": + version: 2.1.0 + resolution: "pkg-conf@npm:2.1.0" + dependencies: + find-up: ^2.0.0 + load-json-file: ^4.0.0 + checksum: b50775157262abd1bfb4d3d948f3fc6c009d10266c6507d4de296af4e2cbb6d2738310784432185886d83144466fbb286b6e8ff0bc23dc5ee7d81810dc6c4788 + languageName: node + linkType: hard + "pkg-dir@npm:^3.0.0": version: 3.0.0 resolution: "pkg-dir@npm:3.0.0" @@ -17094,6 +17645,13 @@ __metadata: languageName: node linkType: hard +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + "range-parser@npm:~1.2.1": version: 1.2.1 resolution: "range-parser@npm:1.2.1" @@ -17268,6 +17826,8 @@ __metadata: version: 0.0.0-use.local resolution: "react-native-legal@workspace:packages/react-native-legal" dependencies: + "@callstack/react-native-legal-shared": "workspace:*" + "@types/glob": ^8.1.0 "@types/xml2js": ^0.4.11 expo: ~52.0.36 expo-module-scripts: ^4.0.0 @@ -17453,6 +18013,17 @@ __metadata: languageName: node linkType: hard +"read-pkg-up@npm:^8.0.0": + version: 8.0.0 + resolution: "read-pkg-up@npm:8.0.0" + dependencies: + find-up: ^5.0.0 + read-pkg: ^6.0.0 + type-fest: ^1.0.1 + checksum: fe4c80401656b40b408884457fffb5a8015c03b1018cfd8e48f8d82a5e9023e24963603aeb2755608d964593e046c15b34d29b07d35af9c7aa478be81805209c + languageName: node + linkType: hard + "read-pkg@npm:^5.2.0": version: 5.2.0 resolution: "read-pkg@npm:5.2.0" @@ -17465,6 +18036,18 @@ __metadata: languageName: node linkType: hard +"read-pkg@npm:^6.0.0": + version: 6.0.0 + resolution: "read-pkg@npm:6.0.0" + dependencies: + "@types/normalize-package-data": ^2.4.0 + normalize-package-data: ^3.0.2 + parse-json: ^5.2.0 + type-fest: ^1.0.1 + checksum: 0cebdff381128e923815c643074a87011070e5fc352bee575d327d6485da3317fab6d802a7b03deeb0be7be8d3ad1640397b3d5d2f044452caf4e8d1736bf94f + languageName: node + linkType: hard + "read-yaml-file@npm:^1.1.0": version: 1.1.0 resolution: "read-yaml-file@npm:1.1.0" @@ -17526,6 +18109,16 @@ __metadata: languageName: node linkType: hard +"redent@npm:^4.0.0": + version: 4.0.0 + resolution: "redent@npm:4.0.0" + dependencies: + indent-string: ^5.0.0 + strip-indent: ^4.0.0 + checksum: 6944e7b1d8f3fd28c2515f5c605b9f7f0ea0f4edddf41890bbbdd4d9ee35abb7540c3b278f03ff827bd278bb6ff4a5bd8692ca406b748c5c1c3ce7355e9fbf8f + languageName: node + linkType: hard + "reduce-configs@npm:^1.1.0": version: 1.1.0 resolution: "reduce-configs@npm:1.1.0" @@ -17884,6 +18477,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 1012afc566b3fdb190a6309cc37ef3b2dcc35dff5fa6683a9d00cd25c3247edfbc4691b91078c97adc82a29b77a2660c30d791d65dab4fc78bfc473f60289977 + languageName: node + linkType: hard + "resolve-workspace-root@npm:^2.0.0": version: 2.0.0 resolution: "resolve-workspace-root@npm:2.0.0" @@ -18131,6 +18731,7 @@ __metadata: "@evilmartians/lefthook": 1.4.3 commitlint: 17.6.6 eslint: ^8.46.0 + eslint-import-resolver-typescript: ^4.4.3 eslint-plugin-flowtype: ^8.0.3 eslint-plugin-prettier: ^5.0.0 prettier: ^3.0.1 @@ -18620,6 +19221,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.1": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621 + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -18904,6 +19514,17 @@ __metadata: languageName: node linkType: hard +"signale@npm:^1.4.0": + version: 1.4.0 + resolution: "signale@npm:1.4.0" + dependencies: + chalk: ^2.3.2 + figures: ^2.0.0 + pkg-conf: ^2.1.0 + checksum: a6a540e054096a1f4cf8b1f21fea62ca3e44a19faa63bd486723b736348609caab1fa59a87f16559de347dde8ae1fdebfc25a8b6723c88ae8239f176ffb0dda5 + languageName: node + linkType: hard + "simple-plist@npm:^1.1.0": version: 1.4.0 resolution: "simple-plist@npm:1.4.0" @@ -18936,6 +19557,13 @@ __metadata: languageName: node linkType: hard +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + "slash@npm:^5.0.0": version: 5.1.0 resolution: "slash@npm:5.1.0" @@ -19136,6 +19764,13 @@ __metadata: languageName: node linkType: hard +"stable-hash-x@npm:^0.1.1": + version: 0.1.1 + resolution: "stable-hash-x@npm:0.1.1" + checksum: b21afd1259b77719fe2a7af6788c22e5d093172e2932954a29a73a426eae4bdc6d6d8f3920cf73a607c5297784d6830d13ec057f4eb9466f8933658d8882a896 + languageName: node + linkType: hard + "stack-generator@npm:^2.0.5": version: 2.0.10 resolution: "stack-generator@npm:2.0.10" @@ -19509,6 +20144,15 @@ __metadata: languageName: node linkType: hard +"strip-indent@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-indent@npm:4.0.0" + dependencies: + min-indent: ^1.0.1 + checksum: 06cbcd93da721c46bc13caeb1c00af93a9b18146a1c95927672d2decab6a25ad83662772417cea9317a2507fb143253ecc23c4415b64f5828cef9b638a744598 + languageName: node + linkType: hard + "strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" @@ -19852,6 +20496,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.14": + version: 0.2.14 + resolution: "tinyglobby@npm:0.2.14" + dependencies: + fdir: ^6.4.4 + picomatch: ^4.0.2 + checksum: 261e986e3f2062dec3a582303bad2ce31b4634b9348648b46828c000d464b012cf474e38f503312367d4117c3f2f18611992738fca684040758bba44c24de522 + languageName: node + linkType: hard + "titleize@npm:^3.0.0": version: 3.0.0 resolution: "titleize@npm:3.0.0" @@ -19956,6 +20610,13 @@ __metadata: languageName: node linkType: hard +"trim-newlines@npm:^4.0.2": + version: 4.1.1 + resolution: "trim-newlines@npm:4.1.1" + checksum: 5b09f8e329e8f33c1111ef26906332ba7ba7248cde3e26fc054bb3d69f2858bf5feedca9559c572ff91f33e52977c28e0d41c387df6a02a633cbb8c2d8238627 + languageName: node + linkType: hard + "trough@npm:^2.0.0": version: 2.2.0 resolution: "trough@npm:2.2.0" @@ -20178,6 +20839,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^1.0.1, type-fest@npm:^1.2.1, type-fest@npm:^1.2.2": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 + languageName: node + linkType: hard + "type-fest@npm:^3.0.0": version: 3.13.0 resolution: "type-fest@npm:3.13.0" @@ -20295,6 +20963,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.8.3": + version: 5.8.3 + resolution: "typescript@npm:5.8.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: cb1d081c889a288b962d3c8ae18d337ad6ee88a8e81ae0103fa1fecbe923737f3ba1dbdb3e6d8b776c72bc73bfa6d8d850c0306eed1a51377d2fccdfd75d92c4 + languageName: node + linkType: hard + "typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin, typescript@patch:typescript@^5.1.3#~builtin": version: 5.1.6 resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin::version=5.1.6&hash=5da071" @@ -20305,6 +20983,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@^5.8.3#~builtin": + version: 5.8.3 + resolution: "typescript@patch:typescript@npm%3A5.8.3#~builtin::version=5.8.3&hash=14eedb" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 1b503525a88ff0ff5952e95870971c4fb2118c17364d60302c21935dedcd6c37e6a0a692f350892bafcef6f4a16d09073fe461158547978d2f16fbe4cb18581c + languageName: node + linkType: hard + "ua-parser-js@npm:^1.0.35": version: 1.0.35 resolution: "ua-parser-js@npm:1.0.35" @@ -20587,6 +21275,67 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.7.11": + version: 1.7.11 + resolution: "unrs-resolver@npm:1.7.11" + dependencies: + "@unrs/resolver-binding-darwin-arm64": 1.7.11 + "@unrs/resolver-binding-darwin-x64": 1.7.11 + "@unrs/resolver-binding-freebsd-x64": 1.7.11 + "@unrs/resolver-binding-linux-arm-gnueabihf": 1.7.11 + "@unrs/resolver-binding-linux-arm-musleabihf": 1.7.11 + "@unrs/resolver-binding-linux-arm64-gnu": 1.7.11 + "@unrs/resolver-binding-linux-arm64-musl": 1.7.11 + "@unrs/resolver-binding-linux-ppc64-gnu": 1.7.11 + "@unrs/resolver-binding-linux-riscv64-gnu": 1.7.11 + "@unrs/resolver-binding-linux-riscv64-musl": 1.7.11 + "@unrs/resolver-binding-linux-s390x-gnu": 1.7.11 + "@unrs/resolver-binding-linux-x64-gnu": 1.7.11 + "@unrs/resolver-binding-linux-x64-musl": 1.7.11 + "@unrs/resolver-binding-wasm32-wasi": 1.7.11 + "@unrs/resolver-binding-win32-arm64-msvc": 1.7.11 + "@unrs/resolver-binding-win32-ia32-msvc": 1.7.11 + "@unrs/resolver-binding-win32-x64-msvc": 1.7.11 + napi-postinstall: ^0.2.2 + dependenciesMeta: + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: e9097c7ea77a079a3605de087f364f4f6b4bcf0552ac52f0af021ce90826c476c6b7ca91979930f485ee375708913fcbf4c9cac883dc14f8182ef8e399a147cb + languageName: node + linkType: hard + "untildify@npm:^4.0.0": version: 4.0.0 resolution: "untildify@npm:4.0.0" @@ -21310,7 +22059,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^20.2.3": +"yargs-parser@npm:^20.2.3, yargs-parser@npm:^20.2.9": version: 20.2.9 resolution: "yargs-parser@npm:20.2.9" checksum: 8bb69015f2b0ff9e17b2c8e6bfe224ab463dd00ca211eece72a4cd8a906224d2703fb8a326d36fdd0e68701e201b2a60ed7cf81ce0fd9b3799f9fe7745977ae3 From 7d17de09a37737655a501b6fb8471ef562ebb51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 15:51:47 +0200 Subject: [PATCH 02/35] feat: rename to license-kit --- CONTRIBUTING.md | 4 +- docs/docs/docs/standalone-cli.mdx | 2 +- package.json | 2 +- .../.editorconfig | 0 packages/license-kit/README.md | 69 ++++++++++ .../package.json | 11 +- packages/license-kit/src/index.ts | 88 +++++++++++++ .../tsconfig.json | 0 packages/licenses-aggregator/README.md | 33 ----- packages/licenses-aggregator/src/index.ts | 18 --- packages/shared/package.json | 4 +- packages/shared/src/common.ts | 26 ++-- yarn.lock | 124 +----------------- 13 files changed, 191 insertions(+), 190 deletions(-) rename packages/{licenses-aggregator => license-kit}/.editorconfig (100%) create mode 100644 packages/license-kit/README.md rename packages/{licenses-aggregator => license-kit}/package.json (89%) create mode 100644 packages/license-kit/src/index.ts rename packages/{licenses-aggregator => license-kit}/tsconfig.json (100%) delete mode 100644 packages/licenses-aggregator/README.md delete mode 100644 packages/licenses-aggregator/src/index.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d750703..2bd7f19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -78,7 +78,7 @@ The codebase of Expo Config Plugin is located in: - `packages/react-native-legal/plugin` - `packages/react-native-legal/app.plugin.js` (the entry point) -- `packages/licenses-aggregator` (logic) +- `packages/license-kit` (logic) To test the changes, build the plugin run (from the root directory, the one with consisting all workspaces): @@ -98,7 +98,7 @@ The codebase of RN CLI plugin is located in: - `packages/react-native-legal/bare-plugin` - `packages/react-native-legal/react-native.config.js` (the entry point) -- `packages/react-native-legal/licenses-aggregator` (logic) +- `packages/react-native-legal/license-kit` (logic) To test the changes, build the plugin run (from the root directory, the one with consisting all workspaces): diff --git a/docs/docs/docs/standalone-cli.mdx b/docs/docs/docs/standalone-cli.mdx index 9d47166..c3892e2 100644 --- a/docs/docs/docs/standalone-cli.mdx +++ b/docs/docs/docs/standalone-cli.mdx @@ -6,7 +6,7 @@ import { PackageManagerTabs, Badge } from '@theme'; To get started, install the package using your preferred package manager: - + ## Programmatic usage (API) diff --git a/package.json b/package.json index 1c3c625..9f39f9b 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ ] }, "scripts": { - "build:library": "yarn workspace @callstack/react-native-legal-shared build && yarn workspace react-native-legal build-plugins && yarn workspace licenses-aggregator build-library && yarn workspace react-native-legal build-library", + "build:library": "yarn workspace @callstack/react-native-legal-shared build && yarn workspace react-native-legal build-plugins && yarn workspace license-kit build-library && yarn workspace react-native-legal build-library", "lint:js": "eslint \"**/*.{js,ts,tsx}\"", "typescript": "yarn build:library && tsc --noEmit -p examples/bare-example/tsconfig.json && tsc --noEmit -p examples/expo-example/tsconfig.json", "lint:android": "./scripts/lint-android.sh", diff --git a/packages/licenses-aggregator/.editorconfig b/packages/license-kit/.editorconfig similarity index 100% rename from packages/licenses-aggregator/.editorconfig rename to packages/license-kit/.editorconfig diff --git a/packages/license-kit/README.md b/packages/license-kit/README.md new file mode 100644 index 0000000..5469bda --- /dev/null +++ b/packages/license-kit/README.md @@ -0,0 +1,69 @@ +# license-kit + +A CLI for managing and analyzing Open Source Software (OSS) licenses in your Node.js projects. This package helps you aggregate license information and ensure compliance with license requirements. + +## Features + +- ๐Ÿ” Scan and aggregate license information from your project dependencies +- โš ๏ธ Detect copyleft licenses that might affect your project +- ๐Ÿ“ Generate license reports +- ๐Ÿ”„ Support for both direct and transitive dependencies + +## Installation + +```bash +npm install license-kit +``` + +## Quick Start + +Run the license check in your project root: + +```bash +npx license-kit +``` + +## Usage + +### Basic Usage + +```bash +# Run with default settings +npx license-kit + +# Check for copyleft licenses +npx license-kit --copyleft + +# Exit on weak copyleft licenses +npx license-kit --error-on-weak +``` + +### Command Line Options + +| Option | Description | Default | +| ----------------- | ----------------------------------------------------------------------------------- | ------------------------- | +| `--copyleft` | Check for copyleft licenses. Exits with error if strong copyleft licenses are found | `false` | +| `--error-on-weak` | Exit with error if weak copyleft licenses are found | `false` | +| `--root` | Path to the root of your project | Current working directory | +| `--help` | Show help message | - | + +## 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) + +## Contributing + +We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on: + +- Development workflow +- Code style +- Pull request process +- Testing requirements + +## License + +MIT ยฉ [Callstack](https://callstack.com) diff --git a/packages/licenses-aggregator/package.json b/packages/license-kit/package.json similarity index 89% rename from packages/licenses-aggregator/package.json rename to packages/license-kit/package.json index 6f9fa6b..0f41e42 100644 --- a/packages/licenses-aggregator/package.json +++ b/packages/license-kit/package.json @@ -1,6 +1,6 @@ { - "name": "licenses-aggregator", - "version": "1.0.0", + "name": "license-kit", + "version": "0.1.0", "description": "Aggregate license notes of OSS libraries used in your Node.js project", "main": "build/index", "module": "build/index", @@ -41,7 +41,7 @@ "repository": { "type": "git", "url": "git+https://github.com/callstackincubator/react-native-legal.git", - "directory": "packages/licenses-aggregator" + "directory": "packages/license-kit" }, "author": "Mateusz Mฤ™drek (https://github.com/mateusz1913)", "license": "MIT", @@ -54,14 +54,13 @@ }, "devDependencies": { "@types/jest": "^29.5.5", - "@types/signale": "^1.4.7", + "@types/minimist": "^1.2.5", "del-cli": "^5.1.0", "jest": "^29.7.0", "typescript": "^5.8.3" }, "dependencies": { "@callstack/react-native-legal-shared": "workspace:*", - "commander": "^14.0.0", - "signale": "^1.4.0" + "minimist": "^1.2.8" } } diff --git a/packages/license-kit/src/index.ts b/packages/license-kit/src/index.ts new file mode 100644 index 0000000..d53f4c4 --- /dev/null +++ b/packages/license-kit/src/index.ts @@ -0,0 +1,88 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; + +import { scanDependencies } from '@callstack/react-native-legal-shared'; +import minimist from 'minimist'; + +const args = minimist(process.argv.slice(2)); + +if (args.help) { + console.log(` +Usage: license-kit [options] + +License Kit: Scan dependencies and check for copyleft licenses. + +Options: + --copyleft: Check for copyleft licenses. Exits with error if strong copyleft licenses are found. + --error-on-weak: Exit with error if weak copyleft licenses are found. + --root: Path to the root of the React Native project. Defaults to the current working directory. + --help: Show this help message. + `); + process.exit(0); +} + +const repoRootPath = args.root ? path.join(process.cwd(), args.root) : process.cwd(); +const packageJsonPath = path.join(repoRootPath, 'package.json'); + +if (!fs.existsSync(packageJsonPath)) { + console.error(`package.json not found at ${packageJsonPath}`); + process.exit(1); +} + +const licenses = scanDependencies(packageJsonPath); + +if (args.copyleft) { + const STRONG_COPYLEFT_LICENSES = [ + 'GPL', + 'GPL-2.0', + 'GPL-3.0', + 'AGPL-3.0', + 'MPL-2.0', + 'EPL-1.0', + 'EPL-2.0', + 'EUPL-1.1', + 'OSL-3.0', + ]; + const WEAK_COPYLEFT_LICENSES = ['LGPL', 'LGPL-2.1', 'LGPL-3.0']; + const strongCopyleftLicenses: string[] = []; + const weakCopyleftLicenses: string[] = []; + + for (const [key, value] of Object.entries(licenses)) { + STRONG_COPYLEFT_LICENSES.find((license) => { + if (value.type === license) { + strongCopyleftLicenses.push(`- ${key}: ${value.type} (${value.file || value.url})`); + return true; + } + }); + + WEAK_COPYLEFT_LICENSES.find((license) => { + if (value.type === license) { + weakCopyleftLicenses.push(`- ${key}: ${value.type} (${value.file || value.url})`); + return true; + } + }); + } + + if (strongCopyleftLicenses.length > 0) { + console.error('โŒ Copyleft licenses found in the following dependencies:'); + strongCopyleftLicenses.forEach((entry) => { + console.error(entry); + }); + process.exit(1); + } + + if (weakCopyleftLicenses.length > 0) { + console.error('โš ๏ธ Weak copyleft licenses found in the following dependencies:'); + weakCopyleftLicenses.forEach((entry) => { + console.error(entry); + }); + if (args['error-on-weak']) { + process.exit(1); + } + } else { + console.log('โœ… No copyleft licenses found'); + } +} else { + console.log(licenses); +} diff --git a/packages/licenses-aggregator/tsconfig.json b/packages/license-kit/tsconfig.json similarity index 100% rename from packages/licenses-aggregator/tsconfig.json rename to packages/license-kit/tsconfig.json diff --git a/packages/licenses-aggregator/README.md b/packages/licenses-aggregator/README.md deleted file mode 100644 index 33e34ff..0000000 --- a/packages/licenses-aggregator/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# licenses-aggregator - -Aggregate license notes of OSS libraries used in your Node.js project - -## Installation - -```sh -npm install licenses-aggregator -``` - -## Usage - - -```js -import { multiply } from 'licenses-aggregator'; - -// ... - -const result = await multiply(3, 7); -``` - - -## Contributing - -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. - -## License - -MIT - ---- - -Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) diff --git a/packages/licenses-aggregator/src/index.ts b/packages/licenses-aggregator/src/index.ts deleted file mode 100644 index fc36a75..0000000 --- a/packages/licenses-aggregator/src/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import process from 'node:process'; - -import { scanDependencies } from '@callstack/react-native-legal-shared'; -import signale from 'signale'; - -// import Command from 'commander'; -const repoRootPath = process.cwd(); - -const packageJsonPath = path.join(repoRootPath, 'package.json'); - -if (!fs.existsSync(packageJsonPath)) { - signale.error(`package.json not found at ${packageJsonPath}`); - process.exit(1); -} - -scanDependencies(packageJsonPath); diff --git a/packages/shared/package.json b/packages/shared/package.json index e2a2a73..c00c8dc 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@callstack/react-native-legal-shared", - "version": "1.0.0", + "version": "0.1.0", "description": "Shared code for all packages", "private": true, "main": "build/index", @@ -39,7 +39,7 @@ "repository": { "type": "git", "url": "git+https://github.com/callstackincubator/react-native-legal.git", - "directory": "packages/licenses-aggregator" + "directory": "packages/license-kit" }, "author": "Mateusz Mฤ™drek (https://github.com/mateusz1913)", "license": "MIT", diff --git a/packages/shared/src/common.ts b/packages/shared/src/common.ts index 8268bb6..274c18d 100644 --- a/packages/shared/src/common.ts +++ b/packages/shared/src/common.ts @@ -120,15 +120,17 @@ function scanPackage( }; } - const dependencies = localPackageJson.dependencies || {}; + const dependencies = localPackageJson.dependencies; const isWorkspacePackage = version.startsWith('workspace:'); if (!isWorkspacePackage) return; - Object.entries(dependencies).forEach(([depName, depVersion]) => { - scanPackage(depName, depVersion as string, processedPackages, result); - }); + if (dependencies) { + Object.entries(dependencies).forEach(([depName, depVersion]) => { + scanPackage(depName, depVersion as string, processedPackages, result); + }); + } } catch (error) { console.warn(`[react-native-legal] could not process package.json for ${packageName}`); } @@ -143,9 +145,11 @@ export function scanDependencies(appPackageJsonPath: string) { const result: Record = {}; const processedPackages = new Set(); - Object.entries(dependencies).forEach(([packageName, version]) => { - scanPackage(packageName, version, processedPackages, result); - }); + if (dependencies) { + Object.entries(dependencies).forEach(([packageName, version]) => { + scanPackage(packageName, version, processedPackages, result); + }); + } return result; } @@ -402,11 +406,13 @@ function normalizeRepositoryUrl(url: string) { .replace('.git', ''); } -function getPackageJsonPath(dependency: string) { +function getPackageJsonPath(dependency: string, root = process.cwd()) { try { - return require.resolve(`${dependency}/package.json`); + return require.resolve(`${dependency}/package.json`, { paths: [root] }); } catch (error) { - return resolvePackageJsonFromEntry(dependency); + const pkgJsonInNodeModules = path.join(root, 'node_modules', dependency, 'package.json'); + + return fs.existsSync(pkgJsonInNodeModules) ? pkgJsonInNodeModules : resolvePackageJsonFromEntry(dependency); } } diff --git a/yarn.lock b/yarn.lock index f4d0034..cff197c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6078,7 +6078,7 @@ __metadata: languageName: node linkType: hard -"@types/minimist@npm:^1.2.2": +"@types/minimist@npm:^1.2.2, @types/minimist@npm:^1.2.5": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 @@ -6198,15 +6198,6 @@ __metadata: languageName: node linkType: hard -"@types/signale@npm:^1.4.7": - version: 1.4.7 - resolution: "@types/signale@npm:1.4.7" - dependencies: - "@types/node": "*" - checksum: 2e732d9cec0a76f61e5776c120ee5854f67cb42cb70f6b9e0fffc37905cfeaf32cfd670df8ad7c32123ea5046524f1c1fcc41731d7cbbbd7082bef3285f3553e - languageName: node - linkType: hard - "@types/stack-utils@npm:^2.0.0": version: 2.0.1 resolution: "@types/stack-utils@npm:2.0.1" @@ -8069,7 +8060,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.3.2, chalk@npm:^2.4.2": +"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -8453,13 +8444,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^14.0.0": - version: 14.0.0 - resolution: "commander@npm:14.0.0" - checksum: 6e9bdaf2e8e4f512855ffc10579eeae2e84c4a7697a91b1a5f62aab3c9849182207855268dd7c3952ae7a2334312a7138f58e929e4b428aef5bf8af862685c9b - languageName: node - linkType: hard - "commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -11168,15 +11152,6 @@ __metadata: languageName: node linkType: hard -"figures@npm:^2.0.0": - version: 2.0.0 - resolution: "figures@npm:2.0.0" - dependencies: - escape-string-regexp: ^1.0.5 - checksum: 081beb16ea57d1716f8447c694f637668322398b57017b20929376aaf5def9823b35245b734cdd87e4832dc96e9c6f46274833cada77bfe15e5f980fea1fd21f - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -11230,15 +11205,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^2.0.0": - version: 2.1.0 - resolution: "find-up@npm:2.1.0" - dependencies: - locate-path: ^2.0.0 - checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd - languageName: node - linkType: hard - "find-up@npm:^3.0.0": version: 3.0.0 resolution: "find-up@npm:3.0.0" @@ -14497,17 +14463,16 @@ __metadata: languageName: node linkType: hard -"licenses-aggregator@workspace:packages/licenses-aggregator": +"license-kit@workspace:packages/license-kit": version: 0.0.0-use.local - resolution: "licenses-aggregator@workspace:packages/licenses-aggregator" + resolution: "license-kit@workspace:packages/license-kit" dependencies: "@callstack/react-native-legal-shared": "workspace:*" "@types/jest": ^29.5.5 - "@types/signale": ^1.4.7 - commander: ^14.0.0 + "@types/minimist": ^1.2.5 del-cli: ^5.1.0 jest: ^29.7.0 - signale: ^1.4.0 + minimist: ^1.2.8 typescript: ^5.8.3 bin: license-kit: build/index.js @@ -14641,18 +14606,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^4.0.0": - version: 4.0.0 - resolution: "load-json-file@npm:4.0.0" - dependencies: - graceful-fs: ^4.1.2 - parse-json: ^4.0.0 - pify: ^3.0.0 - strip-bom: ^3.0.0 - checksum: 8f5d6d93ba64a9620445ee9bde4d98b1eac32cf6c8c2d20d44abfa41a6945e7969456ab5f1ca2fb06ee32e206c9769a20eec7002fe290de462e8c884b6b8b356 - languageName: node - linkType: hard - "loader-utils@npm:^2.0.4": version: 2.0.4 resolution: "loader-utils@npm:2.0.4" @@ -14664,16 +14617,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^2.0.0": - version: 2.0.0 - resolution: "locate-path@npm:2.0.0" - dependencies: - p-locate: ^2.0.0 - path-exists: ^3.0.0 - checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 - languageName: node - linkType: hard - "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -16120,7 +16063,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.6": +"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.8": version: 1.2.8 resolution: "minimist@npm:1.2.8" checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 @@ -16947,15 +16890,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^1.1.0": - version: 1.3.0 - resolution: "p-limit@npm:1.3.0" - dependencies: - p-try: ^1.0.0 - checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd - languageName: node - linkType: hard - "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -16974,15 +16908,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^2.0.0": - version: 2.0.0 - resolution: "p-locate@npm:2.0.0" - dependencies: - p-limit: ^1.1.0 - checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -17035,13 +16960,6 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^1.0.0": - version: 1.0.0 - resolution: "p-try@npm:1.0.0" - checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 - languageName: node - linkType: hard - "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -17299,13 +17217,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^3.0.0": - version: 3.0.0 - resolution: "pify@npm:3.0.0" - checksum: 6cdcbc3567d5c412450c53261a3f10991665d660961e06605decf4544a61a97a54fefe70a68d5c37080ff9d6f4cf51444c90198d1ba9f9309a6c0d6e9f5c4fde - languageName: node - linkType: hard - "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -17320,16 +17231,6 @@ __metadata: languageName: node linkType: hard -"pkg-conf@npm:^2.1.0": - version: 2.1.0 - resolution: "pkg-conf@npm:2.1.0" - dependencies: - find-up: ^2.0.0 - load-json-file: ^4.0.0 - checksum: b50775157262abd1bfb4d3d948f3fc6c009d10266c6507d4de296af4e2cbb6d2738310784432185886d83144466fbb286b6e8ff0bc23dc5ee7d81810dc6c4788 - languageName: node - linkType: hard - "pkg-dir@npm:^3.0.0": version: 3.0.0 resolution: "pkg-dir@npm:3.0.0" @@ -19514,17 +19415,6 @@ __metadata: languageName: node linkType: hard -"signale@npm:^1.4.0": - version: 1.4.0 - resolution: "signale@npm:1.4.0" - dependencies: - chalk: ^2.3.2 - figures: ^2.0.0 - pkg-conf: ^2.1.0 - checksum: a6a540e054096a1f4cf8b1f21fea62ca3e44a19faa63bd486723b736348609caab1fa59a87f16559de347dde8ae1fdebfc25a8b6723c88ae8239f176ffb0dda5 - languageName: node - linkType: hard - "simple-plist@npm:^1.1.0": version: 1.4.0 resolution: "simple-plist@npm:1.4.0" From 73185ac3037de380da486902c850e6ef73f628e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 15:54:40 +0200 Subject: [PATCH 03/35] chore: update bin --- packages/license-kit/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index 0f41e42..92c8397 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -5,9 +5,7 @@ "main": "build/index", "module": "build/index", "types": "build/index.d.ts", - "bin": { - "license-kit": "build/index.js" - }, + "bin": "build/index.js", "exports": { ".": { "source": "./src/index.ts", From 0cd21114bedbda89c9e699b673d29e02a5f4434f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 15:55:27 +0200 Subject: [PATCH 04/35] chore: not private --- packages/shared/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/shared/package.json b/packages/shared/package.json index c00c8dc..3aab0c9 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -2,7 +2,6 @@ "name": "@callstack/react-native-legal-shared", "version": "0.1.0", "description": "Shared code for all packages", - "private": true, "main": "build/index", "module": "build/index", "types": "build/index.d.ts", From 2841e6fc42799b76c8f4f3887211699c60c1f0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 16:04:07 +0200 Subject: [PATCH 05/35] chore: set version instead of workspace --- packages/license-kit/package.json | 2 +- packages/react-native-legal/package.json | 2 +- yarn.lock | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index 92c8397..ee5b9e5 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -58,7 +58,7 @@ "typescript": "^5.8.3" }, "dependencies": { - "@callstack/react-native-legal-shared": "workspace:*", + "@callstack/react-native-legal-shared": "^0.1.0", "minimist": "^1.2.8" } } diff --git a/packages/react-native-legal/package.json b/packages/react-native-legal/package.json index bee1eff..cf52891 100644 --- a/packages/react-native-legal/package.json +++ b/packages/react-native-legal/package.json @@ -57,7 +57,7 @@ "react-native-builder-bob": "0.23.1" }, "dependencies": { - "@callstack/react-native-legal-shared": "workspace:*", + "@callstack/react-native-legal-shared": "^0.1.0", "glob": "^7.1.3", "xcode": "^3.0.1", "xml2js": "^0.6.2" diff --git a/yarn.lock b/yarn.lock index cff197c..cf92e8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3105,7 +3105,7 @@ __metadata: languageName: node linkType: hard -"@callstack/react-native-legal-shared@workspace:*, @callstack/react-native-legal-shared@workspace:packages/shared": +"@callstack/react-native-legal-shared@^0.1.0, @callstack/react-native-legal-shared@workspace:packages/shared": version: 0.0.0-use.local resolution: "@callstack/react-native-legal-shared@workspace:packages/shared" dependencies: @@ -14467,7 +14467,7 @@ __metadata: version: 0.0.0-use.local resolution: "license-kit@workspace:packages/license-kit" dependencies: - "@callstack/react-native-legal-shared": "workspace:*" + "@callstack/react-native-legal-shared": ^0.1.0 "@types/jest": ^29.5.5 "@types/minimist": ^1.2.5 del-cli: ^5.1.0 @@ -17727,7 +17727,7 @@ __metadata: version: 0.0.0-use.local resolution: "react-native-legal@workspace:packages/react-native-legal" dependencies: - "@callstack/react-native-legal-shared": "workspace:*" + "@callstack/react-native-legal-shared": ^0.1.0 "@types/glob": ^8.1.0 "@types/xml2js": ^0.4.11 expo: ~52.0.36 From fa761cbfc930582ce6f891394eabcdf661984800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 16:06:25 +0200 Subject: [PATCH 06/35] chore: changeset --- .changeset/tall-ghosts-stick.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/tall-ghosts-stick.md diff --git a/.changeset/tall-ghosts-stick.md b/.changeset/tall-ghosts-stick.md new file mode 100644 index 0000000..dd346ee --- /dev/null +++ b/.changeset/tall-ghosts-stick.md @@ -0,0 +1,6 @@ +--- +'license-kit': patch +'@callstack/react-native-legal-shared': patch +--- + +feat: setup new packages in monorepo From cdd692311f75ef9978cc774c87c85f6b45513fdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 16:14:51 +0200 Subject: [PATCH 07/35] v0.1.1 --- packages/license-kit/package.json | 4 ++-- packages/react-native-legal/package.json | 2 +- packages/shared/package.json | 2 +- yarn.lock | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index ee5b9e5..6592d88 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -1,6 +1,6 @@ { "name": "license-kit", - "version": "0.1.0", + "version": "0.1.1", "description": "Aggregate license notes of OSS libraries used in your Node.js project", "main": "build/index", "module": "build/index", @@ -58,7 +58,7 @@ "typescript": "^5.8.3" }, "dependencies": { - "@callstack/react-native-legal-shared": "^0.1.0", + "@callstack/react-native-legal-shared": "^0.1.1", "minimist": "^1.2.8" } } diff --git a/packages/react-native-legal/package.json b/packages/react-native-legal/package.json index cf52891..bf75763 100644 --- a/packages/react-native-legal/package.json +++ b/packages/react-native-legal/package.json @@ -57,7 +57,7 @@ "react-native-builder-bob": "0.23.1" }, "dependencies": { - "@callstack/react-native-legal-shared": "^0.1.0", + "@callstack/react-native-legal-shared": "^0.1.1", "glob": "^7.1.3", "xcode": "^3.0.1", "xml2js": "^0.6.2" diff --git a/packages/shared/package.json b/packages/shared/package.json index 3aab0c9..4dfc3df 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@callstack/react-native-legal-shared", - "version": "0.1.0", + "version": "0.1.1", "description": "Shared code for all packages", "main": "build/index", "module": "build/index", diff --git a/yarn.lock b/yarn.lock index cf92e8d..3d70cc8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3105,7 +3105,7 @@ __metadata: languageName: node linkType: hard -"@callstack/react-native-legal-shared@^0.1.0, @callstack/react-native-legal-shared@workspace:packages/shared": +"@callstack/react-native-legal-shared@^0.1.1, @callstack/react-native-legal-shared@workspace:packages/shared": version: 0.0.0-use.local resolution: "@callstack/react-native-legal-shared@workspace:packages/shared" dependencies: @@ -14467,7 +14467,7 @@ __metadata: version: 0.0.0-use.local resolution: "license-kit@workspace:packages/license-kit" dependencies: - "@callstack/react-native-legal-shared": ^0.1.0 + "@callstack/react-native-legal-shared": ^0.1.1 "@types/jest": ^29.5.5 "@types/minimist": ^1.2.5 del-cli: ^5.1.0 @@ -17727,7 +17727,7 @@ __metadata: version: 0.0.0-use.local resolution: "react-native-legal@workspace:packages/react-native-legal" dependencies: - "@callstack/react-native-legal-shared": ^0.1.0 + "@callstack/react-native-legal-shared": ^0.1.1 "@types/glob": ^8.1.0 "@types/xml2js": ^0.4.11 expo: ~52.0.36 From b531ff5a29a57f73cf2c2f9f91cf483044c80a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 16:19:03 +0200 Subject: [PATCH 08/35] fix: set shebang --- packages/license-kit/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/license-kit/src/index.ts b/packages/license-kit/src/index.ts index d53f4c4..2a28dfd 100644 --- a/packages/license-kit/src/index.ts +++ b/packages/license-kit/src/index.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import fs from 'node:fs'; import path from 'node:path'; import process from 'node:process'; From 115c900389e1b71c982a64fc7f4996a254b4d012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 9 Jun 2025 16:20:08 +0200 Subject: [PATCH 09/35] chore: license-kit@0.1.2 --- packages/license-kit/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index 6592d88..9fb21aa 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -1,6 +1,6 @@ { "name": "license-kit", - "version": "0.1.1", + "version": "0.1.2", "description": "Aggregate license notes of OSS libraries used in your Node.js project", "main": "build/index", "module": "build/index", From 51acaf5b1f3e8b224677fc6e96b3b61b6731c1d8 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 17:12:50 +0200 Subject: [PATCH 10/35] refactor!: refactor extracted parts of code to the shared module --- packages/license-kit/LICENSE | 21 ++ packages/license-kit/src/types/Format.ts | 2 + packages/license-kit/src/types/Output.ts | 1 + packages/react-native-legal/LICENSE | 21 ++ .../bare-plugin/src/android/androidCommand.ts | 4 +- .../bare-plugin/src/ios/iosCommand.ts | 4 +- .../plugin-utils/src/android.ts | 4 +- .../plugin/src/android/withAndroidLegal.ts | 4 +- .../plugin/src/ios/withIosLegal.ts | 4 +- packages/shared/LICENSE | 21 ++ packages/shared/src/common.ts | 287 +++++------------- packages/shared/src/index.ts | 2 + .../types/AboutLibrariesLibraryJsonPayload.ts | 9 + .../types/AboutLibrariesLicenseJsonPayload.ts | 6 + .../shared/src/types/AggregatedLicensesObj.ts | 3 + packages/shared/src/types/LicenseObj.ts | 9 + .../shared/src/types/LicensePlistPayload.ts | 7 + packages/shared/src/types/index.ts | 5 + packages/shared/src/utils/index.ts | 3 + packages/shared/src/utils/miscUtils.ts | 38 +++ packages/shared/src/utils/packageUtils.ts | 82 +++++ packages/shared/src/utils/repositoryUtils.ts | 13 + 22 files changed, 335 insertions(+), 215 deletions(-) create mode 100644 packages/license-kit/LICENSE create mode 100644 packages/license-kit/src/types/Format.ts create mode 100644 packages/license-kit/src/types/Output.ts create mode 100644 packages/react-native-legal/LICENSE create mode 100644 packages/shared/LICENSE create mode 100644 packages/shared/src/types/AboutLibrariesLibraryJsonPayload.ts create mode 100644 packages/shared/src/types/AboutLibrariesLicenseJsonPayload.ts create mode 100644 packages/shared/src/types/AggregatedLicensesObj.ts create mode 100644 packages/shared/src/types/LicenseObj.ts create mode 100644 packages/shared/src/types/LicensePlistPayload.ts create mode 100644 packages/shared/src/types/index.ts create mode 100644 packages/shared/src/utils/index.ts create mode 100644 packages/shared/src/utils/miscUtils.ts create mode 100644 packages/shared/src/utils/packageUtils.ts create mode 100644 packages/shared/src/utils/repositoryUtils.ts diff --git a/packages/license-kit/LICENSE b/packages/license-kit/LICENSE new file mode 100644 index 0000000..1c06532 --- /dev/null +++ b/packages/license-kit/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Callstack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/license-kit/src/types/Format.ts b/packages/license-kit/src/types/Format.ts new file mode 100644 index 0000000..831bbb0 --- /dev/null +++ b/packages/license-kit/src/types/Format.ts @@ -0,0 +1,2 @@ +export type Format = 'json' | 'about-json' | 'text' | 'markdown'; +export const validFormats: Format[] = ['json', 'about-json', 'text', 'markdown']; diff --git a/packages/license-kit/src/types/Output.ts b/packages/license-kit/src/types/Output.ts new file mode 100644 index 0000000..09e8e77 --- /dev/null +++ b/packages/license-kit/src/types/Output.ts @@ -0,0 +1 @@ +export type Output = 'stdout' | string; diff --git a/packages/react-native-legal/LICENSE b/packages/react-native-legal/LICENSE new file mode 100644 index 0000000..1c06532 --- /dev/null +++ b/packages/react-native-legal/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Callstack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. 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 f7bbf0c..802284d 100644 --- a/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/android/androidCommand.ts @@ -1,6 +1,6 @@ import path from 'path'; -import { generateAboutLibrariesNPMOutput, scanDependencies } from '@callstack/react-native-legal-shared'; +import { scanDependencies, writeAboutLibrariesNPMOutput } from '@callstack/react-native-legal-shared'; import { addListActivity } from './addListActivity'; import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin'; @@ -15,7 +15,7 @@ import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin'; export function androidCommand(androidProjectPath: string) { const licenses = scanDependencies(path.join(path.resolve(androidProjectPath, '..'), 'package.json')); - generateAboutLibrariesNPMOutput(licenses, androidProjectPath); + writeAboutLibrariesNPMOutput(licenses, androidProjectPath); declareAboutLibrariesPlugin(androidProjectPath); applyAndConfigureAboutLibrariesPlugin(androidProjectPath); 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 f2fb08d..9cf88e7 100644 --- a/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts +++ b/packages/react-native-legal/bare-plugin/src/ios/iosCommand.ts @@ -1,6 +1,6 @@ import path from 'path'; -import { generateLicensePlistNPMOutput, scanDependencies } from '@callstack/react-native-legal-shared'; +import { scanDependencies, writeLicensePlistNPMOutput } from '@callstack/react-native-legal-shared'; import { addSettingsBundle } from './addSettingsBundle'; import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase'; @@ -14,7 +14,7 @@ import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase export function iosCommand(iosProjectPath: string) { const licenses = scanDependencies(path.join(path.resolve(iosProjectPath, '..'), 'package.json')); - generateLicensePlistNPMOutput(licenses, iosProjectPath); + writeLicensePlistNPMOutput(licenses, iosProjectPath); addSettingsBundle(iosProjectPath); registerLicensePlistBuildPhase(iosProjectPath); diff --git a/packages/react-native-legal/plugin-utils/src/android.ts b/packages/react-native-legal/plugin-utils/src/android.ts index ab3edf9..6e33dc5 100644 --- a/packages/react-native-legal/plugin-utils/src/android.ts +++ b/packages/react-native-legal/plugin-utils/src/android.ts @@ -1,4 +1,4 @@ -import { arrayIncludesObject } from '@callstack/react-native-legal-shared'; +import { MiscUtils } from '@callstack/react-native-legal-shared'; /** * Applies Gradle Plugin Portal & AboutLibraries Gradle plugin repositories (if needed) inside root build.gradle @@ -62,7 +62,7 @@ export function applyAndConfigureAboutLibrariesPluginUtil(androidAppBuildGradleC export function addListActivityUtil(activities: T[]): T[] { const listActivity = prepareListActivity(); - if (!arrayIncludesObject(activities, listActivity)) { + if (!MiscUtils.arrayIncludesObject(activities, listActivity)) { activities?.push(listActivity as T); console.log('About Libraries activity - ADDED'); } else { diff --git a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts index b363c9c..6cb94ce 100644 --- a/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts +++ b/packages/react-native-legal/plugin/src/android/withAndroidLegal.ts @@ -2,7 +2,7 @@ import path from 'path'; import { type ConfigPlugin, withAndroidManifest } from 'expo/config-plugins'; -import { generateAboutLibrariesNPMOutput, scanDependencies } from '../../../../shared/build/index'; +import { scanDependencies, writeAboutLibrariesNPMOutput } from '../../../../shared/build/index'; import { addListActivity } from './addListActivity'; import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin'; @@ -18,7 +18,7 @@ export const withAndroidLegal: ConfigPlugin = (config) => { withAndroidManifest(config, async (exportedConfig) => { const licenses = scanDependencies(path.join(exportedConfig.modRequest.projectRoot, 'package.json')); - generateAboutLibrariesNPMOutput(licenses, exportedConfig.modRequest.platformProjectRoot); + writeAboutLibrariesNPMOutput(licenses, exportedConfig.modRequest.platformProjectRoot); return exportedConfig; }); config = declareAboutLibrariesPlugin(config); diff --git a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts index 026b4ec..21a2886 100644 --- a/packages/react-native-legal/plugin/src/ios/withIosLegal.ts +++ b/packages/react-native-legal/plugin/src/ios/withIosLegal.ts @@ -2,7 +2,7 @@ import path from 'path'; import { type ConfigPlugin, withXcodeProject } from 'expo/config-plugins'; -import { generateLicensePlistNPMOutput, scanDependencies } from '../../../../shared/build/index'; +import { scanDependencies, writeLicensePlistNPMOutput } from '../../../../shared/build/index'; import { addSettingsBundle } from './addSettingsBundle'; import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase'; @@ -17,7 +17,7 @@ export const withIosLegal: ConfigPlugin = (config) => { withXcodeProject(config, async (exportedConfig) => { const licenses = scanDependencies(path.join(exportedConfig.modRequest.projectRoot, 'package.json')); - generateLicensePlistNPMOutput(licenses, exportedConfig.modRequest.platformProjectRoot); + writeLicensePlistNPMOutput(licenses, exportedConfig.modRequest.platformProjectRoot); return exportedConfig; }); config = addSettingsBundle(config); diff --git a/packages/shared/LICENSE b/packages/shared/LICENSE new file mode 100644 index 0000000..1c06532 --- /dev/null +++ b/packages/shared/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Callstack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/shared/src/common.ts b/packages/shared/src/common.ts index 274c18d..b258a7c 100644 --- a/packages/shared/src/common.ts +++ b/packages/shared/src/common.ts @@ -1,76 +1,15 @@ -import crypto from 'crypto'; import fs from 'fs'; import path from 'path'; import glob from 'glob'; -type LicenseObj = { - author?: string; - content?: string; - description?: string; - file?: string; - type?: string; - url?: string; - version: string; -}; - -type AboutLibrariesLibraryJsonPayload = { - artifactVersion: string; - description: string; - developers: { name: string; organisationUrl: string }[]; - licenses: string[]; - name: string; - tag: string; - uniqueId: string; -}; - -type AboutLibrariesLicenseJsonPayload = { - content: string; - hash: string; - name: string; - url: string; -}; - -type LicensePlistPayload = { - name: string; - source?: string; - version: string; - body?: string; - file?: string; -}; - -function compareObjects(a: unknown, b: unknown): boolean { - if (a == null || b == null || typeof a !== 'object' || typeof b !== 'object') { - return a === b; - } - - const entriesA = Object.entries(a); - const entriesB = Object.entries(b); - - return ( - entriesA.length === entriesB.length && - entriesA - .map(([keyA, valueA]) => { - const entry = entriesB.find(([keyB]) => keyA === keyB); - - if (!entry) { - return valueA === entry; - } - - const [, valueB] = entry; - - return compareObjects(valueA, valueB); - }) - .reduce((acc, curr) => acc && curr, true) - ); -} - -/** - * Makes a deep-check between array items and provided object, returns true if array has provided object. - */ -export function arrayIncludesObject(array?: unknown[], object?: unknown) { - return array?.map((item) => compareObjects(item, object)).reduce((acc, curr) => acc || curr, false); -} +import type { + AboutLibrariesLibraryJsonPayload, + AboutLibrariesLicenseJsonPayload, + AggregatedLicensesObj, + LicensePlistPayload, +} from './types'; +import { PackageUtils } from './utils'; /** * Scans a single package and its dependencies for license information @@ -79,7 +18,7 @@ function scanPackage( packageName: string, version: string, processedPackages: Set, - result: Record, + result: AggregatedLicensesObj, ) { const packageKey = `${packageName}@${version}`; @@ -91,7 +30,7 @@ function scanPackage( processedPackages.add(packageKey); try { - const localPackageJsonPath = getPackageJsonPath(packageName); + const localPackageJsonPath = PackageUtils.getPackageJsonPath(packageName); if (!localPackageJsonPath) { console.warn(`[react-native-legal] skipping ${packageName} could not find package.json`); @@ -110,12 +49,12 @@ function scanPackage( }); result[packageName] = { - author: parseAuthorField(localPackageJson), + author: PackageUtils.parseAuthorField(localPackageJson), content: licenseFiles?.[0] ? fs.readFileSync(licenseFiles[0], { encoding: 'utf-8' }) : undefined, file: licenseFiles?.[0] ? licenseFiles[0] : undefined, description: localPackageJson.description, - type: parseLicenseField(localPackageJson), - url: parseRepositoryFieldToUrl(localPackageJson), + type: PackageUtils.parseLicenseField(localPackageJson), + url: PackageUtils.parseRepositoryFieldToUrl(localPackageJson), version: localPackageJson.version, }; } @@ -125,8 +64,9 @@ function scanPackage( const isWorkspacePackage = version.startsWith('workspace:'); if (!isWorkspacePackage) return; - + console.log(dependencies); if (dependencies) { + console.log(dependencies); Object.entries(dependencies).forEach(([depName, depVersion]) => { scanPackage(depName, depVersion as string, processedPackages, result); }); @@ -142,7 +82,7 @@ function scanPackage( export function scanDependencies(appPackageJsonPath: string) { const appPackageJson = require(path.resolve(appPackageJsonPath)); const dependencies: Record = appPackageJson.dependencies; - const result: Record = {}; + const result: AggregatedLicensesObj = {}; const processedPackages = new Set(); if (dependencies) { @@ -229,22 +169,16 @@ function toYaml(obj: unknown, indent = 0): string { } /** - * Generates LicensePlist-compatible metadata for NPM dependencies + * Generates LicensePlist-compatible metadata for NPM dependencies as a YAML string. * - * This will take scanned NPM licenses and produce following output inside iOS project's directory: + * To write a file directly, use `writeLicensePlistNPMOutput` function. * - * | - ios - * | ---- myawesomeapp - * | ---- myawesomeapp.xcodeproj - * | ---- myawesomeapp.xcodeworkspace - * | ---- license_plist.yml <--- generated LicensePlist config with NPM dependencies - * | ---- Podfile - * | ---- Podfile.lock + * @see {@link writeLicensePlistNPMOutput} */ -export function generateLicensePlistNPMOutput(licenses: Record, iosProjectPath: string) { +export function generateLicensePlistNPMOutput(licenses: AggregatedLicensesObj, iosProjectPath: string) { const renames: Record = {}; const licenseEntries = Object.entries(licenses).map(([dependency, licenseObj]) => { - const normalizedName = normalizePackageName(dependency); + const normalizedName = PackageUtils.normalizePackageName(dependency); if (dependency !== normalizedName) { renames[normalizedName] = dependency; @@ -273,51 +207,48 @@ export function generateLicensePlistNPMOutput(licenses: Record, androidProjectPath: string) { - const aboutLibrariesConfigDirPath = path.join(androidProjectPath, 'config'); - const aboutLibrariesConfigLibrariesDirPath = path.join(aboutLibrariesConfigDirPath, 'libraries'); - const aboutLibrariesConfigLicensesDirPath = path.join(aboutLibrariesConfigDirPath, 'licenses'); - - if (!fs.existsSync(aboutLibrariesConfigDirPath)) { - fs.mkdirSync(aboutLibrariesConfigDirPath); - } +export function writeLicensePlistNPMOutput(licenses: AggregatedLicensesObj, iosProjectPath: string) { + const yamlContent = generateLicensePlistNPMOutput(licenses, iosProjectPath); - if (!fs.existsSync(aboutLibrariesConfigLibrariesDirPath)) { - fs.mkdirSync(aboutLibrariesConfigLibrariesDirPath); - } - - if (!fs.existsSync(aboutLibrariesConfigLicensesDirPath)) { - fs.mkdirSync(aboutLibrariesConfigLicensesDirPath); - } + fs.writeFileSync(path.join(iosProjectPath, 'license_plist.yml'), yamlContent, { encoding: 'utf-8' }); +} - Object.entries(licenses) +/** + * Generates AboutLibraries-compatible metadata for NPM dependencies + * + * This will take scanned NPM licenses and produce following output inside android project's directory: + */ +export function generateAboutLibrariesNPMOutput(licenses: AggregatedLicensesObj) { + return Object.entries(licenses) .map(([dependency, licenseObj]) => { return { artifactVersion: licenseObj.version, content: licenseObj.content ?? '', description: licenseObj.description ?? '', developers: [{ name: licenseObj.author ?? '', organisationUrl: '' }], - licenses: [prepareAboutLibrariesLicenseField(licenseObj)], + licenses: [PackageUtils.prepareAboutLibrariesLicenseField(licenseObj)], name: dependency, tag: '', type: licenseObj.type, - uniqueId: normalizePackageName(dependency), + uniqueId: PackageUtils.normalizePackageName(dependency), }; }) .map((jsonPayload) => { @@ -336,109 +267,55 @@ export function generateAboutLibrariesNPMOutput(licenses: Record { + const libraryJsonFilePath = path.join(aboutLibrariesConfigLibrariesDirPath, `${normalizedPackageName}.json`); + const licenseJsonFilePath = path.join(aboutLibrariesConfigLicensesDirPath, `${licenseJsonPayload.hash}.json`); - const packageJsonPath = path.join(packageDir, 'package.json'); + fs.writeFileSync(libraryJsonFilePath, JSON.stringify(libraryJsonPayload)); - return fs.existsSync(packageJsonPath) ? packageJsonPath : null; - } catch { - return null; - } -} - -function findPackageRoot(entryPath: string) { - let currentDir = path.dirname(entryPath); - while (currentDir !== path.dirname(currentDir)) { - if (fs.existsSync(path.join(currentDir, 'package.json'))) return currentDir; - currentDir = path.dirname(currentDir); - } -} - -function normalizePackageName(packageName: string): string { - return packageName.replace('/', '_'); + if (!fs.existsSync(licenseJsonFilePath)) { + fs.writeFileSync(licenseJsonFilePath, JSON.stringify(licenseJsonPayload)); + } + }); } diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index d0b9323..d9b4f58 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1 +1,3 @@ export * from './common'; +export * as Types from './types'; +export * from './utils'; diff --git a/packages/shared/src/types/AboutLibrariesLibraryJsonPayload.ts b/packages/shared/src/types/AboutLibrariesLibraryJsonPayload.ts new file mode 100644 index 0000000..4346245 --- /dev/null +++ b/packages/shared/src/types/AboutLibrariesLibraryJsonPayload.ts @@ -0,0 +1,9 @@ +export type AboutLibrariesLibraryJsonPayload = { + artifactVersion: string; + description: string; + developers: { name: string; organisationUrl: string }[]; + licenses: string[]; + name: string; + tag: string; + uniqueId: string; +}; diff --git a/packages/shared/src/types/AboutLibrariesLicenseJsonPayload.ts b/packages/shared/src/types/AboutLibrariesLicenseJsonPayload.ts new file mode 100644 index 0000000..ee6e744 --- /dev/null +++ b/packages/shared/src/types/AboutLibrariesLicenseJsonPayload.ts @@ -0,0 +1,6 @@ +export type AboutLibrariesLicenseJsonPayload = { + content: string; + hash: string; + name: string; + url: string; +}; diff --git a/packages/shared/src/types/AggregatedLicensesObj.ts b/packages/shared/src/types/AggregatedLicensesObj.ts new file mode 100644 index 0000000..61c94e4 --- /dev/null +++ b/packages/shared/src/types/AggregatedLicensesObj.ts @@ -0,0 +1,3 @@ +import type { LicenseObj } from './LicenseObj'; + +export type AggregatedLicensesObj = Record; diff --git a/packages/shared/src/types/LicenseObj.ts b/packages/shared/src/types/LicenseObj.ts new file mode 100644 index 0000000..666237e --- /dev/null +++ b/packages/shared/src/types/LicenseObj.ts @@ -0,0 +1,9 @@ +export type LicenseObj = { + author?: string; + content?: string; + description?: string; + file?: string; + type?: string; + url?: string; + version: string; +}; diff --git a/packages/shared/src/types/LicensePlistPayload.ts b/packages/shared/src/types/LicensePlistPayload.ts new file mode 100644 index 0000000..6af28a3 --- /dev/null +++ b/packages/shared/src/types/LicensePlistPayload.ts @@ -0,0 +1,7 @@ +export type LicensePlistPayload = { + name: string; + source?: string; + version: string; + body?: string; + file?: string; +}; diff --git a/packages/shared/src/types/index.ts b/packages/shared/src/types/index.ts new file mode 100644 index 0000000..7cd95e2 --- /dev/null +++ b/packages/shared/src/types/index.ts @@ -0,0 +1,5 @@ +export * from './LicenseObj'; +export * from './AggregatedLicensesObj'; +export * from './AboutLibrariesLibraryJsonPayload'; +export * from './AboutLibrariesLicenseJsonPayload'; +export * from './LicensePlistPayload'; diff --git a/packages/shared/src/utils/index.ts b/packages/shared/src/utils/index.ts new file mode 100644 index 0000000..cf3dadd --- /dev/null +++ b/packages/shared/src/utils/index.ts @@ -0,0 +1,3 @@ +export * as PackageUtils from './packageUtils'; +export * as MiscUtils from './miscUtils'; +export * as RepositoryUtils from './repositoryUtils'; diff --git a/packages/shared/src/utils/miscUtils.ts b/packages/shared/src/utils/miscUtils.ts new file mode 100644 index 0000000..bccb7b3 --- /dev/null +++ b/packages/shared/src/utils/miscUtils.ts @@ -0,0 +1,38 @@ +import crypto from 'crypto'; + +export function sha512(text: string) { + return crypto.createHash('sha512').update(text).digest('hex'); +} + +export function compareObjects(a: unknown, b: unknown): boolean { + if (a == null || b == null || typeof a !== 'object' || typeof b !== 'object') { + return a === b; + } + + const entriesA = Object.entries(a); + const entriesB = Object.entries(b); + + return ( + entriesA.length === entriesB.length && + entriesA + .map(([keyA, valueA]) => { + const entry = entriesB.find(([keyB]) => keyA === keyB); + + if (!entry) { + return valueA === entry; + } + + const [, valueB] = entry; + + return compareObjects(valueA, valueB); + }) + .reduce((acc, curr) => acc && curr, true) + ); +} + +/** + * Makes a deep-check between array items and provided object, returns true if array has provided object. + */ +export function arrayIncludesObject(array?: unknown[], object?: unknown) { + return array?.map((item) => compareObjects(item, object)).reduce((acc, curr) => acc || curr, false); +} diff --git a/packages/shared/src/utils/packageUtils.ts b/packages/shared/src/utils/packageUtils.ts new file mode 100644 index 0000000..077cd77 --- /dev/null +++ b/packages/shared/src/utils/packageUtils.ts @@ -0,0 +1,82 @@ +import fs from 'fs'; +import path from 'path'; + +import type { LicenseObj } from '../types'; + +import { sha512 } from './miscUtils'; +import { normalizeRepositoryUrl } from './repositoryUtils'; + +export function getPackageJsonPath(dependency: string, root = process.cwd()) { + try { + return require.resolve(`${dependency}/package.json`, { paths: [root] }); + } catch (error) { + const pkgJsonInNodeModules = path.join(root, 'node_modules', dependency, 'package.json'); + + return fs.existsSync(pkgJsonInNodeModules) ? pkgJsonInNodeModules : resolvePackageJsonFromEntry(dependency); + } +} + +export function resolvePackageJsonFromEntry(dependency: string) { + try { + const entryPath = require.resolve(dependency); + const packageDir = findPackageRoot(entryPath); + + if (!packageDir) return null; + + const packageJsonPath = path.join(packageDir, 'package.json'); + + return fs.existsSync(packageJsonPath) ? packageJsonPath : null; + } catch { + return null; + } +} + +export function findPackageRoot(entryPath: string) { + let currentDir = path.dirname(entryPath); + while (currentDir !== path.dirname(currentDir)) { + if (fs.existsSync(path.join(currentDir, 'package.json'))) return currentDir; + currentDir = path.dirname(currentDir); + } +} + +export function normalizePackageName(packageName: string): string { + return packageName.replace('/', '_'); +} + +export function prepareAboutLibrariesLicenseField(license: LicenseObj) { + if (!license.type) { + return ''; + } + + return `${license.type}_${sha512(license.content ?? license.type)}`; +} + +export function parseAuthorField(json: { author: string | { name: string } }) { + if (typeof json.author === 'object' && typeof json.author.name === 'string') { + return json.author.name; + } + + if (typeof json.author === 'string') { + return json.author; + } +} + +export function parseLicenseField(json: { license: string | { type: string } }) { + if (typeof json.license === 'object' && typeof json.license.type === 'string') { + return json.license.type; + } + + if (typeof json.license === 'string') { + return json.license; + } +} + +export function parseRepositoryFieldToUrl(json: { repository: string | { url?: string } }) { + if (typeof json.repository === 'object' && typeof json.repository.url === 'string') { + return normalizeRepositoryUrl(json.repository.url); + } + + if (typeof json.repository === 'string') { + return normalizeRepositoryUrl(json.repository); + } +} diff --git a/packages/shared/src/utils/repositoryUtils.ts b/packages/shared/src/utils/repositoryUtils.ts new file mode 100644 index 0000000..7845d05 --- /dev/null +++ b/packages/shared/src/utils/repositoryUtils.ts @@ -0,0 +1,13 @@ +export function normalizeRepositoryUrl(url: string) { + return url + .replace('git+ssh://git@', 'git://') + .replace('.git', '') + .replace('git+https://github.com', 'https://github.com') + .replace('.git', '') + .replace('git://github.com', 'https://github.com') + .replace('.git', '') + .replace('git@github.com:', 'https://github.com/') + .replace('.git', '') + .replace('github:', 'https://github.com/') + .replace('.git', ''); +} From f419c6d72525e5786ff9f8c90d44ce8208f1d116 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 17:14:18 +0200 Subject: [PATCH 11/35] chore: tsc watch script for development in shared package, updated docs --- CONTRIBUTING.md | 6 ++++++ packages/license-kit/README.md | 4 ++++ packages/shared/package.json | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2bd7f19..df861f6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,12 @@ To get started with the project, run `yarn` in the root directory to install the yarn ``` +All packages in this monorepo depend on the [shared package](packages/shared) (`@callstack/react-native-legal-shared`). This package needs to be rebuilt whenever you make changes to it since other packages consume the exported, built JS code with emitted typings. You can do this by running the following command from the root directory, which will start `tsc` in watch mode: + +```sh +yarn workspace @callstack/react-native-legal-shared dev +``` + While developing, you will have 2 example apps that can be used to test your changes. Any changes you make in your library's JavaScript code will be reflected in the example app without a rebuild. If you change any native code, then you'll need to rebuild the example app. diff --git a/packages/license-kit/README.md b/packages/license-kit/README.md index 5469bda..ca7a3a6 100644 --- a/packages/license-kit/README.md +++ b/packages/license-kit/README.md @@ -64,6 +64,10 @@ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) f - Pull request process - Testing requirements +To build the project, run `yarn build-library`. This will compile the TypeScript code into JavaScript and prepare the package for distribution. + +To run the project in development mode, use `yarn dev`. This will run the TypeScript entrypoint with node directly. + ## License MIT ยฉ [Callstack](https://callstack.com) diff --git a/packages/shared/package.json b/packages/shared/package.json index 4dfc3df..4ea1695 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -26,7 +26,8 @@ "typecheck": "tsc", "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli build", - "build": "tsc -p tsconfig.json" + "build": "tsc -p tsconfig.json", + "dev": "tsc --watch -p tsconfig.json" }, "keywords": [ "nodejs", From b3b6f59202fd191f390e791cd961ad5bcd15cc89 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 17:15:23 +0200 Subject: [PATCH 12/35] feat: print version of the CLI --- packages/license-kit/src/index.ts | 3 +++ packages/license-kit/tsconfig.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/license-kit/src/index.ts b/packages/license-kit/src/index.ts index 2a28dfd..deeb786 100644 --- a/packages/license-kit/src/index.ts +++ b/packages/license-kit/src/index.ts @@ -6,6 +6,8 @@ import process from 'node:process'; import { scanDependencies } from '@callstack/react-native-legal-shared'; import minimist from 'minimist'; +import { version } from '../package.json'; + const args = minimist(process.argv.slice(2)); if (args.help) { @@ -13,6 +15,7 @@ if (args.help) { Usage: license-kit [options] License Kit: Scan dependencies and check for copyleft licenses. +Version: ${version} Options: --copyleft: Check for copyleft licenses. Exits with error if strong copyleft licenses are found. diff --git a/packages/license-kit/tsconfig.json b/packages/license-kit/tsconfig.json index c6832ec..da1b0f4 100644 --- a/packages/license-kit/tsconfig.json +++ b/packages/license-kit/tsconfig.json @@ -10,7 +10,8 @@ "forceConsistentCasingInFileNames": true, "moduleResolution": "node", "outDir": "build", - "rootDir": "src" + "rootDir": "src", + "resolveJsonModule": true }, "include": ["./src"], "exclude": ["**/__mocks__/*", "**/__tests__/*"] From 4b72608dd5d1ab4de50c24d40bfdbbb1900fa1dc Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 17:17:02 +0200 Subject: [PATCH 13/35] feat: output and format flags to export to file in a given format, impl of presentation layer logic --- packages/license-kit/package.json | 3 +- packages/license-kit/src/index.ts | 40 +++++++++++- packages/license-kit/src/serializeReport.ts | 71 +++++++++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 packages/license-kit/src/serializeReport.ts diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index 9fb21aa..e1ef3bc 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -59,6 +59,7 @@ }, "dependencies": { "@callstack/react-native-legal-shared": "^0.1.1", - "minimist": "^1.2.8" + "minimist": "^1.2.8", + "ts-markdown-builder": "^0.4.1" } } diff --git a/packages/license-kit/src/index.ts b/packages/license-kit/src/index.ts index deeb786..272de89 100644 --- a/packages/license-kit/src/index.ts +++ b/packages/license-kit/src/index.ts @@ -8,6 +8,10 @@ import minimist from 'minimist'; import { version } from '../package.json'; +import { serializeReport } from './serializeReport'; +import { type Format, validFormats } from './types/Format'; +import type { Output } from './types/Output'; + const args = minimist(process.argv.slice(2)); if (args.help) { @@ -21,6 +25,8 @@ Options: --copyleft: Check for copyleft licenses. Exits with error if strong copyleft licenses are found. --error-on-weak: Exit with error if weak copyleft licenses are found. --root: Path to the root of the React Native project. Defaults to the current working directory. + --format: Output format (default: 'json'). Supported formats: 'json', 'about-json' (AboutLibraries-compatible), 'text', 'markdown'. + --output: Where to write the output (default: 'stdout'). Supported: 'stdout', . --help: Show this help message. `); process.exit(0); @@ -36,6 +42,21 @@ if (!fs.existsSync(packageJsonPath)) { const licenses = scanDependencies(packageJsonPath); +let format: Format = 'json'; + +if (args.format) { + if (!validFormats.includes(args.format)) { + console.error(`Invalid format: ${args.format}. Supported formats: ${validFormats.join(', ')}`); + process.exit(1); + } + + format = args.format; +} + +let output: Output = args.output ?? 'stdout'; + +const serializedResult = serializeReport({ licenses, format }); + if (args.copyleft) { const STRONG_COPYLEFT_LICENSES = [ 'GPL', @@ -88,5 +109,22 @@ if (args.copyleft) { console.log('โœ… No copyleft licenses found'); } } else { - console.log(licenses); + switch (output) { + case 'stdout': + console.log(serializedResult); + break; + + default: + // output to a file + { + const outputPath = path.resolve(repoRootPath, output); + + fs.mkdirSync(path.dirname(outputPath), { recursive: true }); + fs.writeFileSync(outputPath, serializedResult); + + console.log(`Output written to ${outputPath}`); + } + + break; + } } diff --git a/packages/license-kit/src/serializeReport.ts b/packages/license-kit/src/serializeReport.ts new file mode 100644 index 0000000..016c089 --- /dev/null +++ b/packages/license-kit/src/serializeReport.ts @@ -0,0 +1,71 @@ +import path from 'node:path'; + +import { type Types, generateAboutLibrariesNPMOutput } from '@callstack/react-native-legal-shared'; +import * as md from 'ts-markdown-builder'; + +import type { Format } from './types/Format'; + +export function serializeReport({ + licenses, + format, +}: { + licenses: Types.AggregatedLicensesObj; + format: Format; +}): string { + // convert absolute paths to license files to just filenames (no point in placing those in the file) + for (const packageInfo of Object.values(licenses)) { + if (packageInfo.file) { + packageInfo.file = path.basename(packageInfo.file); + } + } + + switch (format) { + default: + case 'json': + return JSON.stringify(licenses, null, 2); + + case 'about-json': + return JSON.stringify(generateAboutLibrariesNPMOutput(licenses), null, 2); + + case 'text': + return Object.entries(licenses) + .map(([packageName, { version, author, content, description, file, type, url }]) => + [ + `${packageName} (${version})`, + url ? `URL: ${url}` : '', + author ? `Author: ${author}` : '', + content ?? '', + description ? `Description: ${description}` : '', + file ? `File: ${file}` : '', + type ? `Type: ${type}` : '', + '', + '---'.repeat(10), + '', + ].join('\n'), + ) + .join('\n'); + + case 'markdown': + return md + .joinBlocks( + Object.entries(licenses) + .flatMap(([packageName, { version, author, content, description, file, type, url }]) => [ + '\n', + md.heading(packageName, { level: 2 }), + '\n', + `Version: ${version}
\n`, + url ? `URL: ${url}
\n` : '', + author ? `Author: ${author}
\n\n` : '', + content ?? '', + '\n', + description ? `Description: ${description}\n` : '', + file ? `\nFile: ${file}\n` : '', + type ? `Type: ${type}` : '', + '\n', + md.horizontalRule, + ]) + .join('\n'), + ) + .toString(); + } +} From 859f2e32c4b34d82ef4b288a92592219ed9b74ef Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 17:17:34 +0200 Subject: [PATCH 14/35] chore: added dev script to CLI package --- packages/license-kit/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/license-kit/package.json b/packages/license-kit/package.json index e1ef3bc..56cb585 100644 --- a/packages/license-kit/package.json +++ b/packages/license-kit/package.json @@ -27,7 +27,8 @@ "typecheck": "tsc", "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli build", - "build-library": "tsc -p tsconfig.json" + "build-library": "tsc -p tsconfig.json", + "dev": "npx tsx src/index.ts" }, "keywords": [ "nodejs", From 869e1f1a14945032cda99d2aa5b87aa6406baa56 Mon Sep 17 00:00:00 2001 From: artus9033 Date: Thu, 12 Jun 2025 22:49:57 +0200 Subject: [PATCH 15/35] docs: rewrite of docs for all packages --- README.md | 88 ++++++++++++-- docs/components/CustomHomePage.tsx | 114 ++++++++++++++++++ docs/components/PackagesPresentation.tsx | 27 +++++ docs/docs/_meta.json | 17 ++- docs/docs/docs/_meta.json | 34 ++++++ docs/docs/docs/introduction.mdx | 18 ++- docs/docs/docs/programmatic-usage.mdx | 76 ++++++++++++ .../{quick-start.mdx => react-native.mdx} | 28 +++-- docs/docs/docs/standalone-cli.mdx | 55 +++++++-- docs/docs/index.md | 27 ----- docs/docs/index.mdx | 7 ++ docs/rspress.config.ts | 7 +- docs/styles/globalStyles.css | 31 +++++ docs/tsconfig.json | 5 +- packages/license-kit/README.md | 16 +-- packages/license-kit/src/index.ts | 2 +- packages/shared/README.md | 64 ++++++++++ yarn.lock | 16 +++ 18 files changed, 561 insertions(+), 71 deletions(-) create mode 100644 docs/components/CustomHomePage.tsx create mode 100644 docs/components/PackagesPresentation.tsx create mode 100644 docs/docs/docs/_meta.json create mode 100644 docs/docs/docs/programmatic-usage.mdx rename docs/docs/docs/{quick-start.mdx => react-native.mdx} (50%) delete mode 100644 docs/docs/index.md create mode 100644 docs/docs/index.mdx create mode 100644 docs/styles/globalStyles.css create mode 100644 packages/shared/README.md diff --git a/README.md b/README.md index f503dfc..7ce3a9b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,30 @@ # `react-native-legal` -Automagically generate license acknowledgements for your React Native app ๐Ÿš€ - -| Android | iOS | AndroidTV | tvOS | -| - | - | - | - | +- [`react-native-legal`](#react-native-legal) + - [Installation](#installation) + - [React Native](#react-native) + - [Standalone CLI](#standalone-cli) + - [Node.js - API](#nodejs---api) + - [Usage](#usage) + - [I want to generate licenses in my Expo project ](#i-want-to-generate-licenses-in-my-expo-project-) + - [I want to generate licenses reports in my bare RN project ](#i-want-to-generate-licenses-reports-in-my-bare-rn-project-) + - [I want to generate licenses reports in my Node.js project](#i-want-to-generate-licenses-reports-in-my-nodejs-project) + - [I want to customize the presentation of the licenses in my JS/TS project](#i-want-to-customize-the-presentation-of-the-licenses-in-my-jsts-project) + - [Expo](#expo) + - [Contributing](#contributing) + - [Acknowledgements](#acknowledgements) + - [License](#license) + +Automagically generate license acknowledgements for your React Native app and any Node.js project ๐Ÿš€ + +| Android | iOS | AndroidTV | tvOS | +| ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | ![Android example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-expo.gif) | ![iOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/ios-expo.gif) | ![AndroidTV example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-tv.gif) | ![tvOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/tvos.gif) | ## Installation +### React Native + ```sh yarn add react-native-legal ``` @@ -18,11 +35,38 @@ or npm i --save react-native-legal ``` +### Standalone CLI + +```sh +yarn add -D license-kit +``` + +or + +```sh +npm i --save-dev license-kit +``` + +### Node.js - API + +```sh +yarn add @callstack/react-native-legal-shared +``` + +or + +```sh +npm i --save @callstack/react-native-legal-shared +``` + ## Usage -This tool is split into 2 parts: -- a library that lets you display native screen with a list of all dependencies and their licenses -- a [config plugin](https://docs.expo.dev/config-plugins/introduction/?redirected) (for Expo projects) and a [custom community cli plugin](https://github.com/react-native-community/cli/blob/main/docs/plugins.md) (for bare RN projects) +This tool is split into 4 parts: + +- a React Native library that lets you display native screen with a list of all dependencies and their licenses +- an [Expo config plugin](https://docs.expo.dev/config-plugins/introduction/?redirected) (for Expo projects) and a [custom community cli plugin](https://github.com/react-native-community/cli/blob/main/docs/plugins.md) (for bare RN projects) +- a standalone CLI tool that can be used in any Node.js project to generate license metadata +- a shared package that exposes the core functionality of the license management tool, allowing customization of presentation logic in your Node.js scripts ### I want to generate licenses in my Expo project @@ -60,7 +104,7 @@ function MyComponent() { 3. Use [Prebuild](https://docs.expo.dev/workflow/prebuild/) or [EAS](https://docs.expo.dev/eas/) to build the app -### I want to generate licenses in my bare RN project +### I want to generate licenses reports in my bare RN project 1. Invoke the CLI plugin from the root of your RN app @@ -94,6 +138,34 @@ function MyComponent() { } ``` +### I want to generate licenses reports in my Node.js project + +You can use the `license-kit` CLI tool to generate license reports in your Node.js project. Here's how to do it: + +1. Run the CLI tool from the root of your Node.js project: + +```sh +npx license-kit --format markdown --output ./public/licenses.md +``` + +or + +```sh +yarn license-kit --format markdown --output ./public/licenses.md +``` + +This will scan your project's dependencies and generate a license report in the specified format (JSON, Markdown, raw text, or AboutLibraries-compatible JSON metadata). + +For a list of supported flags and the default values, run `npx license-kit --help` or read them documented [in the package's README](./packages/license-kit/README.md#command-line-options). + +### I want to customize the presentation of the licenses in my JS/TS project + +You can use the `@callstack/react-native-legal-shared` package to access the core functionalities of the license management tool. Here's a basic example of how to use it: + +```typescript +import { LicenseKit } from '@callstack/react-native-legal-shared'; +``` + ## Expo - โœ… You can use this library with [Development Builds](https://docs.expo.dev/development/introduction/) by adding `react-native-legal` to your `app.json`/`app.config.js` plugins array. diff --git a/docs/components/CustomHomePage.tsx b/docs/components/CustomHomePage.tsx new file mode 100644 index 0000000..76371ad --- /dev/null +++ b/docs/components/CustomHomePage.tsx @@ -0,0 +1,114 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { usePageData } from '@rspress/runtime'; +// @ts-ignore-next-line +// eslint-disable-next-line import/no-unresolved +import { Button, HomeFeature, HomeFooter, HomeHero } from '@theme'; + +export function CustomHomePage() { + const { + page: { routePath }, + } = usePageData(); + + return ( + <> +
+ React Native Legal` + + '
' + + `License Kit`, + + tagline: + `` + + 'Automagically generate license acknowledgements' + + '\n' + + 'for your React Native app & any Node.js project' + + ``, + actions: [ + { theme: 'brand', text: 'React Native', link: '/docs/react-native' }, + { theme: 'brand', text: 'CLI', link: '/docs/standalone-cli' }, + { theme: 'brand', text: 'API', link: '/docs/programmatic-usage' }, + { theme: 'alt', text: 'GitHub', link: 'https://github.com/callstackincubator/react-native-legal' }, + ], + }, + }} + routePath={routePath} + /> +
+ +
+ { + window.location.pathname = routePath + (routePath.endsWith('/') ? '' : '/') + 'docs/introduction'; + }} + > +
+ + + + {/* eslint-disable-next-line react-native/no-inline-styles */} +
+ +
+ + ); +} diff --git a/docs/components/PackagesPresentation.tsx b/docs/components/PackagesPresentation.tsx new file mode 100644 index 0000000..c2b0aa0 --- /dev/null +++ b/docs/components/PackagesPresentation.tsx @@ -0,0 +1,27 @@ +// @ts-ignore-next-line +// eslint-disable-next-line import/no-unresolved +import { LinkCard } from '@theme'; + +export function PackagesPresentation() { + return ( +
+ + + + + +
+ ); +} diff --git a/docs/docs/_meta.json b/docs/docs/_meta.json index a55ff81..41809dc 100644 --- a/docs/docs/_meta.json +++ b/docs/docs/_meta.json @@ -1,7 +1,18 @@ [ { - "text": "Docs", - "link": "/docs/introduction.html", - "activeMatch": "/docs/" + "text": "Introduction", + "link": "/docs/introduction.html" + }, + { + "text": "React Native", + "link": "/docs/react-native.html" + }, + { + "text": "CLI", + "link": "/docs/standalone-cli.html" + }, + { + "text": "API", + "link": "/docs/programmatic-usage.html" } ] diff --git a/docs/docs/docs/_meta.json b/docs/docs/docs/_meta.json new file mode 100644 index 0000000..a874782 --- /dev/null +++ b/docs/docs/docs/_meta.json @@ -0,0 +1,34 @@ +[ + { + "type": "section-header", + "label": "Quickstart" + }, + { + "type": "custom-link", + "link": "/index", + "label": "Home" + }, + { + "type": "file", + "name": "introduction" + }, + { + "type": "divider" + }, + { + "type": "section-header", + "label": "Packages documentation" + }, + { + "type": "file", + "name": "react-native" + }, + { + "type": "file", + "name": "standalone-cli" + }, + { + "type": "file", + "name": "programmatic-usage" + } +] diff --git a/docs/docs/docs/introduction.mdx b/docs/docs/docs/introduction.mdx index f3f1ab1..be624fa 100644 --- a/docs/docs/docs/introduction.mdx +++ b/docs/docs/docs/introduction.mdx @@ -1,7 +1,17 @@ +--- +sidebar_position: 1 +--- + +import { PackagesPresentation } from '@components/PackagesPresentation'; + # Introduction -React Native Legal helps you acknowledge open-source libraries in your React Native app by automatically generating and displaying license information using native platform tools. This ensures compliance with open-source licenses while maintaining a native user experience. + + +
+ +React Native Legal (`react-native-legal`) helps you acknowledge open-source libraries in your React Native app by automatically generating and displaying license information using native platform tools. This ensures compliance with open-source licenses while maintaining a native user experience. + +We expose the core functionality related to Node.JS dependencies as a standalone CLI tool, `license-kit`, which can be used in any Node.js project, not just React Native apps. This allows you to generate license reports for any Node.js application. -| ![Android example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-expo.gif) | ![iOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/ios-expo.gif) | ![AndroidTV example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-tv.gif) | ![tvOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/tvos.gif) | -| :-: | :-: | :-: | :-: | -| **Android** | **iOS** | **AndroidTV** | **tvOS** | \ No newline at end of file +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. diff --git a/docs/docs/docs/programmatic-usage.mdx b/docs/docs/docs/programmatic-usage.mdx new file mode 100644 index 0000000..d008970 --- /dev/null +++ b/docs/docs/docs/programmatic-usage.mdx @@ -0,0 +1,76 @@ +--- +sidebar_position: 4 +--- + +import { PackageManagerTabs, Badge } from '@theme'; + +# 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: + + + +## Usage + +### Basic Usage + +```typescript +import { + generateAboutLibrariesNPMOutput, + generateLicensePlistNPMOutput, + scanDependencies, +} from '@callstack/react-native-legal-shared'; + +// scan dependencies of a package +const licenses = scanDependencies(packageJsonPath); + +// generate AboutLibraries-compatible JSON metadata +const aboutLibrariesCompatibleReport = generateAboutLibrariesNPMOutput(licenses); + +// generate LicensePlist-compatible metadata +const licensePlistReport = generateLicensePlistNPMOutput(licenses); + +// generate a Markdown report +const markdownString = md + .joinBlocks( + Object.entries(licenses) + .flatMap(([packageName, { version, author, content, description, file, type, url }]) => [ + md.heading(packageName, { level: 2 }), + '\n', + `Version: ${version}
\n`, + url ? `URL: ${url}
\n` : '', + author ? `Author: ${author}
\n\n` : '', + content ?? '', + '\n', + description ? `Description: ${description}\n` : '', + file ? `\nFile: ${file}\n` : '', + type ? `Type: ${type}` : '', + '\n', + md.horizontalRule, + ]) + .join('\n'), + ) + .toString(); +``` + +## 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. +::: diff --git a/docs/docs/docs/quick-start.mdx b/docs/docs/docs/react-native.mdx similarity index 50% rename from docs/docs/docs/quick-start.mdx rename to docs/docs/docs/react-native.mdx index 2ad44cf..4c17d68 100644 --- a/docs/docs/docs/quick-start.mdx +++ b/docs/docs/docs/react-native.mdx @@ -1,6 +1,10 @@ +--- +sidebar_position: 2 +--- + import { PackageManagerTabs, Badge } from '@theme'; -# Quick Start +# React Native Legal ## Installation @@ -8,6 +12,10 @@ To get started, install the package using your preferred package manager: +| ![Android example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-expo.gif) | ![iOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/ios-expo.gif) | ![AndroidTV example](https://github.com/callstackincubator/react-native-legal/raw/main/static/android-tv.gif) | ![tvOS example](https://github.com/callstackincubator/react-native-legal/raw/main/static/tvos.gif) | +| :-----------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------: | +| **Android** | **iOS** | **AndroidTV** | **tvOS** | + ## Setup The setup process varies depending on whether you are using Expo or a bare React Native project. Follow the steps below based on your project type. @@ -62,10 +70,7 @@ function launchNotice() { function MyComponent() { return ( -