diff --git a/.github/workflows/bundle-and-publish-cli.yml b/.github/workflows/bundle-and-publish-cli.yml new file mode 100644 index 00000000000..3c795d57a19 --- /dev/null +++ b/.github/workflows/bundle-and-publish-cli.yml @@ -0,0 +1,91 @@ +name: Bundle and Publish @ui5/cli + +# Reusable workflow: called by release-please.yml (real publish) and github-ci.yml (dry-run). +# The caller controls whether the publish is real or dry-run via the dry_run input. + +on: + workflow_call: + inputs: + dry_run: + description: "Skip actual publish — runs npm publish --dry-run for CI verification" + type: boolean + default: false + npm_tag: + description: "npm dist-tag (e.g. next, latest)" + type: string + default: next + npm_env: + # Setting this shapes the OIDC token subject claim to + # 'repo:UI5/cli:environment:', which must match the trusted + # publisher configuration on npmjs.com. + # Pass 'npmjs:ui5-cli-mono' for a real publish; leave empty for + # dry-run calls (npm publish --dry-run never contacts the registry, + # so no OIDC token is needed — and omitting the environment avoids + # deployment-protection rules that would otherwise block PR builds). + description: > + GitHub Actions environment name for OIDC trusted publishing (e.g. npmjs:ui5-cli-mono). Leave empty for dry-run calls. + type: string + default: "" + +jobs: + bundle-and-publish: + runs-on: ubuntu-24.04 + # Controls the OIDC subject claim: 'repo:UI5/cli:environment:'. + # npm's trusted publisher verifies this claim — empty string means no environment + # (subject becomes 'repo:UI5/cli:ref:refs/heads/...'), used for dry-run only. + # Permissions are not set here: they are inherited from the calling job. + # The real-publish caller (release-please.yml) passes id-token:write; + # the dry-run caller (github-ci.yml) does not, so no OIDC token is minted for dry-runs. + environment: ${{ inputs.npm_env }} + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Node.js LTS + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24.x + + - name: Install dependencies + run: npm ci + + - name: Generate package-lock.json for bundling + working-directory: packages/cli + run: | + set -e + node ../../internal/lockfile-extractor/cli.js ../../ + + - name: Bundle and publish @ui5/cli + env: + NPM_TAG: ${{ inputs.npm_tag }} + DRY_RUN: ${{ inputs.dry_run }} + run: | + set -e + TEMP_CLI_DIR=$(mktemp -d) + + # Copy package (including generated package-lock.json) outside the workspace + cp -r packages/cli/. "$TEMP_CLI_DIR/" + echo "📦 Copied @ui5/cli to temporary directory: $TEMP_CLI_DIR" + + cd "$TEMP_CLI_DIR" + + # Strip devDependencies so npm ci only installs production deps matching the lock file + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); + delete pkg.devDependencies; + fs.writeFileSync('package.json', JSON.stringify(pkg, null, '\t')); + " + + # Install exact versions from generated lock file (no workspace symlinks) + echo "📦 Installing production dependencies from package-lock.json" + npm ci + + if [ "$DRY_RUN" = "true" ]; then + echo "🔍 Dry-run: reporting what would be published (no actual publish)" + npm publish --access public --tag "$NPM_TAG" --dry-run + else + echo "🚀 Publishing @ui5/cli from temporary directory: $TEMP_CLI_DIR" + npm publish --access public --tag "$NPM_TAG" + fi diff --git a/.github/workflows/github-ci.yml b/.github/workflows/github-ci.yml index 4e3ee72fcc5..ac386d39139 100644 --- a/.github/workflows/github-ci.yml +++ b/.github/workflows/github-ci.yml @@ -86,6 +86,13 @@ jobs: npm run build:vitepress npm run build:assets - - name: Check shrinkwrap integrity - working-directory: internal/shrinkwrap-extractor + - name: Run lockfile extractor tests + working-directory: internal/lockfile-extractor run: npm run test + + bundle-cli-dry-run: + name: Verify @ui5/cli bundle (dry-run) + needs: test + uses: ./.github/workflows/bundle-and-publish-cli.yml + with: + dry_run: true diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 816a1895ad5..3cf8582b8a1 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -76,7 +76,7 @@ jobs: environment: npmjs:ui5-cli-mono strategy: # Sequential publishing ensures dependencies exist on NPM before dependents are published - # Order: logger → fs → builder → server → project (CLI handled separately for shrinkwrap generation) + # Order: logger → fs → builder → server → project (CLI handled separately for lockfile generation) max-parallel: 1 matrix: package: [logger, fs, builder, server, project] @@ -98,7 +98,6 @@ jobs: npm publish --access public --tag next publish-cli: - runs-on: ubuntu-24.04 needs: [release-please, publish-packages] # Two paths: # 1. Automatic: release-please created releases and publish-packages succeeded @@ -117,28 +116,9 @@ jobs: ) ) permissions: - id-token: write # Required for trusted publishing via OIDC (https://docs.npmjs.com/trusted-publishers) - # The GitHub Actions Environment configured for the trusted publisher - environment: npmjs:ui5-cli-mono - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - - name: Node.js LTS - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 - with: - node-version: 24.x - - - name: Install dependencies - run: npm ci - - - name: Generate npm-shrinkwrap.json - working-directory: packages/cli - run: | - set -e - node ../../internal/shrinkwrap-extractor/cli.js ../../ - - - name: Publish @ui5/cli package - working-directory: packages/cli - run: | - echo "🚀 Publishing @ui5/cli" - npm publish --access public --tag next + id-token: write # Required for OIDC trusted publishing inside the reusable workflow + uses: ./.github/workflows/bundle-and-publish-cli.yml + with: + dry_run: false + npm_tag: next + npm_env: npmjs:ui5-cli-mono diff --git a/.github/workflows/reuse-compliance.yml b/.github/workflows/reuse-compliance.yml index 47605fa21d8..9ce4113a3dd 100644 --- a/.github/workflows/reuse-compliance.yml +++ b/.github/workflows/reuse-compliance.yml @@ -19,7 +19,7 @@ jobs: matrix: package: - "internal/documentation" - - "internal/shrinkwrap-extractor" + - "internal/lockfile-extractor" - "packages/builder" - "packages/cli" - "packages/fs" diff --git a/.gitignore b/.gitignore index a458c538d1b..92459e130c6 100644 --- a/.gitignore +++ b/.gitignore @@ -72,4 +72,7 @@ internal/documentation/docs/api internal/documentation/tmp # E2E-tests -internal/e2e-tests/tmp \ No newline at end of file +internal/e2e-tests/tmp + +# Generated during bundled CLI publish flow (not committed) +packages/cli/package-lock.json diff --git a/AGENTS.md b/AGENTS.md index 1c30e5ed125..b2d57ee2563 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -63,7 +63,7 @@ npm run coverage --workspace=@ui5/server # Single package Internal packages: - `internal/documentation` — VitePress docs + JSDoc + JSON schema generation -- `internal/shrinkwrap-extractor` — npm shrinkwrap utilities +- `internal/lockfile-extractor` — generates a standalone package-lock.json for @ui5/cli from the monorepo workspace lock file ### Internal package dependencies @@ -93,6 +93,6 @@ Conventional commits enforced via commitlint + husky. Subject must be sentence-c **Types**: `build`, `ci`, `deps`, `docs`, `feat`, `fix`, `perf`, `refactor`, `release`, `revert`, `style`, `test` -**Scopes** are package names: `builder`, `cli`, `documentation`, `fs`, `logger`, `project`, `server`, `shrinkwrap-extractor`. Some types restrict which scopes are valid (e.g., `feat` and `fix` only allow public package scopes). +**Scopes** are package names: `builder`, `cli`, `documentation`, `fs`, `logger`, `project`, `server`, `lockfile-extractor`. Some types restrict which scopes are valid (e.g., `feat` and `fix` only allow public package scopes). Examples: `feat(builder): Add CSS source map support`, `fix(server): Correct middleware ordering` diff --git a/commitlint.config.mjs b/commitlint.config.mjs index e1cd5a89e7d..53d5376c129 100644 --- a/commitlint.config.mjs +++ b/commitlint.config.mjs @@ -10,7 +10,7 @@ const PUBLIC_PACKAGES = [ const INTERNAL_PACKAGES = [ "documentation", - "shrinkwrap-extractor" + "lockfile-extractor" ]; const ALLOWED_TYPE_SCOPE_COMBINATIONS = { diff --git a/docs/Release-Workflow.md b/docs/Release-Workflow.md index 0c9d8adbf70..291f6ee30bd 100644 --- a/docs/Release-Workflow.md +++ b/docs/Release-Workflow.md @@ -37,9 +37,9 @@ The workflow consists of three main jobs: ### 3. `publish-cli` Job - **Trigger**: All other packages have been published -- **Purpose**: Generates `npm-shrinkwrap.json` using `shrinkwrap-extractor` and publishes the CLI package -- **Why separate**: The shrinkwrap must contain published registry versions of workspace packages, not workspace links. This requires all dependencies to be available on npm registry first. -- **How it works**: The `shrinkwrap-extractor` reads the monorepo's `package-lock.json`, extracts production dependencies for `@ui5/cli`, converts workspace references to registry URLs, and generates a valid `npm-shrinkwrap.json` that will be included in the published CLI package. +- **Purpose**: Generates a standalone `package-lock.json` using `lockfile-extractor`, installs outside the workspace, packs with `bundleDependencies`, and publishes the CLI package +- **Why separate**: The lock file must reference published registry versions of workspace packages, not workspace symlinks. This requires all `@ui5/*` dependencies to be available on the npm registry first. +- **How it works**: The `lockfile-extractor` reads the monorepo's `package-lock.json`, extracts production dependencies for `@ui5/cli`, resolves workspace references to registry URLs, and generates a standalone `package-lock.json`. The package is then copied outside the workspace, `npm ci` installs exact versions, and `npm pack` bundles all `node_modules` into the tarball via `bundleDependencies: true`. ## Release Please Configuration diff --git a/internal/shrinkwrap-extractor/LICENSES/Apache-2.0.txt b/internal/lockfile-extractor/LICENSES/Apache-2.0.txt similarity index 100% rename from internal/shrinkwrap-extractor/LICENSES/Apache-2.0.txt rename to internal/lockfile-extractor/LICENSES/Apache-2.0.txt diff --git a/internal/shrinkwrap-extractor/REUSE.toml b/internal/lockfile-extractor/REUSE.toml similarity index 95% rename from internal/shrinkwrap-extractor/REUSE.toml rename to internal/lockfile-extractor/REUSE.toml index 75466b3c066..0e74629c28f 100644 --- a/internal/shrinkwrap-extractor/REUSE.toml +++ b/internal/lockfile-extractor/REUSE.toml @@ -1,7 +1,7 @@ version = 1 -SPDX-PackageName = "ui5-shrinkwrap-extractor" +SPDX-PackageName = "ui5-lockfile-extractor" SPDX-PackageSupplier = "SAP OpenUI5 " -SPDX-PackageDownloadLocation = "https://github.com/UI5/cli/tree/main/packages/shrinkwrap-extractor" +SPDX-PackageDownloadLocation = "https://github.com/UI5/cli/tree/main/internal/lockfile-extractor" SPDX-PackageComment = "The code in this project may include calls to APIs (“API Calls”) of\n SAP or third-party products or services developed outside of this project\n (“External Products”).\n “APIs” means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products,or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project’s code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls." [[annotations]] diff --git a/internal/shrinkwrap-extractor/cli.js b/internal/lockfile-extractor/cli.js similarity index 64% rename from internal/shrinkwrap-extractor/cli.js rename to internal/lockfile-extractor/cli.js index 9604ba697fc..d0783efc0fd 100755 --- a/internal/shrinkwrap-extractor/cli.js +++ b/internal/lockfile-extractor/cli.js @@ -2,7 +2,7 @@ import {readFile, writeFile} from "node:fs/promises"; import {join} from "node:path"; -import convertPackageLockToShrinkwrap from "./lib/convertPackageLockToShrinkwrap.js"; +import extractFromWorkspaceLockfile from "./lib/extractFromWorkspaceLockfile.js"; async function main() { const args = process.argv.slice(2); @@ -10,14 +10,14 @@ async function main() { // Validate arguments if (args.length !== 1) { console.error("Error: Expected exactly 1 argument"); - console.error("Usage: shrinkwrap-extractor "); + console.error("Usage: lockfile-extractor "); process.exit(1); } const [workspaceRootPath] = args; try { - console.log(`Generating shrinkwrap in: ${process.cwd()}`); + console.log(`Generating lockfile in: ${process.cwd()}`); console.log(`Using workspace root: ${workspaceRootPath}`); // Read and parse package.json @@ -33,17 +33,17 @@ async function main() { console.log(`Converting dependencies for package: ${packageName}`); - // Extract into shrinkwrap - const shrinkwrap = await convertPackageLockToShrinkwrap(workspaceRootPath, packageName); + // Extract into lockfile + const lockfile = await extractFromWorkspaceLockfile(workspaceRootPath, packageName); - // Write npm-shrinkwrap.json to current working directory - const outputPath = join(process.cwd(), "npm-shrinkwrap.json"); - const shrinkwrapContent = JSON.stringify(shrinkwrap, null, "\t"); + // Write package-lock.json to current working directory + const outputPath = join(process.cwd(), "package-lock.json"); + const lockfileContent = JSON.stringify(lockfile, null, "\t"); - await writeFile(outputPath, shrinkwrapContent, "utf-8"); + await writeFile(outputPath, lockfileContent, "utf-8"); - console.log(`Successfully generated npm-shrinkwrap.json with ` + - `${Object.keys(shrinkwrap.packages).length - 1} dependencies (excluding root)`); + console.log(`Successfully generated package-lock.json with ` + + `${Object.keys(lockfile.packages).length - 1} dependencies (excluding root)`); console.log(`Output written to: ${outputPath}`); } catch (error) { console.error(`Unexpected error: ${error.message}`); diff --git a/internal/shrinkwrap-extractor/eslint.config.js b/internal/lockfile-extractor/eslint.config.js similarity index 100% rename from internal/shrinkwrap-extractor/eslint.config.js rename to internal/lockfile-extractor/eslint.config.js diff --git a/internal/shrinkwrap-extractor/lib/convertPackageLockToShrinkwrap.js b/internal/lockfile-extractor/lib/extractFromWorkspaceLockfile.js similarity index 78% rename from internal/shrinkwrap-extractor/lib/convertPackageLockToShrinkwrap.js rename to internal/lockfile-extractor/lib/extractFromWorkspaceLockfile.js index 2493f16c5ca..198fee0fdcf 100644 --- a/internal/shrinkwrap-extractor/lib/convertPackageLockToShrinkwrap.js +++ b/internal/lockfile-extractor/lib/extractFromWorkspaceLockfile.js @@ -11,7 +11,7 @@ async function readJson(filePath) { return JSON.parse(jsonString); } -export default async function convertPackageLockToShrinkwrap(workspaceRootDir, targetPackageName) { +export default async function extractFromWorkspaceLockfile(workspaceRootDir, targetPackageName) { const packageLockJson = await readJson(path.join(workspaceRootDir, "package-lock.json")); // Input validation @@ -60,6 +60,7 @@ export default async function convertPackageLockToShrinkwrap(workspaceRootDir, t // Using the keys, extract relevant package-entries from package-lock.json const extractedPackages = Object.create(null); + const extractedPackageNodes = new Map(); for (let [packageLoc, node] of relevantPackageLocations) { let pkg = packageLockJson.packages[packageLoc]; if (pkg.link) { @@ -82,7 +83,24 @@ export default async function convertPackageLockToShrinkwrap(workspaceRootDir, t pkg.resolved = resolved; pkg.integrity = integrity; } + const existingNode = extractedPackageNodes.get(packageLoc); + if (existingNode && + (existingNode.packageName !== node.packageName || existingNode.version !== node.version)) { + const existingIsFromTarget = isDirectDependencyOf(existingNode, targetPackageName); + const currentIsFromTarget = isDirectDependencyOf(node, targetPackageName); + if (existingIsFromTarget !== currentIsFromTarget) { + if (currentIsFromTarget) { + nestPackageBelowDependents(existingNode, extractedPackages[packageLoc], extractedPackages, + relevantPackageLocations, targetPackageName, tree.packageName); + } else { + nestPackageBelowDependents(node, pkg, extractedPackages, relevantPackageLocations, + targetPackageName, tree.packageName); + continue; + } + } + } extractedPackages[packageLoc] = pkg; + extractedPackageNodes.set(packageLoc, node); } // Sort packages by key to ensure consistent order (just like the npm cli does it) @@ -92,8 +110,8 @@ export default async function convertPackageLockToShrinkwrap(workspaceRootDir, t sortedExtractedPackages[key] = extractedPackages[key]; } - // Generate npm-shrinkwrap.json - const shrinkwrap = { + // Generate package-lock.json + const lockfile = { name: targetPackageName, version: cliNode.version, lockfileVersion: 3, @@ -101,7 +119,7 @@ export default async function convertPackageLockToShrinkwrap(workspaceRootDir, t packages: sortedExtractedPackages }; - return shrinkwrap; + return lockfile; } /** @@ -112,9 +130,9 @@ export default async function convertPackageLockToShrinkwrap(workspaceRootDir, t * * @param {string} location - Package location from arborist * @param {object} node - Package node from arborist - * @param {string} targetPackageName - Target package name for shrinkwrap file + * @param {string} targetPackageName - Target package name for lockfile file * @param {string} rootPackageName - Root / workspace package name - * @returns {string} - Normalized location for npm-shrinkwrap.json + * @returns {string} - Normalized location for package-lock.json */ function normalizePackageLocation(location, node, targetPackageName, rootPackageName) { const topPackageName = node.top.packageName; @@ -129,6 +147,22 @@ function normalizePackageLocation(location, node, targetPackageName, rootPackage return location; } +function nestPackageBelowDependents(node, pkg, extractedPackages, relevantPackageLocations, + targetPackageName, rootPackageName) { + for (const edge of node.edgesIn) { + if (edge.dev || !relevantPackageLocations.has(edge.from.location)) { + continue; + } + const parentLoc = normalizePackageLocation(edge.from.location, edge.from, + targetPackageName, rootPackageName); + extractedPackages[`${parentLoc}/node_modules/${edge.name}`] = pkg; + } +} + +function isDirectDependencyOf(node, packageName) { + return Array.from(node.edgesIn).some((edge) => !edge.dev && edge.from.packageName === packageName); +} + function collectDependencies(node, relevantPackageLocations) { if (relevantPackageLocations.has(node.location)) { // Already processed diff --git a/internal/shrinkwrap-extractor/package.json b/internal/lockfile-extractor/package.json similarity index 61% rename from internal/shrinkwrap-extractor/package.json rename to internal/lockfile-extractor/package.json index 15ad209d292..4a85b5c74bd 100644 --- a/internal/shrinkwrap-extractor/package.json +++ b/internal/lockfile-extractor/package.json @@ -1,33 +1,32 @@ { - "name": "@ui5/shrinkwrap-extractor", + "name": "@ui5/lockfile-extractor", "version": "1.0.0", "private": true, - "description": "Convert npm package-lock.json files to npm-shrinkwrap.json format for specific packages in monorepos", + "description": "Extract a standalone package-lock.json for a specific package from a monorepo workspace", "author": { "name": "SAP SE", "email": "openui5@sap.com", "url": "https://www.sap.com" }, "license": "Apache-2.0", - "main": "lib/convertPackageLockToShrinkwrap.js", + "main": "lib/extractFromWorkspaceLockfile.js", "bin": { - "shrinkwrap-extractor": "cli.js" + "lockfile-extractor": "cli.js" }, "repository": { "type": "git", "url": "git+ssh://git@github.com/UI5/cli.git", - "directory": "internal/shrinkwrap-extractor" + "directory": "internal/lockfile-extractor" }, "scripts": { "test": "npm run lint && npm run coverage", - "unit": "node --test test/lib/convertToShrinkwrap.js", - "unit-watch": "node --test --watch test/lib/convertToShrinkwrap.js", - "coverage": "node --test --experimental-test-coverage 'test/lib/convertToShrinkwrap.js'", + "unit": "node --test test/lib/extractFromWorkspaceLockfile.js", + "unit-watch": "node --test --watch test/lib/extractFromWorkspaceLockfile.js", + "coverage": "node --test --experimental-test-coverage 'test/lib/extractFromWorkspaceLockfile.js'", "lint": "eslint ." }, "keywords": [ "npm", - "shrinkwrap", "package-lock", "monorepo", "dependencies" diff --git a/internal/shrinkwrap-extractor/test/expected/package.a/npm-shrinkwrap.json b/internal/lockfile-extractor/test/expected/package.a/package-lock.json similarity index 100% rename from internal/shrinkwrap-extractor/test/expected/package.a/npm-shrinkwrap.json rename to internal/lockfile-extractor/test/expected/package.a/package-lock.json diff --git a/internal/shrinkwrap-extractor/test/expected/package.b/npm-shrinkwrap.json b/internal/lockfile-extractor/test/expected/package.b/package-lock.json similarity index 100% rename from internal/shrinkwrap-extractor/test/expected/package.b/npm-shrinkwrap.json rename to internal/lockfile-extractor/test/expected/package.b/package-lock.json diff --git a/internal/shrinkwrap-extractor/test/fixture/invalid/invalid-packages/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/invalid/invalid-packages/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/invalid/invalid-packages/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/invalid/invalid-packages/package-lock.fixture.json diff --git a/internal/shrinkwrap-extractor/test/fixture/invalid/malformed/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/invalid/malformed/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/invalid/malformed/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/invalid/malformed/package-lock.fixture.json diff --git a/internal/shrinkwrap-extractor/test/fixture/invalid/no-packages/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/invalid/no-packages/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/invalid/no-packages/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/invalid/no-packages/package-lock.fixture.json diff --git a/internal/shrinkwrap-extractor/test/fixture/invalid/v2/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/invalid/v2/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/invalid/v2/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/invalid/v2/package-lock.fixture.json diff --git a/internal/shrinkwrap-extractor/test/fixture/project.a/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/project.a/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/project.a/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/project.a/package-lock.fixture.json diff --git a/internal/shrinkwrap-extractor/test/fixture/project.b/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/project.b/package-lock.fixture.json similarity index 100% rename from internal/shrinkwrap-extractor/test/fixture/project.b/package-lock.fixture.json rename to internal/lockfile-extractor/test/fixture/project.b/package-lock.fixture.json diff --git a/internal/lockfile-extractor/test/fixture/target-root-collision/package-lock.fixture.json b/internal/lockfile-extractor/test/fixture/target-root-collision/package-lock.fixture.json new file mode 100644 index 00000000000..24a83d2352a --- /dev/null +++ b/internal/lockfile-extractor/test/fixture/target-root-collision/package-lock.fixture.json @@ -0,0 +1,46 @@ +{ + "name": "fixture-workspace", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fixture-workspace", + "version": "1.0.0", + "workspaces": [ + "packages/cli" + ] + }, + "node_modules/@ui5/cli": { + "resolved": "packages/cli", + "link": true + }, + "node_modules/boxen": { + "version": "8.0.1", + "dependencies": { + "chalk": "^5.3.0" + } + }, + "node_modules/chalk": { + "version": "5.6.2" + }, + "node_modules/update-notifier": { + "version": "7.3.1", + "dependencies": { + "boxen": "^8.0.1", + "chalk": "^5.3.0" + } + }, + "packages/cli": { + "name": "@ui5/cli", + "version": "1.0.0", + "dependencies": { + "chalk": "^6.0.0", + "update-notifier": "^7.3.1" + } + }, + "packages/cli/node_modules/chalk": { + "version": "6.0.0" + } + } +} \ No newline at end of file diff --git a/internal/shrinkwrap-extractor/test/lib/convertToShrinkwrap.js b/internal/lockfile-extractor/test/lib/extractFromWorkspaceLockfile.js similarity index 63% rename from internal/shrinkwrap-extractor/test/lib/convertToShrinkwrap.js rename to internal/lockfile-extractor/test/lib/extractFromWorkspaceLockfile.js index 2f9ea90d476..05d0ea04f5b 100644 --- a/internal/shrinkwrap-extractor/test/lib/convertToShrinkwrap.js +++ b/internal/lockfile-extractor/test/lib/extractFromWorkspaceLockfile.js @@ -1,6 +1,6 @@ import path from "node:path"; import {readFile, mkdir, writeFile, unlink, symlink} from "node:fs/promises"; -import convertPackageLockToShrinkwrap from "../../lib/convertPackageLockToShrinkwrap.js"; +import extractFromWorkspaceLockfile from "../../lib/extractFromWorkspaceLockfile.js"; import {test} from "node:test"; import assert from "node:assert"; import {mock} from "node:test"; @@ -32,7 +32,7 @@ async function setupFixtureSymlink(fixtureDir) { return symlinkPath; } -test("Convert package-lock.json to shrinkwrap", async (t) => { +test("Convert package-lock.json to lockfile", async (t) => { const __dirname = import.meta.dirname; const cwd = path.join(__dirname, "..", "fixture", "project.a"); @@ -40,24 +40,24 @@ test("Convert package-lock.json to shrinkwrap", async (t) => { t.after(async () => await unlink(symlinkPath).catch(() => {})); const targetPackageName = "@ui5/cli"; - const shrinkwrapJson = await convertPackageLockToShrinkwrap(cwd, targetPackageName); + const lockfileJson = await extractFromWorkspaceLockfile(cwd, targetPackageName); // Basic structure validation - assert.equal(shrinkwrapJson.name, "@ui5/cli"); - assert.equal(shrinkwrapJson.version, "4.0.34"); - assert.equal(shrinkwrapJson.lockfileVersion, 3); - assert.equal(shrinkwrapJson.requires, true); - assert.ok(shrinkwrapJson.packages); + assert.equal(lockfileJson.name, "@ui5/cli"); + assert.equal(lockfileJson.version, "4.0.34"); + assert.equal(lockfileJson.lockfileVersion, 3); + assert.equal(lockfileJson.requires, true); + assert.ok(lockfileJson.packages); // Verify root package entry - const rootPackage = shrinkwrapJson.packages[""]; + const rootPackage = lockfileJson.packages[""]; assert.ok(rootPackage); assert.equal(rootPackage.name, "@ui5/cli"); assert.equal(rootPackage.version, "4.0.34"); assert.ok(rootPackage.dependencies); // Verify workspace packages are resolved to registry-like URLs - const builderDep = shrinkwrapJson.packages["node_modules/@ui5/builder"]; + const builderDep = lockfileJson.packages["node_modules/@ui5/builder"]; assert.ok(builderDep?.resolved, "Builder dependency should have a resolved URL"); assert.equal(builderDep.version, "4.1.1"); assert.ok(builderDep.resolved.startsWith("https://registry.npmjs.org/")); @@ -67,21 +67,21 @@ test("Convert package-lock.json to shrinkwrap", async (t) => { assert.ok(builderDep.integrity, "Builder dependency should have integrity from registry"); // Verify regular dependencies have proper structure - const chalkDep = shrinkwrapJson.packages["node_modules/chalk"]; + const chalkDep = lockfileJson.packages["node_modules/chalk"]; assert.ok(chalkDep); assert.equal(chalkDep.version, "5.6.2"); - const yargsDep = shrinkwrapJson.packages["node_modules/yargs"]; + const yargsDep = lockfileJson.packages["node_modules/yargs"]; assert.ok(yargsDep); assert.equal(yargsDep.version, "17.7.2"); // Verify only production dependencies are included (no devDependencies) - const packagePaths = Object.keys(shrinkwrapJson.packages); + const packagePaths = Object.keys(lockfileJson.packages); assert.ok(packagePaths.includes("node_modules/@ui5/builder")); assert.ok(packagePaths.includes("node_modules/chalk")); assert.ok(packagePaths.includes("node_modules/semver")); assert.ok(!packagePaths.includes("node_modules/@eslint/js")); - console.log(`Generated shrinkwrap with ${packagePaths.length - 1} dependencies`); + console.log(`Generated lockfile with ${packagePaths.length - 1} dependencies`); }); test("Workspace paths should be normalized to node_modules format", async (t) => { @@ -92,10 +92,10 @@ test("Workspace paths should be normalized to node_modules format", async (t) => t.after(async () => await unlink(symlinkPath).catch(() => {})); const targetPackageName = "@ui5/cli"; - const shrinkwrapJson = await convertPackageLockToShrinkwrap(cwd, targetPackageName); + const lockfileJson = await extractFromWorkspaceLockfile(cwd, targetPackageName); // Verify that no package paths contain workspace prefixes like "packages/cli/node_modules/..." - const packagePaths = Object.keys(shrinkwrapJson.packages); + const packagePaths = Object.keys(lockfileJson.packages); for (const packagePath of packagePaths) { // Skip root package (empty string) @@ -112,96 +112,96 @@ test("Workspace paths should be normalized to node_modules format", async (t) => // Specifically check a package that would have been under packages/cli/node_modules in the monorepo // The "@npmcli/config" package is a direct dependency that exists in the CLI's node_modules - const npmCliConfigPackage = shrinkwrapJson.packages["node_modules/@npmcli/config"]; + const npmCliConfigPackage = lockfileJson.packages["node_modules/@npmcli/config"]; assert.ok(npmCliConfigPackage, "The '@npmcli/config' package should be present at normalized path"); assert.equal(npmCliConfigPackage.version, "9.0.0", "@npmcli/config package should have correct version"); console.log(`✓ All ${packagePaths.length - 1} package paths correctly normalized`); }); -test("Compare generated shrinkwrap with expected result", async (t) => { +test("Compare generated lockfile with expected result", async (t) => { // Setup mock to prevent actual npm registry requests const mockRestore = setupPacoteMock(); t.after(() => mockRestore()); const __dirname = import.meta.dirname; - const generatedShrinkwrapPath = path.join(__dirname, "..", "tmp", "package.a", "npm-shrinkwrap.generated.json"); + const generatedLockfilePath = path.join(__dirname, "..", "tmp", "package.a", "package-lock.generated.json"); // Clean any existing generated file - await mkdir(path.dirname(generatedShrinkwrapPath), {recursive: true}); - await unlink(generatedShrinkwrapPath).catch(() => {}); + await mkdir(path.dirname(generatedLockfilePath), {recursive: true}); + await unlink(generatedLockfilePath).catch(() => {}); - // Generate shrinkwrap from fixture + // Generate lockfile from fixture const cwd = path.join(__dirname, "..", "fixture", "project.a"); const symlinkPath = await setupFixtureSymlink(cwd); t.after(async () => await unlink(symlinkPath).catch(() => {})); const targetPackageName = "@ui5/cli"; - const generatedShrinkwrap = await convertPackageLockToShrinkwrap(cwd, targetPackageName); + const generatedLockfile = await extractFromWorkspaceLockfile(cwd, targetPackageName); - // Load expected shrinkwrap - const expectedShrinkwrapPath = path.join(__dirname, "..", "expected", "package.a", "npm-shrinkwrap.json"); - const expectedShrinkwrap = await readJson(expectedShrinkwrapPath); + // Load expected lockfile + const expectedLockfilePath = path.join(__dirname, "..", "expected", "package.a", "package-lock.json"); + const expectedLockfile = await readJson(expectedLockfilePath); - // Write generated shrinkwrap to tmp dir for debugging purposes - await writeFile(generatedShrinkwrapPath, JSON.stringify(generatedShrinkwrap, null, "\t"), "utf-8"); + // Write generated lockfile to tmp dir for debugging purposes + await writeFile(generatedLockfilePath, JSON.stringify(generatedLockfile, null, "\t"), "utf-8"); // Compare top-level properties console.log("=== TOP-LEVEL COMPARISON ==="); - console.log(`Generated name: ${generatedShrinkwrap.name}, Expected name: ${expectedShrinkwrap.name}`); - console.log(`Generated version: ${generatedShrinkwrap.version}, Expected version: ${expectedShrinkwrap.version}`); - console.log(`Generated lockfileVersion: ${generatedShrinkwrap.lockfileVersion},` + - ` Expected lockfileVersion: ${expectedShrinkwrap.lockfileVersion}`); - console.log(`Generated requires: ${generatedShrinkwrap.requires}, ` + - `Expected requires: ${expectedShrinkwrap.requires}`); + console.log(`Generated name: ${generatedLockfile.name}, Expected name: ${expectedLockfile.name}`); + console.log(`Generated version: ${generatedLockfile.version}, Expected version: ${expectedLockfile.version}`); + console.log(`Generated lockfileVersion: ${generatedLockfile.lockfileVersion},` + + ` Expected lockfileVersion: ${expectedLockfile.lockfileVersion}`); + console.log(`Generated requires: ${generatedLockfile.requires}, ` + + `Expected requires: ${expectedLockfile.requires}`); // Compare root package entries console.log("\n=== ROOT PACKAGE COMPARISON ==="); - const generatedRoot = generatedShrinkwrap.packages[""]; - const expectedRoot = expectedShrinkwrap.packages[""]; + const generatedRoot = generatedLockfile.packages[""]; + const expectedRoot = expectedLockfile.packages[""]; console.log(`Generated root keys: ${Object.keys(generatedRoot).sort().join(", ")}`); console.log(`Expected root keys: ${Object.keys(expectedRoot).sort().join(", ")}`); // Compare package counts console.log("\n=== PACKAGE COUNT COMPARISON ==="); - const generatedPackageKeys = Object.keys(generatedShrinkwrap.packages); - const expectedPackageKeys = Object.keys(expectedShrinkwrap.packages); + const generatedPackageKeys = Object.keys(generatedLockfile.packages); + const expectedPackageKeys = Object.keys(expectedLockfile.packages); console.log(`Generated packages: ${generatedPackageKeys.length}`); console.log(`Expected packages: ${expectedPackageKeys.length}`); - assert.deepEqual(generatedShrinkwrap.packages, expectedShrinkwrap.packages, - "Generated shrinkwrap packages should match expected"); + assert.deepEqual(generatedLockfile.packages, expectedLockfile.packages, + "Generated lockfile packages should match expected"); }); -test("Compare generated shrinkwrap with expected result", async (t) => { +test("Compare generated lockfile with expected result", async (t) => { // Setup mock to prevent actual npm registry requests const mockRestore = setupPacoteMock(); t.after(() => mockRestore()); const __dirname = import.meta.dirname; - const generatedShrinkwrapPath = path.join(__dirname, "..", "tmp", "package.b", "npm-shrinkwrap.generated.json"); + const generatedLockfilePath = path.join(__dirname, "..", "tmp", "package.b", "package-lock.generated.json"); // Clean any existing generated file - await mkdir(path.dirname(generatedShrinkwrapPath), {recursive: true}); - await unlink(generatedShrinkwrapPath).catch(() => {}); + await mkdir(path.dirname(generatedLockfilePath), {recursive: true}); + await unlink(generatedLockfilePath).catch(() => {}); - // Generate shrinkwrap from fixture + // Generate lockfile from fixture const cwd = path.join(__dirname, "..", "fixture", "project.b"); const symlinkPath = await setupFixtureSymlink(cwd); t.after(async () => await unlink(symlinkPath).catch(() => {})); const targetPackageName = "@ui5/cli"; - const generatedShrinkwrap = await convertPackageLockToShrinkwrap(cwd, targetPackageName); + const generatedLockfile = await extractFromWorkspaceLockfile(cwd, targetPackageName); - // Load expected shrinkwrap - const expectedShrinkwrapPath = path.join(__dirname, "..", "expected", "package.b", "npm-shrinkwrap.json"); - const expectedShrinkwrap = await readJson(expectedShrinkwrapPath); + // Load expected lockfile + const expectedLockfilePath = path.join(__dirname, "..", "expected", "package.b", "package-lock.json"); + const expectedLockfile = await readJson(expectedLockfilePath); - // Write generated shrinkwrap to tmp dir for debugging purposes - await writeFile(generatedShrinkwrapPath, JSON.stringify(generatedShrinkwrap, null, "\t"), "utf-8"); + // Write generated lockfile to tmp dir for debugging purposes + await writeFile(generatedLockfilePath, JSON.stringify(generatedLockfile, null, "\t"), "utf-8"); - assert.deepEqual(generatedShrinkwrap.packages, expectedShrinkwrap.packages, - "Generated shrinkwrap packages should match expected"); + assert.deepEqual(generatedLockfile.packages, expectedLockfile.packages, + "Generated lockfile packages should match expected"); }); test("Optional peer dependencies with null edges should be excluded", async (t) => { @@ -214,19 +214,34 @@ test("Optional peer dependencies with null edges should be excluded", async (t) const symlinkPath = await setupFixtureSymlink(cwd); t.after(async () => await unlink(symlinkPath).catch(() => {})); - const shrinkwrapJson = await convertPackageLockToShrinkwrap(cwd, "@ui5/cli"); + const lockfileJson = await extractFromWorkspaceLockfile(cwd, "@ui5/cli"); // ws itself must be present (it is a real production dep of @ui5/server) - assert.ok(shrinkwrapJson.packages["node_modules/ws"], - "ws should be included in the shrinkwrap"); + assert.ok(lockfileJson.packages["node_modules/ws"], + "ws should be included in the lockfile"); // Its optional peer deps are not installed and must NOT appear - assert.equal(shrinkwrapJson.packages["node_modules/bufferutil"], undefined, + assert.equal(lockfileJson.packages["node_modules/bufferutil"], undefined, "bufferutil (optional peerDep of ws) must not be included"); - assert.equal(shrinkwrapJson.packages["node_modules/utf-8-validate"], undefined, + assert.equal(lockfileJson.packages["node_modules/utf-8-validate"], undefined, "utf-8-validate (optional peerDep of ws) must not be included"); }); +test("Direct target dependencies take precedence at the root", async (t) => { + const mockRestore = setupPacoteMock(); + t.after(() => mockRestore()); + + const cwd = path.join(import.meta.dirname, "..", "fixture", "target-root-collision"); + const symlinkPath = await setupFixtureSymlink(cwd); + t.after(async () => await unlink(symlinkPath).catch(() => {})); + + const lockfileJson = await extractFromWorkspaceLockfile(cwd, "@ui5/cli"); + + assert.equal(lockfileJson.packages["node_modules/chalk"].version, "6.0.0"); + assert.equal(lockfileJson.packages["node_modules/update-notifier/node_modules/chalk"].version, "5.6.2"); + assert.equal(lockfileJson.packages["node_modules/boxen/node_modules/chalk"].version, "5.6.2"); +}); + // Error handling tests test("Error handling - invalid target package name", async (t) => { const __dirname = import.meta.dirname; @@ -235,17 +250,17 @@ test("Error handling - invalid target package name", async (t) => { t.after(async () => await unlink(symlinkPath).catch(() => {})); await assert.rejects( - convertPackageLockToShrinkwrap(validCwd, null), + extractFromWorkspaceLockfile(validCwd, null), /Invalid target package name: must be a non-empty string/ ); await assert.rejects( - convertPackageLockToShrinkwrap(validCwd, ""), + extractFromWorkspaceLockfile(validCwd, ""), /Invalid target package name: must be a non-empty string/ ); await assert.rejects( - convertPackageLockToShrinkwrap(validCwd, " "), + extractFromWorkspaceLockfile(validCwd, " "), /Invalid target package name: must be a non-empty string/ ); }); @@ -257,14 +272,14 @@ test("Error handling - target package not found", async (t) => { t.after(async () => await unlink(symlinkPath).catch(() => {})); await assert.rejects( - convertPackageLockToShrinkwrap(validCwd, "non-existent-package"), + extractFromWorkspaceLockfile(validCwd, "non-existent-package"), /Target package "non-existent-package" not found in workspace/ ); }); test("Error handling - invalid workspace directory", async (t) => { await assert.rejects( - convertPackageLockToShrinkwrap("/non/existent/path", "@ui5/cli"), + extractFromWorkspaceLockfile("/non/existent/path", "@ui5/cli"), /ENOENT.*package-lock\.json/ ); }); @@ -292,25 +307,25 @@ test("Error handling - invalid package-lock.json files", async (t) => { // Test malformed JSON await assert.rejects( - convertPackageLockToShrinkwrap(malformedDir, "@ui5/cli"), + extractFromWorkspaceLockfile(malformedDir, "@ui5/cli"), /Unexpected token/ ); // Test missing packages field await assert.rejects( - convertPackageLockToShrinkwrap(noPackagesDir, "@ui5/cli"), + extractFromWorkspaceLockfile(noPackagesDir, "@ui5/cli"), /Invalid package-lock\.json: missing packages field/ ); // Test invalid packages field await assert.rejects( - convertPackageLockToShrinkwrap(invalidPackagesDir, "@ui5/cli"), + extractFromWorkspaceLockfile(invalidPackagesDir, "@ui5/cli"), /Invalid package-lock\.json: packages field must be an object/ ); // Test unsupported lockfile version await assert.rejects( - convertPackageLockToShrinkwrap(v2Dir, "@ui5/cli"), + extractFromWorkspaceLockfile(v2Dir, "@ui5/cli"), /Unsupported lockfile version: 2\. Only lockfile version 3 is supported/ ); }); diff --git a/package-lock.json b/package-lock.json index b13e8688602..3be0d0d2dfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,12 +93,12 @@ "npm": ">= 8" } }, - "internal/shrinkwrap-extractor": { - "name": "@ui5/shrinkwrap-extractor", + "internal/lockfile-extractor": { + "name": "@ui5/lockfile-extractor", "version": "1.0.0", "license": "Apache-2.0", "bin": { - "shrinkwrap-extractor": "cli.js" + "lockfile-extractor": "cli.js" }, "devDependencies": { "@npmcli/arborist": "^10.0.2", @@ -111,7 +111,7 @@ "npm": ">= 8" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/agent": { + "internal/lockfile-extractor/node_modules/@npmcli/agent": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-5.0.2.tgz", "integrity": "sha512-EkzGmEsgbQ1rqWkRJe2P0oQHx/ylZozDUNPMXCklLuSFL3GY+QyEfBUjhjCsgGXzh4OGpnHvkboSQgczjP/jJg==", @@ -128,7 +128,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/arborist": { + "internal/lockfile-extractor/node_modules/@npmcli/arborist": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-10.0.2.tgz", "integrity": "sha512-+pkXINqcFRhiSK6EvhzqfiKD43Qsp6KKl8nVijPVjvJZuxl501UPd7uO48wcSAnWIub7prHuxL2fxrFIEg1FzA==", @@ -179,7 +179,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/fs": { + "internal/lockfile-extractor/node_modules/@npmcli/fs": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-6.0.0.tgz", "integrity": "sha512-AheOs4swKka/XLtht6xxJDPezlQ7K2IYQ9Y8lST4JLDjnralnWuMM9AE2CdVcgQJ5omrXhsRzM7F7aYmeZBvKQ==", @@ -192,7 +192,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/git": { + "internal/lockfile-extractor/node_modules/@npmcli/git": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-8.0.0.tgz", "integrity": "sha512-5P1oo+TbxZNAiiMBtpzHA8QyEGh5D69LYLexNWJEDXLdxnAZvT/SLitGJBXxjtCE4ftAcFOS/Tu2185MeIjooQ==", @@ -212,7 +212,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/installed-package-contents": { + "internal/lockfile-extractor/node_modules/@npmcli/installed-package-contents": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-5.0.0.tgz", "integrity": "sha512-6Ay12sf2Lh7U1ifvnS1mq7TZFeh/rXHMXye+kV7jQrANIubaoVcleeh4HdFumxhsRYwm9OaHycB5lYmSwGrcIQ==", @@ -229,7 +229,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/map-workspaces": { + "internal/lockfile-extractor/node_modules/@npmcli/map-workspaces": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-6.0.0.tgz", "integrity": "sha512-Dsex7XBea0BoFRbfALMbNuaNqeI3kbZJxiBMQhFvPUNluv0yEeKMd5FLIXy0NCsOuGMYQkLa+i219CadnoqLbg==", @@ -245,7 +245,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/metavuln-calculator": { + "internal/lockfile-extractor/node_modules/@npmcli/metavuln-calculator": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-10.0.0.tgz", "integrity": "sha512-fC56lpGOae+unrFx6hoiWeWa0/4q+bLhOQTSrB65qcy+Zm34i1OdBcevAQFJJdUB/3i9uXw7PjdrrRjt0KSKXw==", @@ -262,7 +262,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/name-from-folder": { + "internal/lockfile-extractor/node_modules/@npmcli/name-from-folder": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-5.0.0.tgz", "integrity": "sha512-Mua2i5asmOn4sGGAsANS9Guamo7sgUd4BihhQWzlNGz6l/Ki23CzC2oGe4I94r2k/39ImCjDLbyu/rSJr/SXoA==", @@ -272,7 +272,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/node-gyp": { + "internal/lockfile-extractor/node_modules/@npmcli/node-gyp": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-6.0.0.tgz", "integrity": "sha512-MFakpea4pcZNlHSTbMi15HK8RY8zl2UpgDtxhZCWOer+KRN3x7HFIMk/fKpOMgR55L4LIcA2qn8IHeyABhIFtw==", @@ -282,7 +282,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/package-json": { + "internal/lockfile-extractor/node_modules/@npmcli/package-json": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-8.0.0.tgz", "integrity": "sha512-agNZzYQ18MR0wKp3Emg1q5QbcC8CXigYp3Z3CvB0Sax9Ge9aF4cVyyuSG+5SbACSrZUKTvMjVULWiE1RJA38wg==", @@ -301,7 +301,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/promise-spawn": { + "internal/lockfile-extractor/node_modules/@npmcli/promise-spawn": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-10.0.0.tgz", "integrity": "sha512-llZkSzeTsimFx64U+ThT2xQM2uEce8GIQUYvxgbB6ZFvBhV2LP9LeJJb3HT+syG0uCFLsTCHjV9SfC0WNU1vtA==", @@ -314,7 +314,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/redact": { + "internal/lockfile-extractor/node_modules/@npmcli/redact": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-5.0.0.tgz", "integrity": "sha512-3zcN5Q3yEmeyxXBzqB6fXPQFzYa2ROsGFSr69W0ArXIAGJqxl/aFECOVPD2kbkYPm0U/EHxFKgclK3UA9WQg5A==", @@ -324,7 +324,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@npmcli/run-script": { + "internal/lockfile-extractor/node_modules/@npmcli/run-script": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-11.0.0.tgz", "integrity": "sha512-leBRl6F5F0TvWut8m1/aZcMTUHi2vXjKeMJ/Ik1lW7Q7Yy16Dhtkklu+cEqQww1p1NeLnUNzV3+uwpzqRcy9vw==", @@ -341,7 +341,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@sigstore/bundle": { + "internal/lockfile-extractor/node_modules/@sigstore/bundle": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-5.0.0.tgz", "integrity": "sha512-wefjygudENbzbQMks1t5u34EP0fFoD0XvaEP7DOUP/sXKvogzEJYFw5E6pegGyp3onGWzVEYKVa3bNZWyTYX+A==", @@ -354,7 +354,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@sigstore/core": { + "internal/lockfile-extractor/node_modules/@sigstore/core": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-4.0.1.tgz", "integrity": "sha512-9v5hRjujn5NXq8o7XFEUgLyAtdr5Iisb4pzM05u3K61IS5q3hP3luWAndk0RkPPLTUFoTbg7Vb84UQ1ZQeajWQ==", @@ -364,7 +364,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@sigstore/sign": { + "internal/lockfile-extractor/node_modules/@sigstore/sign": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-5.0.0.tgz", "integrity": "sha512-DSFivqz9/i5AkwZ5fq0YdjaJlc4o1WeS2Zffon0kqtChx0vy4W9NOjkEet9bF2vkzOufX72eVH8kZBIGtcBp1w==", @@ -382,7 +382,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@sigstore/tuf": { + "internal/lockfile-extractor/node_modules/@sigstore/tuf": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-5.0.0.tgz", "integrity": "sha512-Zyqg9tcHps3uRAlKHLNmsW4ohsUZAjb9G+31r7lg0ICh/JOcadzmJsIRdjKljlRHpaR0K4aJ2kXXIdywdcdMlA==", @@ -396,7 +396,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@sigstore/verify": { + "internal/lockfile-extractor/node_modules/@sigstore/verify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-4.1.2.tgz", "integrity": "sha512-BfD9eLrz3A/DG58aSgfgZYmIR6V9Yw96QVN/frtu2bEH7ctSTk2TDvHU12un3JsDPBTqTNkqkIkucjxljpOFqQ==", @@ -411,7 +411,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/@tufjs/models": { + "internal/lockfile-extractor/node_modules/@tufjs/models": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-5.0.0.tgz", "integrity": "sha512-U4mVcdFGOi6pt8n38LdWZp67Svn7ppnU1Pj8SGOVaBi1X4gm+G4ztQlLfkoJbKSHfjA6WeaiJp2A4V83AJF6nQ==", @@ -425,7 +425,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/abbrev": { + "internal/lockfile-extractor/node_modules/abbrev": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-5.0.0.tgz", "integrity": "sha512-/XrFJgzQQQHpti1raDJC6m4ws6aNktmjBlhk8Fdlk7LwCEuDoieEJJY9OFHjfiFJFFRM2tK+Ky/IsfbbmlMu1w==", @@ -435,7 +435,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/agent-base": { + "internal/lockfile-extractor/node_modules/agent-base": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz", "integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==", @@ -445,7 +445,7 @@ "node": ">= 20" } }, - "internal/shrinkwrap-extractor/node_modules/bin-links": { + "internal/lockfile-extractor/node_modules/bin-links": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-7.0.0.tgz", "integrity": "sha512-kEk4UROE3064ebMhwmW1qx5BFSBWzmqMe0UwUzn5gsbDyXHmqMUSO8MW6sieYNiRJsindpdnjg4U0D9iXUkIxQ==", @@ -462,7 +462,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/cacache": { + "internal/lockfile-extractor/node_modules/cacache": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/cacache/-/cacache-21.0.1.tgz", "integrity": "sha512-pTwz/uj3Jyp6WXdJ6fWhR+7LVxVs6RyroQSn7KJwHsSxXuyGSp0pcMVcwSwTpCFq1X2YG8QBe0W+vN+cr0SwzA==", @@ -484,7 +484,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/cmd-shim": { + "internal/lockfile-extractor/node_modules/cmd-shim": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-9.0.2.tgz", "integrity": "sha512-xVHoI+wNrM4tDB9iC1idf/8D0tYnVimlBp/5zHW+x1sGjjRD69NvR9th3Z1JAYGN/BTW4he6aZFYV6kzy+k+jw==", @@ -494,7 +494,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/hosted-git-info": { + "internal/lockfile-extractor/node_modules/hosted-git-info": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-10.1.1.tgz", "integrity": "sha512-DeOnSPAvOndYKfw075gt8yZzQ7S2hNztw34zBTfhIzLhmBTswIBg5/y+pqu/VD5cYWm5goAFTusDmUEmKZ0PEQ==", @@ -507,7 +507,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/http-proxy-agent": { + "internal/lockfile-extractor/node_modules/http-proxy-agent": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-9.1.0.tgz", "integrity": "sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==", @@ -522,7 +522,7 @@ "node": ">= 20" } }, - "internal/shrinkwrap-extractor/node_modules/https-proxy-agent": { + "internal/lockfile-extractor/node_modules/https-proxy-agent": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz", "integrity": "sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==", @@ -537,7 +537,7 @@ "node": ">= 20" } }, - "internal/shrinkwrap-extractor/node_modules/ignore-walk": { + "internal/lockfile-extractor/node_modules/ignore-walk": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-9.0.0.tgz", "integrity": "sha512-tCBEZV2z2FNpIDl2vrhiWzIHzs4qOAuIDEO85eS02vZ3L1U3P56qpPL8GuGGAijDktAEaq2swMkO/Fmbo7YmfQ==", @@ -550,7 +550,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/ini": { + "internal/lockfile-extractor/node_modules/ini": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz", "integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==", @@ -560,7 +560,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/json-parse-even-better-errors": { + "internal/lockfile-extractor/node_modules/json-parse-even-better-errors": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-6.0.0.tgz", "integrity": "sha512-2/8adwnK1/+Fdjyts4r6wSpfANWw8zdNhU9U/Llk59c6O+DjSisPWPykwoL8gZmocP9Dy64S7oie2g+Mia123A==", @@ -570,7 +570,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/lru-cache": { + "internal/lockfile-extractor/node_modules/lru-cache": { "version": "11.5.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", @@ -580,7 +580,7 @@ "node": "20 || >=22" } }, - "internal/shrinkwrap-extractor/node_modules/make-fetch-happen": { + "internal/lockfile-extractor/node_modules/make-fetch-happen": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-16.0.1.tgz", "integrity": "sha512-uUv1yxHzaKVVEPfcFeGSNov/Cehjv08ovlY8ImTljgL7Q+SiA0dAYLQ6SYVa2kkKqNj4Y3aZEI7xv2teadie0A==", @@ -604,7 +604,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/minipass-fetch": { + "internal/lockfile-extractor/node_modules/minipass-fetch": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-6.0.0.tgz", "integrity": "sha512-AWI8bKapGmgx/J0E6IGYSKj8TiHebZkmKWSs8raPSw8KXwgEAJ+Bw3+LSdXHR6T/RHKAWCOYk2MiLrYluaUU6w==", @@ -622,7 +622,7 @@ "iconv-lite": "^0.7.2" } }, - "internal/shrinkwrap-extractor/node_modules/node-gyp": { + "internal/lockfile-extractor/node_modules/node-gyp": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-13.0.2.tgz", "integrity": "sha512-SXTvw3PxznpowYhJSOD9mVQBgDaCTWXffX+wQZsQ7PbcTV86TsXCUcSZhHnskFQvrvn/OdSzJPMsptT2pIj9ww==", @@ -647,7 +647,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/nopt": { + "internal/lockfile-extractor/node_modules/nopt": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-10.0.1.tgz", "integrity": "sha512-df3sBr/6ax9hSGuC3CspvLlbnX8cP5L5nZwXF8cGN8l0zSWR6BvzmQ6jPUKjvo6+/xdpkNvEcucBNUdBeeV13g==", @@ -663,7 +663,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-bundled": { + "internal/lockfile-extractor/node_modules/npm-bundled": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-6.0.0.tgz", "integrity": "sha512-EqdodKEW6pYM+dPxA66TZQfMEqVDiuzjDM9edSjuPI1mXUbUJwVxkgqMZSJvs8RTXz2CGq8HUol/AffTZX5g8w==", @@ -676,7 +676,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-install-checks": { + "internal/lockfile-extractor/node_modules/npm-install-checks": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-9.0.0.tgz", "integrity": "sha512-t05Izcgi7p15cpldqoiXYpjzlkTTvBw33sgjmL/JjcvtV0ydbm2O4iEXO8A6smqComu5FAQhUas86HTMQ6Z1Uw==", @@ -689,7 +689,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-normalize-package-bin": { + "internal/lockfile-extractor/node_modules/npm-normalize-package-bin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-6.0.0.tgz", "integrity": "sha512-tdt4aFn9QamlhdN3HV2D2ccpBwO5/fyjjbXUxYA6uBjyekMZcZvDq0aSj9t5Jo+tih6AYFnt/cuIRn9013e0Uw==", @@ -699,7 +699,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-package-arg": { + "internal/lockfile-extractor/node_modules/npm-package-arg": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-14.0.0.tgz", "integrity": "sha512-69XQh3k+dtGa1p+7RaR57IuG3rCko96xr/nUfN4yDYBXbTYICiWcOpsFKLN2GtGE9cyIljE+f1exnaYt9MvM+Q==", @@ -715,7 +715,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-packlist": { + "internal/lockfile-extractor/node_modules/npm-packlist": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-11.3.0.tgz", "integrity": "sha512-cS1yVkyriZgQAbiK8PtwhZHEtsFOsKHsCg5Ww2ONckAvXIspgqd6o4WirOzvkupU24iMRZ4xtO4kb2iK2rbnag==", @@ -730,7 +730,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-pick-manifest": { + "internal/lockfile-extractor/node_modules/npm-pick-manifest": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-12.0.0.tgz", "integrity": "sha512-8Fs3YLrnNOhrCdPNZy18MzNgVC58LTDAFzq1FdZO/p3BHeCC/coz+t4F5Pxabys8HJpyTUorMea26GkXsb4J/Q==", @@ -746,7 +746,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/npm-registry-fetch": { + "internal/lockfile-extractor/node_modules/npm-registry-fetch": { "version": "20.0.1", "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-20.0.1.tgz", "integrity": "sha512-vzc1svxw/kw1IRjFsLi6gaxe1Olqm88V0tIfu2u5raL0b1gChe6ZEXNkyUlKxUC7s/egt5NxZHkbY18tMKKLfQ==", @@ -766,7 +766,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/pacote": { + "internal/lockfile-extractor/node_modules/pacote": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/pacote/-/pacote-22.0.0.tgz", "integrity": "sha512-++VqeOZeL03uGM2MFLk96jGCSt1owBGkyFKoPr+trwNlZhCpjN2RrvwYxt8nTbs1wNMqSFYurq0TafVWkAIHig==", @@ -798,7 +798,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/parse-conflict-json": { + "internal/lockfile-extractor/node_modules/parse-conflict-json": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-6.0.0.tgz", "integrity": "sha512-JIdsITvN0yVRpYxiip9DpCduYi75AryIDSCf6ez/Yul6PV46L0B/8SxSvLiMmWiUZKopLrD1BZgexxCfufoT9w==", @@ -813,7 +813,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/proc-log": { + "internal/lockfile-extractor/node_modules/proc-log": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-7.0.0.tgz", "integrity": "sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==", @@ -823,7 +823,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/read-cmd-shim": { + "internal/lockfile-extractor/node_modules/read-cmd-shim": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-7.0.0.tgz", "integrity": "sha512-GkU4W2VYxlMQqyn9JQQm8opl/UIXRzCS7iau12zNZm//CperjtK9CtpNhIh7hzU807BSdcmJIcRWeu0LIkTkYQ==", @@ -833,7 +833,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/sigstore": { + "internal/lockfile-extractor/node_modules/sigstore": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-5.0.0.tgz", "integrity": "sha512-hJqJfoG/e4qFQaauQL00c6J6FrHLBGKtkFvW3JbTSIEFOhLrSjdSM/gWd/yUOfYo/gsERehTXGC1VZWX+9X4Dg==", @@ -851,7 +851,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/socks-proxy-agent": { + "internal/lockfile-extractor/node_modules/socks-proxy-agent": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-10.1.0.tgz", "integrity": "sha512-WlMj/67cEJ6MDI1OcsnjuYKDNDoyPCCYZ249kuuXPiMDw9F8PXkVaQ7YWu3siTydfQ/4BEZcvGzu+aYvz7dDCQ==", @@ -866,7 +866,7 @@ "node": ">= 20" } }, - "internal/shrinkwrap-extractor/node_modules/ssri": { + "internal/lockfile-extractor/node_modules/ssri": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-14.0.0.tgz", "integrity": "sha512-jQxKI0yx0ZnTKrqjKkLDV2DXkBQn3k49JVmVqDGcDwKDtGDbImD/GXsq04KD0VVzCQQ9wZJYal3RwR1GzWTSow==", @@ -879,7 +879,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/tuf-js": { + "internal/lockfile-extractor/node_modules/tuf-js": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-6.0.0.tgz", "integrity": "sha512-zlJVOIO68hmgo1//X4ENEcTGfuOTAtDPi8PsTsG+FyxD85E/ww1ZnwBbWo/yCEExGpI+Kilg7Z3qCdHX2BoJTQ==", @@ -894,17 +894,17 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/undici": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz", - "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==", + "internal/lockfile-extractor/node_modules/undici": { + "version": "8.10.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.1.tgz", + "integrity": "sha512-YQ3WlbqjYMmNpdvDH64jAgLjxuAR9+649calDWhbshYaeQGO2bR4nI94ORJmwI3J9YhoKQnpyGOK+0zlWS5N5Q==", "dev": true, "license": "MIT", "engines": { "node": ">=22.19.0" } }, - "internal/shrinkwrap-extractor/node_modules/validate-npm-package-name": { + "internal/lockfile-extractor/node_modules/validate-npm-package-name": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-8.0.0.tgz", "integrity": "sha512-SCv6OOV6Xj2/3cXy3dGmADluJTNcL3o7hZAglNPTe+WYuEuvxgJzxPrSDLZhF+CwyQOubqgecjMmTJGMVLWjYQ==", @@ -914,7 +914,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/which": { + "internal/lockfile-extractor/node_modules/which": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/which/-/which-7.0.0.tgz", "integrity": "sha512-RancgH2dmbLdHl6LRhEqvklWMgl/Hdnun0Y90KhBOLkMefg8Qa7/Zel8Sm+8HEcP6DEjzsWzpkuBQEZok58isA==", @@ -930,7 +930,7 @@ "node": "^22.22.2 || ^24.15.0 || >=26.0.0" } }, - "internal/shrinkwrap-extractor/node_modules/write-file-atomic": { + "internal/lockfile-extractor/node_modules/write-file-atomic": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-8.0.0.tgz", "integrity": "sha512-dYwyZredl67GyLLIHJnRM3h2PcOmN5SkcgC7eM5DPDEOEl6dLFqVrMg3F1Ea32usj4VSVZtd2H4MtKTNOf6nPg==", @@ -6162,6 +6162,10 @@ "resolved": "packages/fs", "link": true }, + "node_modules/@ui5/lockfile-extractor": { + "resolved": "internal/lockfile-extractor", + "link": true + }, "node_modules/@ui5/logger": { "resolved": "packages/logger", "link": true @@ -6174,10 +6178,6 @@ "resolved": "packages/server", "link": true }, - "node_modules/@ui5/shrinkwrap-extractor": { - "resolved": "internal/shrinkwrap-extractor", - "link": true - }, "node_modules/@ungap/structured-clone": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", @@ -19804,6 +19804,23 @@ "packages/cli": { "name": "@ui5/cli", "version": "5.0.0-alpha.9", + "bundleDependencies": [ + "@ui5/builder", + "@ui5/fs", + "@ui5/logger", + "@ui5/project", + "@ui5/server", + "chalk", + "data-with-position", + "import-local", + "js-yaml", + "open", + "pretty-hrtime", + "semver", + "update-notifier", + "yargs", + "yesno" + ], "license": "Apache-2.0", "dependencies": { "@ui5/builder": "^5.0.0-alpha.9", @@ -19847,6 +19864,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-6.0.0.tgz", "integrity": "sha512-2uNTXIuTTxk7ciZgAU1BQcgnchcG0xXnrs6jzkQfj9SsRa9M2s5zE8WT96hS6KmG4MzWHSrvH43DF1m4XRkrFg==", + "inBundle": true, "license": "MIT", "engines": { "node": ">=22" @@ -19859,6 +19877,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "inBundle": true, "license": "ISC", "dependencies": { "string-width": "^7.2.0", @@ -19873,6 +19892,7 @@ "version": "18.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.1.0.tgz", "integrity": "sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==", + "inBundle": true, "license": "MIT", "dependencies": { "cliui": "^9.0.1", @@ -19890,6 +19910,7 @@ "version": "22.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "inBundle": true, "license": "ISC", "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" @@ -19899,6 +19920,7 @@ "version": "8.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.2.tgz", "integrity": "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==", + "inBundle": true, "license": "MIT", "dependencies": { "get-east-asian-width": "^1.5.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index 85bc4a965c2..e52b8bc8d32 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -40,11 +40,11 @@ }, "files": [ "CHANGELOG.md", - "npm-shrinkwrap.json", "bin/**", "lib/**", "LICENSES/**" ], + "bundleDependencies": true, "repository": { "type": "git", "url": "git+ssh://git@github.com/UI5/cli.git",